{"openapi":"3.1.0","info":{"title":"v3","version":"3"},"x-canonical-resources":{"description":"The resource a permission rule for an operation is granted on. Every operation's x-canonical-resource names an entry here, and every entry is named by at least one operation. An entry with a definition is a curated resource: its key is a snake_case entity name, or the path root it replaced when consumers already used that root. An entry without a definition is a placeholder that keeps the API's own path-root spelling until it is curated. scripts/lint_canonical_resources.py enforces all of this.","resources":{"accountContacts":{"label":"Account contacts"},"account_user":{"label":"Account user","definition":"A login/user who can access the ActiveCampaign tenant"},"activecampaign_account":{"label":"ActiveCampaign account","definition":"The customer's hosted ActiveCampaign tenant and tenant-level settings"},"activity":{"label":"Activity","definition":"A recorded activity"},"addressGroups":{"label":"Address groups"},"addressLists":{"label":"Address lists"},"addresses":{"label":"Addresses"},"automation":{"label":"Automation","definition":"An automated workflow of triggers and actions that contacts enter and move through"},"brand_kit":{"label":"Brand Kit","definition":"A customer's Brand Kit: name, colors, fonts, tone, and other identity fields used to personalize generated content"},"brandings":{"label":"Brandings"},"business_goal":{"label":"Business goal","definition":"An Initiative: a business goal a customer tracks progress against, with associated conversion targets."},"calendars":{"label":"Calendars"},"campaign":{"label":"Campaign","definition":"A campaign record and its campaign-level fields"},"campaign_message":{"label":"Campaign message","definition":"The relationship that identifies messages belonging to a campaign"},"connections":{"label":"Connections"},"contact":{"label":"Contact","definition":"A subscriber/person record managed by the tenant"},"contactAutomations":{"label":"Contact automation","definition":"One contact's entry into an automation and its path through it"},"contactDeals":{"label":"Contact deals"},"contactLists":{"label":"Contact lists"},"contactTags":{"label":"Contact tags"},"content":{"label":"Content"},"content_manager_file":{"label":"Content manager file","definition":"A file, such as an image or a PDF, stored in the account's Content Manager and shared with every user on the account"},"content_manager_folder":{"label":"Content manager folder","definition":"A custom folder that organizes files in the account's Content Manager"},"conversion":{"label":"Conversion","definition":"A tracked event or action with an optional dollar value, used to measure campaign/automation effectiveness"},"conversion_label":{"label":"Conversion label","definition":"The association between a conversion and a label/folder, optionally carrying a business-goal target"},"conversion_trigger":{"label":"Conversion trigger","definition":"A rule that fires a conversion for a contact -- by segment membership, a URL visit, a named event, a manual call, an automation/goal step, or an ecommerce order"},"crm_account":{"label":"CRM account","definition":"A company or organization record associated with contacts"},"custom_field_definition":{"label":"Custom field definition","definition":"Metadata describing a field"},"custom_field_value":{"label":"Custom field value","definition":"A value stored for a specific record and field definition"},"custom_object_record":{"label":"Custom object record","definition":"A custom object record: one item stored under a custom object schema, with values for that schema's fields"},"custom_object_schema":{"label":"Custom object schema","definition":"A custom object schema: the definition of a custom object type, its fields and its relationships to other records"},"deal":{"label":"Deal","definition":"A sales opportunity record managed in a pipeline"},"dealActivities":{"label":"Deal activities"},"dealGroup":{"label":"Deal group"},"dealGroups":{"label":"Deal groups"},"dealRoles":{"label":"Deal roles"},"dealStages":{"label":"Deal stages"},"dealTasktypes":{"label":"Deal task types"},"deal_task":{"label":"Deal task","definition":"A task associated with a deal"},"ecomCustomers":{"label":"Ecom customers"},"ecomOrderProducts":{"label":"Ecom order products"},"ecomOrders":{"label":"Ecom orders"},"emailActivities":{"label":"Email activities"},"eventTracking":{"label":"Event tracking"},"eventTrackingEvents":{"label":"Event tracking events"},"fieldOption":{"label":"Field option"},"fieldRels":{"label":"Field relationships"},"forms":{"label":"Forms"},"geoIps":{"label":"Geo ips"},"group":{"label":"Group"},"groupDefinitions":{"label":"Group definitions"},"groupLimits":{"label":"Group limits"},"groupMembers":{"label":"Group members"},"groups":{"label":"Groups"},"import":{"label":"Import"},"legacy_segment":{"label":"Legacy segment","definition":"A segment represented by legacy /segments operations"},"listGroups":{"label":"List groups"},"lists":{"label":"Lists"},"localevent":{"label":"Local event"},"message":{"label":"Message","definition":"The message record referenced by a campaign-message association"},"note":{"label":"Note","definition":"A note attached to a contact, deal, deal task, activity, or CRM account"},"personalizations":{"label":"Personalization tags","definition":"A personalization tag: a placeholder that inserts a contact's own data into campaign and message content when it is sent"},"savedResponses":{"label":"Saved responses"},"saved_segment_summaries":{"label":"Saved Segment Summaries","definition":"Saved Segment Summaries contain a high level view of a Saved Segment. Saved Segment Summaries can be listed or searched for by Segment Name via /audiences. Segment definitions returned by /segmentsV2 that have a name attribute are saved segments."},"segments":{"label":"Segments","definition":"A segment definition comprising conditions and condition groups. Segments can be created, retrieved, updated, or deleted via /segmentsV2. A segment with a name attribute is a saved segment and its summary can be retrieved via /audiences."},"segment_match_requests":{"label":"Segment Match Requests","definition":"Segment Match Requests show which contact(s) satisfy the segment and any Additional Criteria provided. Segments can be evaluated against a single contact or all matching contacts can be identified. Each unique Segment Match Request returns a RunId. Match Results persist for 90 days and can be referenced at any time using the request's RunId"},"scores":{"label":"Scores"},"segment_membership":{"label":"Segment membership","definition":"A request that evaluates whether contacts match segment criteria"},"siteTracking":{"label":"Site tracking"},"siteTrackingDomains":{"label":"Site tracking domains"},"sms_broadcast":{"label":"SMS","definition":"An SMS broadcast message, its recipients and its delivery metrics"},"sms_conversation":{"label":"SMS conversation","definition":"A conversation with a contact in the SMS inbox, and the messages exchanged in it"},"sms_credits":{"label":"SMS credits","definition":"The account's SMS sending allowance for the current period"},"sms_registration":{"label":"SMS sender registration","definition":"An account's SMS sender registration: 10DLC brand and campaign forms, country bundle and toll-free registrations, and the phone numbers they provision"},"tags":{"label":"Tags"},"taskNotifications":{"label":"Task notifications"},"taskOutcomes":{"label":"Task outcomes"},"tasktypeOutcomeRels":{"label":"Task type outcomes"},"templates":{"label":"Templates"},"tracked_event":{"label":"Tracked event","definition":"An event occurrence recorded through event tracking"},"web_content":{"label":"Web content","definition":"Content retrieved from the public web on an AI agent's behalf: a scraped page, web search results, or the URLs discovered on a site"},"webhook_event_type":{"label":"Webhook event type","definition":"A configured webhook event category, not an occurrence log"},"webhooks":{"label":"Webhooks"},"whatsapp_conversation":{"label":"WhatsApp conversation","definition":"A conversation with a contact in the WhatsApp inbox, and the status tracking its progress"},"whatsapp_flow":{"label":"WhatsApp flow","definition":"One run of a WhatsApp Messaging flow: the automated conversation it ran and the contacts it took through it"},"whatsapp_message":{"label":"WhatsApp message","definition":"A single WhatsApp message sent to a contact from an approved template"},"whatsapp_template":{"label":"WhatsApp template","definition":"A pre-made WhatsApp message that Meta must approve before it is sent, with its category, content and variables"},"automation_group":{"label":"Automation group permission","definition":"The grant that lets one user group see and work with one automation"},"automation_label":{"label":"Automation label","definition":"The association between an automation and a label/folder"},"channel_connection":{"label":"Channel connection","definition":"A messaging channel account, such as an Instagram account, that the tenant has connected to Engage through the provider's OAuth flow"},"currencies":{"label":"Currencies"},"deal_connection":{"label":"Deal connection","definition":"A user's mailbox connected to the CRM through Nylas, used to sync and send deal emails"},"email_account":{"label":"Subscription by email account","definition":"A POP3 mailbox or piped address whose incoming mail subscribes or unsubscribes the sender to the tenant's lists"},"form_label":{"label":"Form label","definition":"The association between a form and a label/folder"},"postmark":{"label":"Postmark"},"push_registration":{"label":"Mobile push registration","definition":"A mobile device registered to receive the ActiveCampaign app's push notifications"},"site_message":{"label":"Site message","definition":"An on-site message an automation shows to a contact on the customer's tracked website, with its content, display position and delivery queue"},"product_idea":{"label":"Product idea","definition":"An idea or problem a user of the tenant shared with ActiveCampaign from inside the app, and who on the tenant follows it"},"report":{"label":"Report","definition":"An analytics report or dashboard the tenant views in the app, including embedded Looker reports and the sessions that open them"},"agent_consumption":{"label":"Agent consumption","definition":"The account's usage of its AI allowance, reported by the AI features that draw on it"},"agent_file_summary":{"label":"Agent file summary","definition":"A summary of a file, from a conversation or saved as an account resource, that the AI agent uses as context"},"agent_memory":{"label":"Agent memory","definition":"A fact the AI agent remembers about the account and uses in later conversations"},"agent_permission_rule":{"label":"Agent permission rule","definition":"A rule that allows or restricts an action the AI agent may take on a user's behalf"},"agent_settings":{"label":"Agent settings","definition":"The account-level settings that control how the AI agent behaves, such as whether conversation uploads become account resources"},"agent_user_profile":{"label":"Agent user profile","definition":"The profile the AI agent builds and refreshes for a user to personalize its responses"},"custom_instruction":{"label":"Custom instruction","definition":"An instruction the account gives the AI agent to steer how it responds"},"label":{"label":"Label","definition":"A label (folder) that can be put on automations, forms, campaigns, conversions and SMS broadcasts to group them"}}},"x-mcp-tool-rules":"2026.10.3","x-mcp-tool-names-lock":{"lock_version":1,"entries":[{"name":"list_automation_runs","key":"GET /agents/mcp-gateway/automation-generation/runs","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"poll_automation_generation_status","key":"GET /agents/mcp-gateway/automation-generation/runs/{}","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"get_campaign_generation_context","key":"GET /agents/mcp-gateway/campaign-generation/context","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"list_campaign_runs","key":"GET /agents/mcp-gateway/campaign-generation/runs","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"poll_campaign_generation_status","key":"GET /agents/mcp-gateway/campaign-generation/runs/{}","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"list_campaign_templates","key":"GET /agents/mcp-gateway/campaign-generation/templates","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"generate_automation","key":"POST /agents/mcp-gateway/automation-generation/generate","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"cancel_automation_run","key":"POST /agents/mcp-gateway/automation-generation/runs/{}/cancel","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"copy_campaign","key":"POST /agents/mcp-gateway/campaign-generation/copy","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"edit_campaign","key":"POST /agents/mcp-gateway/campaign-generation/edit","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"generate_campaign","key":"POST /agents/mcp-gateway/campaign-generation/generate","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"get_campaign_history","key":"POST /agents/mcp-gateway/campaign-generation/history","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"import_campaign_design","key":"POST /agents/mcp-gateway/campaign-generation/import","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"redo_campaign_version","key":"POST /agents/mcp-gateway/campaign-generation/redo","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"restore_campaign_version","key":"POST /agents/mcp-gateway/campaign-generation/restore","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"cancel_campaign_run","key":"POST /agents/mcp-gateway/campaign-generation/runs/{}/cancel","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"manage_campaign_template","key":"POST /agents/mcp-gateway/campaign-generation/templates/manage","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"save_campaign_as_template","key":"POST /agents/mcp-gateway/campaign-generation/templates/save","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"set_campaign_audience","key":"POST /agents/mcp-gateway/campaign-send/audience","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"confirm_campaign_schedule","key":"POST /agents/mcp-gateway/campaign-send/schedule/confirm","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"prepare_campaign_schedule","key":"POST /agents/mcp-gateway/campaign-send/schedule/prepare","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"confirm_campaign_send","key":"POST /agents/mcp-gateway/campaign-send/send/confirm","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"prepare_campaign_send","key":"POST /agents/mcp-gateway/campaign-send/send/prepare","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"unschedule_campaign","key":"POST /agents/mcp-gateway/campaign-send/unschedule","service":"ac-agents","first_delivered":"2026-10-27","delivered_in":"a07d02d313734faa72bc300b50d336888ab0fd4d"},{"name":"list_account_contacts","key":"GET /accountContacts","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_account_custom_field_values","key":"GET /accountCustomFieldData","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_account_custom_fields","key":"GET /accountCustomFieldMeta","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_accounts","key":"GET /accounts","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"get_account","key":"GET /accounts/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_deal_custom_field_values","key":"GET /dealCustomFieldData","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_deal_custom_fields","key":"GET /dealCustomFieldMeta","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_deal_roles","key":"GET /dealRoles","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_tasks","key":"GET /dealTasks","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"get_task","key":"GET /dealTasks/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_task_types","key":"GET /dealTasktypes","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_notes","key":"GET /notes","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_saved_responses","key":"GET /savedResponses","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"get_saved_response","key":"GET /savedResponses/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"list_task_outcomes","key":"GET /taskOutcomes","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"link_contact_to_account","key":"POST /accountContacts","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"set_account_custom_field_value","key":"POST /accountCustomFieldData","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"create_account_custom_field","key":"POST /accountCustomFieldMeta","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"create_account","key":"POST /accounts","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"create_account_note","key":"POST /accounts/{}/notes","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"add_contact_to_deal","key":"POST /contactDeals","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"set_deal_custom_field_value","key":"POST /dealCustomFieldData","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"create_deal_custom_field","key":"POST /dealCustomFieldMeta","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"create_task","key":"POST /dealTasks","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"update_account_custom_field_value","key":"PUT /accountCustomFieldData/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"update_account","key":"PUT /accounts/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"update_deal_custom_field_value","key":"PUT /dealCustomFieldData/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"update_task","key":"PUT /dealTasks/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"},{"name":"update_note","key":"PUT /notes/{}","service":"hosted","first_delivered":"2026-10-28","delivered_in":"99c61b529a53a2f9a3bde236cdbd4181f06eec04"}]},"x-mcp-tool-profiles":{"account":"hosted-api3@1","accountContacts":"hosted-api3@1","accountCustomFieldData":"hosted-api3@1","accountCustomFieldMeta":"hosted-api3@1","accountOpenTrends":"hosted-api3@1","accounts":"hosted-api3@1","activities":"hosted-api3@1","activityRecipients":"hosted-api3@1","addressGroups":"hosted-api3@1","addressLists":"hosted-api3@1","addresses":"hosted-api3@1","aggregateRevenue":"hosted-api3@1","ai":"hosted-api3@1","alerts":"hosted-api3@1","ambassador":"hosted-api3@1","assetMigration":"hosted-api3@1","automation":"hosted-api3@1","automationConnections":"hosted-api3@1","automationGroups":"hosted-api3@1","automationLabels":"hosted-api3@1","automationRelations":"hosted-api3@1","automationStarts":"hosted-api3@1","automations":"hosted-api3@1","automationsProcess":"hosted-api3@1","bounceLogs":"hosted-api3@1","bounces":"hosted-api3@1","brandings":"hosted-api3@1","businessGoals":"hosted-api3@1","calendarRel":"hosted-api3@1","calendarUser":"hosted-api3@1","calendars":"hosted-api3@1","campaign":"hosted-api3@1","campaignDomainValidation":"hosted-api3@1","campaignLanguages":"hosted-api3@1","campaignMessages":"hosted-api3@1","campaignReport":"hosted-api3@1","campaigns":"hosted-api3@1","canduConfig":"hosted-api3@1","channel":"hosted-api3@1","configs":"hosted-api3@1","connection":"hosted-api3@1","connections":"hosted-api3@1","contact":"hosted-api3@1","contactArchives":"hosted-api3@1","contactAutomation":"hosted-api3@1","contactAutomationLogs":"hosted-api3@1","contactAutomationStats":"hosted-api3@1","contactAutomations":"hosted-api3@1","contactConversionPoints":"hosted-api3@1","contactConversionSources":"hosted-api3@1","contactConversions":"hosted-api3@1","contactData":"hosted-api3@1","contactDeals":"hosted-api3@1","contactEmails":"hosted-api3@1","contactGoalLists":"hosted-api3@1","contactGoalTags":"hosted-api3@1","contactGoals":"hosted-api3@1","contactImports":"hosted-api3@1","contactLists":"hosted-api3@1","contactLogs":"hosted-api3@1","contactPerformance":"hosted-api3@1","contactSettings":"hosted-api3@1","contactTags":"hosted-api3@1","contacts":"hosted-api3@1","content":"hosted-api3@1","content-proxy":"hosted-api3@1","conversion":"hosted-api3@1","conversionSegmentTrigger":"hosted-api3@1","conversionTrigger":"hosted-api3@1","conversionTriggers":"hosted-api3@1","conversions":"hosted-api3@1","currencies":"hosted-api3@1","customObjects":"hosted-api3@1","dataLookups":"hosted-api3@1","dealActivities":"hosted-api3@1","dealConnections":"hosted-api3@1","dealCustomFieldData":"hosted-api3@1","dealCustomFieldMeta":"hosted-api3@1","dealEmail":"hosted-api3@1","dealGroup":"hosted-api3@1","dealGroups":"hosted-api3@1","dealRoles":"hosted-api3@1","dealStage":"hosted-api3@1","dealStages":"hosted-api3@1","dealTasks":"hosted-api3@1","dealTasktypes":"hosted-api3@1","deals":"hosted-api3@1","deductEmailTestCredit":"hosted-api3@1","ecomCustomerProps":"hosted-api3@1","ecomCustomers":"hosted-api3@1","ecomData":"hosted-api3@1","ecomOrderProducts":"hosted-api3@1","ecomOrders":"hosted-api3@1","emailAccounts":"hosted-api3@1","emailActivities":"hosted-api3@1","ember":"hosted-api3@1","enableReadTracking":"hosted-api3@1","eventTracking":"hosted-api3@1","eventTrackingEvents":"hosted-api3@1","exclusions":"hosted-api3@1","field":"hosted-api3@1","fieldDetails":"hosted-api3@1","fieldOption":"hosted-api3@1","fieldOptions":"hosted-api3@1","fieldRel":"hosted-api3@1","fieldRels":"hosted-api3@1","fieldValues":"hosted-api3@1","fields":"hosted-api3@1","form":"hosted-api3@1","formLabels":"hosted-api3@1","forms":"hosted-api3@1","geoAddresses":"hosted-api3@1","geoIps":"hosted-api3@1","globalData":"hosted-api3@1","goal":"hosted-api3@1","goals":"hosted-api3@1","group":"hosted-api3@1","groupDefinitions":"hosted-api3@1","groupLimits":"hosted-api3@1","groupMembers":"hosted-api3@1","groupTypesSync":"hosted-api3@1","groups":"hosted-api3@1","ideas":"hosted-api3@1","import":"hosted-api3@1","importsettings":"hosted-api3@1","industryOpenTrends":"hosted-api3@1","init":"hosted-api3@1","initiatives":"hosted-api3@1","kafka":"hosted-api3@1","labels":"hosted-api3@1","landingPages":"hosted-api3@1","legacyEngage":"hosted-api3@1","listGroups":"hosted-api3@1","lists":"hosted-api3@1","localevent":"hosted-api3@1","looker":"hosted-api3@1","lookupFields":"hosted-api3@1","message":"hosted-api3@1","messages":"hosted-api3@1","microsoftDynamics":"hosted-api3@1","notes":"hosted-api3@1","notification":"hosted-api3@1","nylas":"hosted-api3@1","outboundemail":"hosted-api3@1","overview":"hosted-api3@1","performance":"hosted-api3@1","persTags":"hosted-api3@1","personalizations":"hosted-api3@1","platform":"hosted-api3@1","plusAppend":"hosted-api3@1","plusAppends":"hosted-api3@1","postmark":"hosted-api3@1","preferenceCenterData":"hosted-api3@1","prism":"hosted-api3@1","pushUnregister":"hosted-api3@1","salesforce":"hosted-api3@1","savedResponse":"hosted-api3@1","savedResponses":"hosted-api3@1","scores":"hosted-api3@1","scribeConfig":"hosted-api3@1","segmentcom":"hosted-api3@1","segments":"hosted-api3@1","settings":"hosted-api3@1","siteMessage":"hosted-api3@1","siteTracking":"hosted-api3@1","siteTrackingDomains":"hosted-api3@1","sms":"hosted-api3@1","statsActivityItem":"hosted-api3@1","stripo":"hosted-api3@1","subscriberEmails":"hosted-api3@1","syncs":"hosted-api3@1","tags":"hosted-api3@1","taskNotifications":"hosted-api3@1","taskOutcomes":"hosted-api3@1","tasktypeOutcomeRels":"hosted-api3@1","templates":"hosted-api3@1","tracking":"hosted-api3@1","trackingLogs":"hosted-api3@1","updates":"hosted-api3@1","userStates":"hosted-api3@1","users":"hosted-api3@1","vega":"hosted-api3@1","webhook":"hosted-api3@1","webhookTest":"hosted-api3@1","webhooks":"hosted-api3@1","whatsapp":"hosted-api3@1","whatsappPrimaryInbox":"hosted-api3@1","zendesk":"hosted-api3@1"},"servers":[{"url":"https://{youraccountname}.api-us1.com/api/3","variables":{"youraccountname":{"default":"youraccountname"}}}],"components":{"securitySchemes":{"sec0":{"type":"apiKey","name":"Api-Token","in":"header","x-default":""}},"schemas":{"ACHQFranchisor":{"description":"A franchisor account and the franchisee accounts linked to it, as jsonSerialize() writes it. The stored API key is never returned.","required":["accountId","apiUrl","createdTimestamp","updatedTimestamp","franchisees"],"properties":{"accountId":{"description":"ID of the franchisor account.","type":"integer","example":1001},"apiUrl":{"description":"Base URL of the franchisor's ACHQ API. Hosted calls it, with the stored API key, to submit franchisee campaigns for approval and to send template, personalization and automation webhooks.","type":"string","example":"https://franchisor.api-us1.com"},"createdTimestamp":{"description":"When the franchisor was registered, as a database date and time (Y-m-d H:i:s).","type":"string","example":"2026-01-15 10:30:00"},"updatedTimestamp":{"description":"When the franchisor was last changed, as a database date and time (Y-m-d H:i:s).","type":"string","example":"2026-01-15 10:30:00"},"franchisees":{"description":"The franchisee accounts linked to this franchisor; empty when there are none.","type":"array","items":{"$ref":"#/components/schemas/FranchiseeAccountMapping"}}},"type":"object"},"AIBroadcastCreateRequest":{"type":"object","required":["source","prompt","tone"],"properties":{"source":{"type":"string","enum":["ai_index","sms_index","ai_builder"],"description":"Origin point of the AI broadcast request"},"prompt":{"type":"string","description":"Instruction text directing the AI content generation"},"tone":{"type":"string","description":"Desired stylistic tone for the generated message"}}},"AIBroadcastRequestResponse":{"type":"object","properties":{"requestId":{"type":"string","description":"Tracking identifier for the AI broadcast request"}}},"AIBroadcastStatus":{"type":"object","properties":{"source":{"type":"string","enum":["ai_index","sms_index","ai_builder"],"description":"Origin point of the AI broadcast request"},"status":{"type":"string","enum":["in_progress","error","success"],"description":"Current execution state of the AI broadcast request"},"broadcastId":{"type":"integer","nullable":true,"description":"Identifier of the broadcast once available"}}},"AIBroadcastUpdateRequest":{"type":"object","required":["source","prompt","tone","broadcastId"],"properties":{"source":{"type":"string","enum":["ai_index","sms_index","ai_builder"],"description":"Origin point of the AI broadcast request"},"prompt":{"type":"string","description":"Instruction text directing the AI content generation"},"tone":{"type":"string","description":"Desired stylistic tone for the generated message"},"broadcastId":{"type":"integer","description":"Identifier of the broadcast to update"}}},"AccountContactHttpError":{"type":"object","properties":{"errors":{"description":"One entry describing the error.","type":"array","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code."},"title":{"type":"string","description":"The HTTP status text, such as Forbidden."},"detail":{"type":"string","description":"What went wrong."}}}}}},"AccountContactValidationErrors":{"type":"object","properties":{"errors":{"type":"array","description":"One entry for each problem found.","items":{"type":"object","properties":{"title":{"type":"string","description":"What is wrong, in English."},"detail":{"type":"string","description":"Always empty here."},"code":{"type":"string","description":"field_missing when account or contact was not sent, related_missing when no account or contact has that id, field_invalid for the other problems."},"error":{"type":"string","description":"A machine-readable code for a missing or unknown account or contact, such as accountContact_account_was_not_provided or account_not_exist. Empty for the other problems."},"source":{"description":"Where the problem is.","type":"object","properties":{"pointer":{"type":"string","description":"The field the problem is about: /data/attributes/account, /data/attributes/contact, or /data/attributes/account,contact for the pair."}}}}}}}},"AccountCustomFieldMetaBulkErrors":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":["integer","string"],"description":"HTTP status code. A number, except when the user lacks the permission, where it is a string."},"title":{"type":"string","description":"Missing when the user lacks the permission."},"detail":{"type":"string","description":"Only when the user lacks the permission."}}}}}},"AccountCustomFieldMetaBulkUpdateItem":{"type":"object","description":"Changes for one field. Keys can be camelCase or snake_case.","properties":{"id":{"type":["integer","string"],"description":"Id of the field to update."},"fieldLabel":{"type":"string","description":"Name of the field."},"fieldOptions":{"type":["array","object"],"description":"Options for the field, as for PUT /accountCustomFieldMeta/{id}.","items":{"type":"string"}},"fieldDefault":{"type":["string","array"],"description":"Default value of the field.","items":{"type":"string"}},"isFormVisible":{"type":["boolean","integer"],"description":"Whether the field is visible on forms."},"isRequired":{"type":["boolean","integer"],"description":"Whether the field is required."},"displayOrder":{"type":"integer","description":"Order of the field on the Manage Fields page."},"personalization":{"type":"string","description":"Personalization tag of the field."}},"additionalProperties":true},"AccountEntitlement":{"type":"object","description":"One entitlement of the account's plan.","required":["code"],"properties":{"code":{"type":"string","description":"Code of the entitlement.","example":"sms-credits"},"limit":{"type":"object","description":"The entitlement's limit. Left out when the entitlement has none. Members depend on the entitlement.","properties":{"type":{"type":"string","description":"Kind of limit, for example capacity or consumptive.","example":"consumptive"},"allowed":{"type":"integer","description":"Amount the plan allows.","example":500},"period":{"type":"string","description":"Period a consumptive limit resets over, when it has one.","example":"month"}}}}},"AccountInstructionContent":{"description":"The text of the account instruction, as it was saved.","required":["content"],"properties":{"content":{"description":"The instruction the AI agent follows for everyone on the account.","type":"string","example":"Always write in a friendly, concise tone and sign off with the team name."}},"type":"object"},"AccountInstructionRecord":{"description":"The instruction the account has given the AI agent.","required":["type","instructions","updated_at"],"properties":{"type":{"description":"Always account: the instruction applies to the whole account.","type":"string","enum":["account"],"example":"account"},"instructions":{"description":"The saved instruction. Always holds exactly one item.","type":"array","items":{"$ref":"#/components/schemas/AccountInstructionContent"}},"updated_at":{"description":"When the instruction was last saved, as YYYY-MM-DD HH:MM:SS. The value carries no time zone.","type":"string","example":"2026-10-19 09:30:00"}},"type":"object"},"ActionRequestMethodEnum":{"enum":["GET","POST","PUT","PATCH","DELETE"],"type":"string","description":"* `GET` - Get\n* `POST` - Post\n* `PUT` - Put\n* `PATCH` - Patch\n* `DELETE` - Delete"},"Activity":{"type":"object","description":"One activity entry, in the same shape as activity in GET /activities/{id}.","properties":{"tstamp":{"type":["string","null"],"description":"When the event happened, as an ISO 8601 date with offset."},"subscriberid":{"type":["string","null"],"description":"The contact id."},"reference_type":{"type":"string","description":"The kind of event. GET /activities explains what each value means."},"reference_id":{"type":"string","description":"The id of the underlying record."},"reference_action":{"type":"string","description":"The sub-kind where a type has several, as listed for GET /activities. Empty when the type has none."},"jsonData":{"description":"Extra data for some types, as a JSON string or null."},"userid":{"type":"string","description":"The account user who caused the event, when one did."},"permission":{"type":"string","description":"The permission that gates this entry in GET /activities: empty, or pg_deal."},"referenceModelName":{"type":"string","description":"The API type name of the underlying record."},"links":{"type":"object","description":"URLs of the related reads for this entry: user, recipients, reference and notes, each at /activities/{id}/<name>."},"id":{"type":"string","description":"The activity entry id."},"user":{"type":["string","null"],"description":"The id of the account user who caused the event, the same value as userid. Null when no user did."},"reference":{"type":["object","null"],"description":"The underlying record as a type and id pair: type is the same value as referenceModelName, id the same as reference_id. Null when the entry has no underlying record."}}},"ActivityFeedEntry":{"description":"One AI customization change made by the calling user: an account instruction, memory, file, brand kit or permission rule that was added, changed or removed.","required":["action","title","description","snippet","brand_id","file_id","user_name","user_id","timestamp"],"properties":{"action":{"description":"What happened, as a fixed event type.","type":"string","enum":["account-instruction-created","account-instruction-updated","account-instruction-deleted","memory-detected","memory-deleted","file-added","file-updated","file-deleted","brand-added","brand-edited","brand-deleted","permission-rule-created","permission-rule-updated","permission-rule-deleted"],"example":"memory-detected"},"title":{"description":"Heading for the entry, translated into the account's language; the fixed name of the event type when no translation is found. The three account-instruction events share one heading (\"Instructions edited\").","type":"string","example":"Memory detected"},"description":{"description":"Longer text for the entry, translated into the account's language when the event type has a translation (the snippet is offered to it as %name%); otherwise the fixed name of the event type, so for most event types it equals title. Empty for an event type this version does not know.","type":"string","example":"Memory detected"},"snippet":{"description":"Short excerpt of the changed item recorded with the event (a memory's text, an instruction, a brand kit or file name). Empty when the event recorded none.","type":"string","example":"Always respond in a friendly tone"},"brand_id":{"description":"UUID of the brand kit the event is about, for brand-added, brand-edited and brand-deleted; null for every other event type.","type":["string","null"],"example":null},"file_id":{"description":"ID of the resource file the event is about, for file-added, file-updated and file-deleted; null for every other event type.","type":["integer","null"],"example":null},"user_name":{"description":"First and last name of the user who made the change. Empty when the user no longer exists.","type":"string","example":"John Smith"},"user_id":{"description":"ID of the user who made the change. Always the calling user, because the feed only lists their own changes.","type":"integer","example":42},"timestamp":{"description":"When the change was recorded, as YYYY-MM-DD HH:MM:SS in the server's time zone, with no zone designator.","type":"string","example":"2026-02-16 14:30:00"}},"type":"object"},"ActivityFeedHistoryResponse":{"description":"One page of the calling user's AI customization history, newest first.","required":["meta","history"],"properties":{"meta":{"description":"Totals for the whole feed, not just this page.","required":["total"],"properties":{"total":{"description":"Number of entries in the whole feed for the calling user, before limit and offset. 0 when the user has made no AI customization change yet.","type":"integer","example":37}},"type":"object"},"history":{"description":"The requested page, newest first. Empty when offset is past the end or total is 0.","type":"array","items":{"$ref":"#/components/schemas/ActivityFeedEntry"}}},"type":"object"},"ActivityFeedValidationError":{"description":"One error in an ActivityFeedValidationErrorResponse.","required":["status","title","detail","source"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed: \"Limit must be digits-only\", \"Limit must be a positive integer\" or \"Offset must be a non-negative integer\". The digits-only message is also used for offset.","type":"string","example":"Limit must be a positive integer"},"source":{"description":"The query parameter that failed the check.","required":["pointer"],"properties":{"pointer":{"description":"The parameter, as /data/attributes/limit or /data/attributes/offset.","type":"string","example":"/data/attributes/limit"}},"type":"object"}},"type":"object"},"ActivityFeedValidationErrorResponse":{"description":"Error body for a limit or offset that fails validation.","required":["errors"],"properties":{"errors":{"description":"One error per failed check; a parameter can fail more than one, for example an omitted limit fails both the digits-only and the positive-integer checks.","type":"array","items":{"$ref":"#/components/schemas/ActivityFeedValidationError"}}},"type":"object"},"ActivityRecipient":{"type":"object","description":"One activity recipient record: the link between an activity entry and a contact.","properties":{"reltype":{"type":"string","description":"Type of the recipient record. Records are written with Subscriber, which is a contact."},"relid":{"type":"string","description":"Id of the contact."},"activityid":{"type":"string","description":"Id of the activity entry. Use it with GET /activities/{id}."},"links":{"type":"object","description":"URLs of the record's related reads: recipient and activity, each at /activityRecipients/{id}/<name>."},"id":{"type":"string","description":"Id of the record."},"recipient":{"type":["object","null"],"description":"The contact as a type and id pair. Null when relid is 0.","properties":{"type":{"type":"string","description":"API type of the recipient: contact."},"id":{"type":"string","description":"Id of the contact. Same value as relid."}}},"activity":{"type":["string","null"],"description":"Id of the activity entry. Same value as activityid. Null when activityid is 0."}}},"AdditionalCriteriaDO":{"title":"AdditionalCriteriaDO","type":"object","required":["conditions","group_operator"],"properties":{"external_id":{"type":"string","description":"Value to inject for any FieldDO's that have external set to `True`","example":"1504"},"limit":{"type":"integer","description":"Maximum number of matches in the result-set","minimum":1,"maximum":10000},"segment_relationship":{"description":"Used to determine how the conditions should be conjoined with the segment conditions. Only required when OR'ing such that: `thisAdditionalCriteriaCondition or theSegmentConditions","type":"string","enum":["or"]},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/ConditionDO"}},"condition_groups":{"type":"array","items":{"$ref":"#/components/schemas/ConditionGroupDO"}},"group_operator":{"type":"string","enum":["and","or"]}}},"AdditionalCriteriaElementDO":{"title":"AdditionalCriteriaElementDO","type":"object","properties":{"attributes":{"$ref":"#/components/schemas/AdditionalCriteriaDO"},"type":{"type":"string","enum":["additionalCriteria"]}}},"AdditionalCriteriaRootDO":{"title":"AdditionalCriteriaRootDO","type":"object","properties":{"data":{"$ref":"#/components/schemas/AdditionalCriteriaElementDO"}}},"AgentOnboardingErrorResponse":{"description":"Error body with a single message and no error code.","required":["error"],"properties":{"error":{"description":"What went wrong. For a 500 this is the underlying exception message, unless the operation says it answers a fixed sentence.","type":"string","example":"No request found for the provided series ID."}},"type":"object"},"AgentOnboardingFailureResponse":{"description":"The operation failed; error_code says which stage did.","required":["error","error_code"],"properties":{"error":{"description":"The underlying exception message.","type":"string","example":"Automation not found with name 'Welcome series'"},"error_code":{"description":"Which stage failed: NOT_FOUND (no such automation), MODEL_REQUEST (the model call), SCHEMA_PAYLOAD (the schema could not be encoded or parsed), SCHEMA_BUILDER (the automation schema builder) or UNKNOWN.","type":"string","enum":["NOT_FOUND","MODEL_REQUEST","SCHEMA_PAYLOAD","SCHEMA_BUILDER","UNKNOWN"],"example":"NOT_FOUND"}},"type":"object"},"AgentOnboardingMessageResponse":{"description":"The call succeeded; message says what was done.","required":["message"],"properties":{"message":{"description":"A fixed sentence per operation; each operation lists its own.","type":"string","example":"Campaign added successfully"}},"type":"object"},"AggFieldDO":{"description":"Required if the aggregate objects is using the \"most_recent\" operator. This AggFieldDO defines the query logic that the most recent object must satisfy. When this field is present, the ConditionDO.fields attribute is used to specify the requirements prior to selecting the most recent record.","title":"AggFieldDO","required":["data_type","name","operator","value"],"type":"object","properties":{"value":{"type":"string","description":"Value the `name` field's value should be evaluated against. Sometimes optional based on `operator`"},"data_type":{"type":"string","enum":["string","number","decimal","date","datetime","list",""]},"name":{"type":"string","description":"Field whose value will be evaluated"},"operator":{"type":"string","enum":["=","<",">","<=",">=","!=","contains","does not contain","is","is not","not empty","empty","wildcard match","aggregate of",""]}}},"AggregateDO":{"title":"AggregateDO","description":"(Optional) AggregateDO allows for requiring a count of discrete matches against the simple (non-aggregate part of a) condition before the entire condition is considered satisfied.","type":"object","example":{},"properties":{"aggregate_field_operator":{"type":"string","description":"Compares the aggregate count of occurrences to the value of the `aggregate_field_value` field. \nDescription of Values:\n* \"\" - Entire AggregateDO object will be ignored\n* \"between\" - Aggregate must be between `aggregate_field_start_value` and `aggregate_field_end_value`\n* \"most_recent\" - Only the most recent record of the given SourceObject type will be looked at.\n* \"all\" - All records of the given SourceObject type will considered.\n* \"\" - aggregation is ignored \"aggregate_most_recent_field\" is required if \"most_recent\" is used. \n* All other values relate directly to only the aggregate_field_value field","default":"","enum":["=","!=","<",">","<=",">=","between","most_recent","all",""]},"aggregate_field_start_value":{"type":"string","example":"4"},"aggregate_field_end_value":{"type":"string","example":"8"},"aggregate_field_value":{"type":"string","example":"2"},"aggregate_field_time_within_unit":{"type":"string","description":"Look for aggregations within the aggregate_field_time_within_value with units equal to this value.\nNot required if `aggregate_field_operator` is empty. If empty when `aggregate_field_operator` is not empty, \"days\" will be assumed.","default":"days","enum":["hours","days","weeks","months",""]},"aggregate_field_time_within_value":{"maximum":2160,"type":"integer","example":90,"description":"Number of aggregate_field_time_within_unit to look for aggregations within. Not required if `aggregate_field_operator` is empty. When `aggregate_field_operator` is not empty, value must be greater than 0 and less than or equal to the maximum value for the unit specified, which are as follows:\n* hours - 2160\n* days - 90\n* weeks - 13\n* months - 3"},"aggregate_most_recent_field":{"$ref":"#/components/schemas/AggFieldDO"}}},"AiSettingsResponse":{"description":"The AI settings of the calling user.","required":["convert_conversation_uploads_to_resources"],"properties":{"convert_conversation_uploads_to_resources":{"description":"Whether files the user uploads in an AI conversation are also saved as resources. False until the user has set it.","type":"boolean","example":true}},"type":"object"},"AnalyzeScopeRequest":{"description":"Which campaign to look at and the edit the user asked for.","required":["campaignId","userPrompt"],"properties":{"campaignId":{"description":"Id of the campaign whose message is analyzed. The campaign and its message must exist, and the message must be an Email Designer (ed_version 3) message; another version is refused with 403.","type":"integer","example":4821},"userPrompt":{"description":"The edit the user asked for, in their words, 5 to 1000 characters.","type":"string","example":"Change the pink buttons to green"},"campaign":{"description":"Not sent by the caller: the server resolves it from campaignId during validation.","type":"object","readOnly":true},"message":{"description":"Not sent by the caller: the server resolves it from campaignId during validation, as the campaign's message.","type":"object","readOnly":true}},"type":"object"},"AnswerOptionsRenderEnum":{"enum":["BUTTONS","LIST","EMOJIS","NUMBERS"],"type":"string","description":"* `BUTTONS` - Buttons\n* `LIST` - List\n* `EMOJIS` - Emojis\n* `NUMBERS` - Numbers"},"AnswerPhoneDefaultCountryEnum":{"enum":["AF","AX","AL","DZ","AS","AD","AO","AI","AQ","AG","AR","AM","AW","AU","AT","AZ","BS","BH","BD","BB","BY","BE","BZ","BJ","BM","BT","BO","BQ","BA","BW","BV","BR","IO","BN","BG","BF","BI","CV","KH","CM","CA","KY","CF","TD","CL","CN","CX","CC","CO","KM","CG","CD","CK","CR","CI","HR","CU","CW","CY","CZ","DK","DJ","DM","DO","EC","EG","SV","GQ","ER","EE","SZ","ET","FK","FO","FJ","FI","FR","GF","PF","TF","GA","GM","GE","DE","GH","GI","GR","GL","GD","GP","GU","GT","GG","GN","GW","GY","HT","HM","VA","HN","HK","HU","IS","IN","ID","IR","IQ","IE","IM","IL","IT","JM","JP","JE","JO","KZ","KE","KI","KW","KG","LA","LV","LB","LS","LR","LY","LI","LT","LU","MO","MG","MW","MY","MV","ML","MT","MH","MQ","MR","MU","YT","MX","FM","MD","MC","MN","ME","MS","MA","MZ","MM","NA","NR","NP","NL","NC","NZ","NI","NE","NG","NU","NF","KP","MK","MP","NO","OM","PK","PW","PS","PA","PG","PY","PE","PH","PN","PL","PT","PR","QA","RE","RO","RU","RW","BL","SH","KN","LC","MF","PM","VC","WS","SM","ST","SA","SN","RS","SC","SL","SG","SX","SK","SI","SB","SO","ZA","GS","KR","SS","ES","LK","SD","SR","SJ","SE","CH","SY","TW","TJ","TZ","TH","TL","TG","TK","TO","TT","TN","TR","TM","TC","TV","UG","UA","AE","GB","UM","US","UY","UZ","VU","VE","VN","VG","VI","WF","EH","YE","ZM","ZW"],"type":"string","description":"* `AF` - Afghanistan\n* `AX` - Åland Islands\n* `AL` - Albania\n* `DZ` - Algeria\n* `AS` - American Samoa\n* `AD` - Andorra\n* `AO` - Angola\n* `AI` - Anguilla\n* `AQ` - Antarctica\n* `AG` - Antigua and Barbuda\n* `AR` - Argentina\n* `AM` - Armenia\n* `AW` - Aruba\n* `AU` - Australia\n* `AT` - Austria\n* `AZ` - Azerbaijan\n* `BS` - Bahamas\n* `BH` - Bahrain\n* `BD` - Bangladesh\n* `BB` - Barbados\n* `BY` - Belarus\n* `BE` - Belgium\n* `BZ` - Belize\n* `BJ` - Benin\n* `BM` - Bermuda\n* `BT` - Bhutan\n* `BO` - Bolivia\n* `BQ` - Bonaire, Sint Eustatius and Saba\n* `BA` - Bosnia and Herzegovina\n* `BW` - Botswana\n* `BV` - Bouvet Island\n* `BR` - Brazil\n* `IO` - British Indian Ocean Territory\n* `BN` - Brunei\n* `BG` - Bulgaria\n* `BF` - Burkina Faso\n* `BI` - Burundi\n* `CV` - Cabo Verde\n* `KH` - Cambodia\n* `CM` - Cameroon\n* `CA` - Canada\n* `KY` - Cayman Islands\n* `CF` - Central African Republic\n* `TD` - Chad\n* `CL` - Chile\n* `CN` - China\n* `CX` - Christmas Island\n* `CC` - Cocos (Keeling) Islands\n* `CO` - Colombia\n* `KM` - Comoros\n* `CG` - Congo\n* `CD` - Congo (the Democratic Republic of the)\n* `CK` - Cook Islands\n* `CR` - Costa Rica\n* `CI` - Côte d'Ivoire\n* `HR` - Croatia\n* `CU` - Cuba\n* `CW` - Curaçao\n* `CY` - Cyprus\n* `CZ` - Czechia\n* `DK` - Denmark\n* `DJ` - Djibouti\n* `DM` - Dominica\n* `DO` - Dominican Republic\n* `EC` - Ecuador\n* `EG` - Egypt\n* `SV` - El Salvador\n* `GQ` - Equatorial Guinea\n* `ER` - Eritrea\n* `EE` - Estonia\n* `SZ` - Eswatini\n* `ET` - Ethiopia\n* `FK` - Falkland Islands (Malvinas)\n* `FO` - Faroe Islands\n* `FJ` - Fiji\n* `FI` - Finland\n* `FR` - France\n* `GF` - French Guiana\n* `PF` - French Polynesia\n* `TF` - French Southern Territories\n* `GA` - Gabon\n* `GM` - Gambia\n* `GE` - Georgia\n* `DE` - Germany\n* `GH` - Ghana\n* `GI` - Gibraltar\n* `GR` - Greece\n* `GL` - Greenland\n* `GD` - Grenada\n* `GP` - Guadeloupe\n* `GU` - Guam\n* `GT` - Guatemala\n* `GG` - Guernsey\n* `GN` - Guinea\n* `GW` - Guinea-Bissau\n* `GY` - Guyana\n* `HT` - Haiti\n* `HM` - Heard Island and McDonald Islands\n* `VA` - Holy See\n* `HN` - Honduras\n* `HK` - Hong Kong\n* `HU` - Hungary\n* `IS` - Iceland\n* `IN` - India\n* `ID` - Indonesia\n* `IR` - Iran\n* `IQ` - Iraq\n* `IE` - Ireland\n* `IM` - Isle of Man\n* `IL` - Israel\n* `IT` - Italy\n* `JM` - Jamaica\n* `JP` - Japan\n* `JE` - Jersey\n* `JO` - Jordan\n* `KZ` - Kazakhstan\n* `KE` - Kenya\n* `KI` - Kiribati\n* `KW` - Kuwait\n* `KG` - Kyrgyzstan\n* `LA` - Laos\n* `LV` - Latvia\n* `LB` - Lebanon\n* `LS` - Lesotho\n* `LR` - Liberia\n* `LY` - Libya\n* `LI` - Liechtenstein\n* `LT` - Lithuania\n* `LU` - Luxembourg\n* `MO` - Macao\n* `MG` - Madagascar\n* `MW` - Malawi\n* `MY` - Malaysia\n* `MV` - Maldives\n* `ML` - Mali\n* `MT` - Malta\n* `MH` - Marshall Islands\n* `MQ` - Martinique\n* `MR` - Mauritania\n* `MU` - Mauritius\n* `YT` - Mayotte\n* `MX` - Mexico\n* `FM` - Micronesia\n* `MD` - Moldova\n* `MC` - Monaco\n* `MN` - Mongolia\n* `ME` - Montenegro\n* `MS` - Montserrat\n* `MA` - Morocco\n* `MZ` - Mozambique\n* `MM` - Myanmar\n* `NA` - Namibia\n* `NR` - Nauru\n* `NP` - Nepal\n* `NL` - Netherlands\n* `NC` - New Caledonia\n* `NZ` - New Zealand\n* `NI` - Nicaragua\n* `NE` - Niger\n* `NG` - Nigeria\n* `NU` - Niue\n* `NF` - Norfolk Island\n* `KP` - North Korea\n* `MK` - North Macedonia\n* `MP` - Northern Mariana Islands\n* `NO` - Norway\n* `OM` - Oman\n* `PK` - Pakistan\n* `PW` - Palau\n* `PS` - Palestine, State of\n* `PA` - Panama\n* `PG` - Papua New Guinea\n* `PY` - Paraguay\n* `PE` - Peru\n* `PH` - Philippines\n* `PN` - Pitcairn\n* `PL` - Poland\n* `PT` - Portugal\n* `PR` - Puerto Rico\n* `QA` - Qatar\n* `RE` - Réunion\n* `RO` - Romania\n* `RU` - Russia\n* `RW` - Rwanda\n* `BL` - Saint Barthélemy\n* `SH` - Saint Helena, Ascension and Tristan da Cunha\n* `KN` - Saint Kitts and Nevis\n* `LC` - Saint Lucia\n* `MF` - Saint Martin (French part)\n* `PM` - Saint Pierre and Miquelon\n* `VC` - Saint Vincent and the Grenadines\n* `WS` - Samoa\n* `SM` - San Marino\n* `ST` - Sao Tome and Principe\n* `SA` - Saudi Arabia\n* `SN` - Senegal\n* `RS` - Serbia\n* `SC` - Seychelles\n* `SL` - Sierra Leone\n* `SG` - Singapore\n* `SX` - Sint Maarten (Dutch part)\n* `SK` - Slovakia\n* `SI` - Slovenia\n* `SB` - Solomon Islands\n* `SO` - Somalia\n* `ZA` - South Africa\n* `GS` - South Georgia and the South Sandwich Islands\n* `KR` - South Korea\n* `SS` - South Sudan\n* `ES` - Spain\n* `LK` - Sri Lanka\n* `SD` - Sudan\n* `SR` - Suriname\n* `SJ` - Svalbard and Jan Mayen\n* `SE` - Sweden\n* `CH` - Switzerland\n* `SY` - Syria\n* `TW` - Taiwan\n* `TJ` - Tajikistan\n* `TZ` - Tanzania\n* `TH` - Thailand\n* `TL` - Timor-Leste\n* `TG` - Togo\n* `TK` - Tokelau\n* `TO` - Tonga\n* `TT` - Trinidad and Tobago\n* `TN` - Tunisia\n* `TR` - Türkiye\n* `TM` - Turkmenistan\n* `TC` - Turks and Caicos Islands\n* `TV` - Tuvalu\n* `UG` - Uganda\n* `UA` - Ukraine\n* `AE` - United Arab Emirates\n* `GB` - United Kingdom\n* `UM` - United States Minor Outlying Islands\n* `US` - United States of America\n* `UY` - Uruguay\n* `UZ` - Uzbekistan\n* `VU` - Vanuatu\n* `VE` - Venezuela\n* `VN` - Vietnam\n* `VG` - Virgin Islands (British)\n* `VI` - Virgin Islands (U.S.)\n* `WF` - Wallis and Futuna\n* `EH` - Western Sahara\n* `YE` - Yemen\n* `ZM` - Zambia\n* `ZW` - Zimbabwe"},"AnswerTypeEnum":{"enum":["ANY","FREE_TEXT","SINGLE_OPTION","NUMBER","URL","EMAIL","FILE","DOCUMENT","VIDEO","IMAGE","PHONE","DATE","TIME","DATETIME","BOOL","LOCATION"],"type":"string","description":"* `ANY` - Any\n* `FREE_TEXT` - Free Text\n* `SINGLE_OPTION` - Single Option\n* `NUMBER` - Number\n* `URL` - Url\n* `EMAIL` - Email\n* `FILE` - File\n* `DOCUMENT` - Document\n* `VIDEO` - Video\n* `IMAGE` - Image\n* `PHONE` - Phone\n* `DATE` - Date\n* `TIME` - Time\n* `DATETIME` - Datetime\n* `BOOL` - Bool\n* `LOCATION` - Location"},"AreacodeListErrorResponse":{"description":"Why the area codes could not be returned.","required":["error"],"properties":{"error":{"description":"What went wrong: `Area code or endpoint not found` when the search found nothing, otherwise `SMS 10DLC get area codes failure: ` followed by the reason the lookup failed.","type":"string","example":"Area code or endpoint not found"}},"type":"object"},"AreacodeListResponse":{"description":"The area codes that have local phone numbers available to buy for the search.","required":["areacodes"],"properties":{"areacodes":{"description":"Distinct three-digit North American area codes, as returned by the search.","type":"array","items":{"type":"integer","example":773}}},"type":"object"},"AsyncClassifyRequest":{"description":"Worker payload for the classification step of a split campaign message generation, dispatched by AsyncDispatcherService after POST /ai/campaigns/split.","required":["requestid","markup","text_blocks"],"properties":{"requestid":{"description":"External identifier of the split message request record, as answered by POST /ai/campaigns/split. The record must be in the classifying status.","type":"string","example":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"markup":{"description":"HTML of the original message with a data-ai-block-id attribute set on each text block the init step found.","type":"string","example":"<html><body><p data-ai-block-id=\"ai-block-1\">Our autumn sale starts today.</p></body></html>"},"text_blocks":{"description":"The text blocks found in the markup, one per data-ai-block-id, for the model to classify.","type":"array","items":{"required":["aiBlockId","text","size"],"properties":{"aiBlockId":{"description":"Value of the block's data-ai-block-id attribute in markup.","type":"string","example":"ai-block-1"},"text":{"description":"Text content of the block.","type":"string","example":"Our autumn sale starts today."},"size":{"description":"Size bucket of the text by word count: xsmall (under 3), small (under 10), medium (under 40), large (under 100) or xlarge.","type":"string","example":"small"}},"type":"object"},"example":[{"aiBlockId":"ai-block-1","text":"Our autumn sale starts today.","size":"small"}]},"statusRequestRecord":{"description":"Ignored on input: the server loads the request record named by requestid into it.","type":"object","readOnly":true},"statusRequest":{"description":"Ignored on input: the server builds the request state (message id, status, components, prompt) from statusRequestRecord.","type":"object","readOnly":true}},"type":"object"},"AsyncGenerateRequest":{"description":"Worker payload for the generation step of a split campaign message generation, dispatched by AsyncDispatcherService after the classification step.","required":["requestid","markup"],"properties":{"requestid":{"description":"External identifier of the split message request record, as answered by POST /ai/campaigns/split. The record must be in the classified status.","type":"string","example":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"markup":{"description":"HTML of the original message with its text blocks labelled by the classification step.","type":"string","example":"<html><body><p data-ai-block-id=\"ai-block-1\">Our autumn sale starts today.</p></body></html>"},"statusRequestRecord":{"description":"Ignored on input: the server loads the request record named by requestid into it.","type":"object","readOnly":true},"statusRequest":{"description":"Ignored on input: the server builds the request state (message id, status, components, prompt) from statusRequestRecord.","type":"object","readOnly":true},"messageId":{"description":"Ignored on input: the server copies the original message id from the request record.","type":["integer","null"],"readOnly":true,"example":9134},"message":{"description":"Ignored on input: the server loads the original message named by messageId into it.","type":"object","readOnly":true}},"type":"object"},"AudienceOutcome":{"description":"How a set_campaign_audience call ended.","enum":["success","not_found","not_permitted","not_modifiable","list_not_found","segment_not_found","segment_not_on_lists","refused","unconfirmed"],"title":"AudienceOutcome","type":"string"},"AudienceSummary":{"description":"A contact-list audience, summarized for background context.","properties":{"id":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"Numeric ID of the list.","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"List name.","title":"Name"},"type":{"const":"list","default":"list","description":"Always `\"list\"`.","title":"Type","type":"string"},"active_subscribers":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"Active subscriber count.","title":"Active Subscribers"}},"title":"Audience Summary","type":"object"},"AutomationBrandkitApplyRequest":{"description":"The job PUT /ai/agent/onboarding/automation/brandkit/{seriesid} queues, one per campaign: which campaign to re-skin with which brand kit. Sent only by Hosted's own background dispatcher.","required":["requestid","campaignid","messageid","brandkitid"],"properties":{"requestid":{"description":"ID of the stored brand kit request the PUT /ai/agent/onboarding/automation/brandkit/{seriesid} call created; must name a stored request.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"campaignid":{"description":"ID of the campaign to re-skin; must exist.","type":"integer","example":4821},"messageid":{"description":"ID of the campaign's message; must exist.","type":"integer","example":9001},"brandkitid":{"description":"UUID of the brand kit to apply; must name a stored brand kit.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"AutomationBrandkitRequest":{"description":"Which brand kit to apply to the automation's campaigns. The body may be empty.","properties":{"brandkitUuid":{"description":"UUID of the brand kit to apply; must name a stored brand kit. Omitted, the account's primary brand kit is used.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"AutomationBrandkitStatusResponse":{"description":"Whether the latest brand kit request for the automation finished.","required":["success"],"properties":{"success":{"description":"True when the latest request completed. False when it failed, or when it was still pending after 5 minutes, which this read marks as failed.","type":"boolean","example":true}},"type":"object"},"AutomationBuildDetailsResource":{"description":"The automation after a successful build.","required":["name","seriesId","benefits","description","removedActions","removedTriggers","truncated","schema","storedConfig"],"properties":{"name":{"description":"Automation name as stored on the series.","type":"string","example":"Welcome series"},"seriesId":{"description":"Id of the saved automation series.","type":"integer","example":1000438},"benefits":{"description":"Benefits paragraph for the automation.","type":"string","example":"Welcomes new subscribers with a single email."},"description":{"description":"Short description of what the automation does.","type":"string","example":"Sends one email when contacts join Engaged readers."},"removedActions":{"description":"Always an empty array on this route; removed action types are not returned on build.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildRemovedCapability"}},"removedTriggers":{"description":"Trigger types removed for capability or plan limits when present; otherwise empty.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildRemovedCapability"}},"truncated":{"description":"True when the workflow document was truncated for size limits.","type":"boolean","example":false},"schema":{"description":"Workflow document when this route returns one after save; otherwise null. Shape is not expanded here.","type":["object","null"],"additionalProperties":true},"storedConfig":{"description":"Always null on this route today. Reserved for stored builder configuration if returned in the future.","type":["object","null"],"additionalProperties":true},"sendBlocks":{"description":"Send step to block pairings when external email writer mode is used; omitted otherwise.","type":["array","null"],"items":{"$ref":"#/components/schemas/AutomationBuildSendBlockPair"}}},"type":"object"},"AutomationBuildEntitlementDeniedResponse":{"description":"The account lacks entitlements for one or more triggers or actions in the proposal.","properties":{"message":{"description":"Why the build was refused, including disallowed trigger or action types when applicable.","type":"string","example":"I'm sorry, but your account is missing permissions needed to generate this automation."},"error_code":{"description":"Machine-readable error category.","type":"string","example":"AUTOMATION_ENTITLEMENT_PERMISSION"}},"type":"object"},"AutomationBuildListEntry":{"description":"One automation start or step and whether this account can build it with the AI schema generator.","required":["id","name","description","buildable","reason"],"properties":{"id":{"description":"Start or step type id.","type":"string","example":"subscribe"},"name":{"description":"Human-readable name.","type":"string","example":"List subscription"},"description":{"description":"Short description when one exists in the schema definition.","type":"string","example":"Trigger when a contact subscribes to a list"},"buildable":{"description":"True when the AI allowlist includes this id and the account plan permits it.","type":"boolean","example":true},"reason":{"description":"Null when buildable is true. Otherwise `not_buildable` when the AI cannot generate this id, or `plan` when the plan blocks an allowlisted id.","type":["string","null"],"example":null}},"type":"object"},"AutomationBuildListResponse":{"description":"Starts and steps this account may reference when building automations with AI.","required":["starts","steps"],"properties":{"starts":{"description":"Automation start triggers in the product catalog for this account.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildListEntry"}},"steps":{"description":"Automation action steps in the product catalog for this account.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildListEntry"}}},"type":"object"},"AutomationBuildRemovedCapability":{"description":"A trigger or action type removed during build or entitlement scrub on this path.","properties":{"id":{"description":"Internal type identifier for the trigger or action.","type":"string","example":"subscribe"},"label":{"description":"Human-readable label for the removed type.","type":"string","example":"Subscribes to a list"},"reason":{"description":"Optional disclosure reason when the scrub removed the type for entitlement or plan limits.","type":["string","null"],"example":"Not available on your plan"}},"type":"object"},"AutomationBuildRequest":{"description":"Workflow document from a prior draft call, plus optional build options.","required":["schema"],"properties":{"schema":{"description":"JSON string of the workflow document returned from the draft call (must include workflow.actions).","type":"string","example":"{\"workflow\":{\"actions\":[]}}"},"labelId":{"description":"Folder label id when the automation should be filed under a label.","type":["integer","null"],"example":12},"failOnError":{"description":"When true, stop on the first blocking build error.","type":["boolean","null"],"example":true},"sessionId":{"description":"Optional automation agent session identifier for telemetry and async follow-up work. A repeated value returns the existing series. Omitting it, or a value with no prior build, still creates one.","type":["string","null"],"example":"sess_01h2x3y4z5"},"skipCampaignGeneration":{"description":"When true, skip LLM campaign generation for send blocks.","type":"boolean","example":false},"externalEmailWriter":{"description":"When true, return send step to block pairings for an external email writer.","type":"boolean","example":false}},"type":"object"},"AutomationBuildSendBlockPair":{"description":"Maps a send step in the workflow document to the persisted send block id.","properties":{"stepId":{"description":"Step identifier from the workflow document.","type":"string","example":"send_welcome"},"blockId":{"description":"Persisted send block id in the automation.","type":"integer","example":42}},"type":"object"},"AutomationBuilderActionBlock":{"type":"object","description":"One block of an automation in the API's JSON format.","properties":{"id":{"type":["integer","string"],"description":"ID of the block."},"automation":{"type":["integer","string"],"description":"ID of the automation the block belongs to."},"parent":{"type":["integer","string"],"description":"ID of the parent block; the trigger (`start`) block is the root."},"ordernum":{"type":["integer","string"],"description":"Position of the block among its parent's children."},"type":{"type":"string","description":"Block type, for example `start`, `send`, `wait`, `if`, `split`, `goal`, `addtag` or `note`."},"params":{"type":["object","array","null"],"description":"Type-specific configuration of the block, decoded from its stored JSON."},"deleted":{"type":["integer","string"],"description":"1 when the block has been deleted, otherwise 0."},"cdate":{"type":"string","description":"When the block was created (ISO 8601)."},"mdate":{"type":"string","description":"When the block was last modified (ISO 8601)."},"links":{"type":"object","description":"URLs of the block's related resources, keyed by relationship name (`automation`, `parent`, `children`, `contactAutomationLogs`, `goal`).","additionalProperties":{"type":"string"}}}},"AutomationBuilderBlockLimitError":{"type":"object","description":"Error body for a request refused by the account's automation block limit.","properties":{"errors":{"type":"array","description":"Always one entry.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status of the error.","example":402},"title":{"type":"string","description":"Short error title.","example":"Too many blocks"},"detail":{"type":"string","description":"Explanation of the limit that was reached.","example":"You have reached the limit of blocks allowed for this automation. Please upgrade your account to use this automation revision."}}}}}},"AutomationBuilderBlockSaveResult":{"type":"object","description":"Result of creating or updating one action block.","required":["succeeded","message"],"properties":{"succeeded":{"type":"integer","enum":[0,1],"description":"1 when the block was saved, otherwise 0."},"message":{"type":"string","description":"Translated outcome, for example `Add contact note action saved.` or the validation error for the block type."},"block":{"description":"The saved block. Present when `succeeded` is 1.","allOf":[{"$ref":"#/components/schemas/AutomationBuilderSavedBlock"}]},"elseblock":{"type":"object","description":"The `else` branch block created alongside a new `if` block. Present only when an `if` block is created.","additionalProperties":true}}},"AutomationBuilderOutcome":{"type":"object","description":"Result envelope the legacy automation builder endpoints return for both success and handled failures. The HTTP status is 200 either way; read `success`.","required":["success","message"],"properties":{"success":{"type":"integer","enum":[0,1],"description":"1 when the request did what it asked, 0 when it was refused."},"message":{"type":"string","description":"Translated, human-readable outcome or reason for refusal."}}},"AutomationBuilderSavedBlock":{"type":"object","description":"The block as the save routine for its type left it: the stored row, not the JSON API format. A block type may add keys of its own.","additionalProperties":true,"properties":{"id":{"type":["integer","string"],"description":"ID of the block."},"seriesid":{"type":["integer","string"],"description":"ID of the automation."},"parentid":{"type":["integer","string"],"description":"ID of the parent block."},"ordernum":{"type":["integer","string"],"description":"Position of the block among its parent's children."},"type":{"type":"string","description":"Block type."},"params":{"type":"string","description":"Type-specific configuration of the block as a JSON-encoded string, for example `{\"note\":\"new note from API\"}`."},"deleted":{"type":["integer","string"],"description":"1 when the block has been deleted, otherwise 0. Present on update."},"cdate":{"type":"string","description":"When the block was created. Present on update."},"mdate":{"type":"string","description":"When the block was last modified. Present on update."}}},"AutomationCampaignBrandkitResponse":{"description":"The brand kit and template an automation campaign was generated with.","required":["brandkitUuid","template"],"properties":{"brandkitUuid":{"description":"UUID of the account's primary brand kit; null when the campaign has no generated-content record or the account has no primary brand kit.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"template":{"description":"Template the campaign content was generated into, one of the generated campaign template names; null when the campaign has no generated-content record.","type":["string","null"],"example":"welcome"}},"type":"object"},"AutomationCampaignEditRequest":{"description":"What to change on an automation campaign message: a prompt for the model, a template to re-render into, or a subject and preheader to set directly.","required":["campaignId"],"properties":{"campaignId":{"description":"ID of the automation campaign to edit; must exist and have a message.","type":"integer","example":4821},"prompt":{"description":"What to change, in plain words. Omitted when only template, subject or preheader are set directly.","type":["string","null"],"example":"Make the opening shorter and add a call to action"},"contentChange":{"description":"True to have the model rewrite the body from prompt.","type":"boolean","example":true},"subjectChange":{"description":"True to have the model rewrite the subject from prompt.","type":"boolean","example":false},"preheaderChange":{"description":"True to have the model rewrite the preheader from prompt.","type":"boolean","example":false},"sessionId":{"description":"Automation agent session the edit belongs to, for tracing.","type":["string","null"],"example":"sess_01h2x3y4z5"},"template":{"description":"Generated campaign template to re-render the message into, one of the template names; omitted keeps the current one.","type":["string","null"],"enum":["promote","welcome","monthly","whatsnew","announcement","letsmove","clean","producthighlight","flashsale","chillvibes","boldheader","colorblocks","fashioneditorial","flashsalecountdown","freetrialcountdown","elegantambiance"],"example":"welcome"},"subject":{"description":"Subject to set as is, without the model; omitted leaves it to prompt and subjectChange.","type":["string","null"],"example":"Welcome to Acme"},"preheader":{"description":"Preheader to set as is, without the model; omitted leaves it to prompt and preheaderChange.","type":["string","null"],"example":"Here is what to expect from us"}},"type":"object"},"AutomationCampaignEditedResponse":{"description":"The campaign message was rewritten; what changed and the subject line it now has.","required":["summary","subject","preheader"],"properties":{"summary":{"description":"The model's one-line summary of the change; empty when no content was generated.","type":"string","example":"Shortened the opening paragraph and added a call to action."},"subject":{"description":"The message's subject after the edit.","type":["string","null"],"example":"Welcome to Acme"},"preheader":{"description":"The message's preheader after the edit.","type":["string","null"],"example":"Here is what to expect from us"}},"type":"object"},"AutomationCampaignGenerationRequest":{"description":"The job an automation build queues for each send block that needs an email written: which campaign to fill and what it should say. Sent by Hosted's own background dispatcher, and by the automation agent in ac-agents when it drives generation itself.","required":["campaignid","messageid","blockid","description","subject","requestid"],"properties":{"campaignid":{"description":"ID of the placeholder campaign the send block already points at; must exist.","type":"integer","example":4821},"messageid":{"description":"ID of that campaign's message; must exist.","type":"integer","example":9001},"description":{"description":"What the email should say, as the automation schema described the send step.","type":"string","example":"A warm welcome that introduces the brand and links to the getting-started guide"},"subject":{"description":"Subject line the schema proposed for the email.","type":"string","example":"Welcome to Acme"},"requestid":{"description":"ID of the stored resource request tracking the automation build; must name a stored request.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"blockid":{"description":"ID of the send block the campaign belongs to; must exist.","type":"integer","example":55021},"sessionid":{"description":"Automation agent session the build belongs to, for tracing.","type":["string","null"],"example":"sess_01h2x3y4z5"},"traceparent":{"description":"W3C traceparent of the build request, so the job rejoins its trace; the queue drops the headers.","type":["string","null"],"example":"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}},"type":"object"},"AutomationCanEditFailureResponse":{"description":"The can-edit check could not be completed.","required":["error"],"properties":{"error":{"description":"Human-readable failure message.","type":"string","example":"Failed to check can-edit automation"}},"type":"object"},"AutomationCanEditResponse":{"description":"Whether one automation can be edited.","required":["allow","reason","link"],"properties":{"allow":{"description":"True when the automation can be edited.","type":"boolean","example":true},"reason":{"description":"OK when allow is true. Otherwise ACTIVE, OTHER, IN_PROGRESS, or NEEDS_MAPPING.","type":"string","example":"OK"},"link":{"description":"Link to the automation in the app.","type":"string","example":"https://example.example.com/series/1000438"}},"type":"object"},"AutomationCompletionStats":{"type":"object","properties":{"entered":{"type":"integer","description":"Times contacts entered the automation."},"completed":{"type":"integer","description":"Runs that completed."},"rate":{"type":["string","integer"],"description":"Completed runs as a percentage of entered runs, with four decimals. 0 when no run completed."},"rateChange":{"type":["string","integer"],"description":"rate minus the rate of runs that started and completed more than 30 days ago, with four decimals. 0 when no run completed."},"averageTime":{"type":"integer","description":"Average time to complete, in milliseconds, counted in whole seconds."}}},"AutomationConnectionsConnection":{"description":"How one automation is linked to the account's other automations. Built on request from the automations' blocks and start triggers; nothing is stored.","properties":{"id":{"description":"ID of the automation the record describes, the same as automation","type":"integer","example":12},"automation":{"description":"ID of the automation the record describes","type":"integer","example":12},"connectionStarts":{"description":"Other automations this automation starts: with a Start an automation action, or with an action that fires the other automation's start trigger (subscribing to a list, adding a tag, updating a field, sending a campaign, and so on)","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsLink"}},"connectionIsStartedBy":{"description":"Other automations that start this one, in the same ways","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsLink"}},"connectionStops":{"description":"Other automations this automation ends with an End another automation action","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsLink"}},"connectionIsStoppedBy":{"description":"Other automations that end this one with an End another automation action","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsLink"}},"connectionInvalid":{"description":"A link that was found but is not shown, because the other automation is hidden or none of the actions still applies. The entry carries only triggers and invalid (1), and the array holds at most one entry. Links to automations that no longer exist are left out entirely.","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsLink"}},"links":{"description":"URLs of the record's related reads","properties":{"automation":{"description":"URL of the automation the record describes, GET /automationConnections/{id}/automation","type":"string","example":"https://:account.api-us1.com/api/:version/automationConnections/12/automation"}},"type":"object"}},"type":"object"},"AutomationConnectionsLink":{"description":"One other automation linked to the requested automation, and the actions that link them","properties":{"triggers":{"description":"The actions that make the link. Each is a block in the automation that does the starting or ending.","type":"array","items":{"properties":{"triggerId":{"description":"ID of the block whose action makes the link","type":"string","example":"41"},"type":{"description":"What links them: `enter` (a Start an automation action), `exit` (an End another automation action), or the action that fires the other automation's start trigger: `subscribe`, `unsubscribe`, `addtag`, `removetag`, `field`, `goal`, `conversion`, `adddeal`, `dealstage`, `dealstatus`, `score`, `sitemessage`, or a campaign event (`read`, `reply`, `forward`, `share`, `click`)","type":"string","example":"addtag"},"action":{"description":"Translated description of the link for display, naming the list, tag, field, campaign or other record involved","type":"string"},"listid":{"description":"List ID, or IDs, the action subscribes to or unsubscribes from. subscribe and unsubscribe only.","type":"array","items":{"type":["string","integer"]}},"fieldid":{"description":"ID of the custom field the action updates. field only, for custom fields.","type":["string","integer"]},"campaignid":{"description":"ID of the campaign the action sends. Campaign events only.","type":["string","integer"]},"campaignlist":{"description":"List the other automation's campaign trigger is limited to. Campaign events only, when that trigger watches any campaign on one list.","type":["string","integer"]},"conversionid":{"description":"ID of the conversion. conversion only.","type":["string","integer"]},"sitemessageid":{"description":"ID of the site message. sitemessage only.","type":["string","integer"]},"pipelineid":{"description":"ID of the deal pipeline. adddeal only.","type":["string","integer"]},"dealstageid":{"description":"ID of the deal stage. dealstage only.","type":["string","integer"]},"scoreid":{"description":"ID of the score. score only.","type":["string","integer"]}},"type":"object"}},"connectedId":{"description":"ID of the other automation. Absent from connectionInvalid entries.","type":"integer","example":87},"connectedTitle":{"description":"Name of the other automation. Absent from connectionInvalid entries.","type":"string","example":"Welcome series"},"connectedInactive":{"description":"True when the other automation is not active. Absent from connectionInvalid entries.","type":"boolean","example":false},"status":{"description":"Status of the other automation as stored: 1 active, 2 inactive, 0 draft. Absent from connectionInvalid entries.","type":"string","example":"1"},"invalid":{"description":"0 for a link that is shown, 1 for an entry of connectionInvalid","type":"integer","enum":[0,1],"example":0}},"type":"object"},"AutomationDescribeResponse":{"description":"A plain-language description of an existing automation, written by the model from its schema.","required":["name","seriesId","benefits","description","removedActions","removedTriggers","truncated","schema","storedConfig"],"properties":{"name":{"description":"Automation name as stored on the series.","type":"string","example":"Welcome series"},"seriesId":{"description":"ID of the automation series.","type":"integer","example":1000438},"benefits":{"description":"Benefits paragraph the model wrote for the automation.","type":"string","example":"Welcomes new subscribers with a single email."},"description":{"description":"Short description of what the automation does, written by the model.","type":"string","example":"Sends one email when contacts join Engaged readers."},"removedActions":{"description":"Always empty on this route: nothing is removed when describing.","type":"array","items":{"type":"string"},"example":[]},"removedTriggers":{"description":"Always empty on this route: nothing is removed when describing.","type":"array","items":{"type":"string"},"example":[]},"truncated":{"description":"Always false on this route.","type":"boolean","example":false},"schema":{"description":"Always null on this route: the schema is what the model read, not what it answers.","type":["object","null"],"additionalProperties":true},"storedConfig":{"description":"The automation's stored configuration as exported by the schema builder, or null when it could not be exported. Shape is the builder's; not expanded here.","type":["object","null"],"additionalProperties":true}},"type":"object"},"AutomationEditDeniedResponse":{"description":"The edit was refused. The automation was not changed.","required":["allow","reason","link","error_code"],"properties":{"allow":{"description":"Always false for this error.","type":"boolean","example":false},"reason":{"description":"Why the edit was refused: ACTIVE when the automation is turned on, OTHER when it is missing, NEEDS_MAPPING when an import still needs mapping.","type":"string","example":"ACTIVE"},"link":{"description":"Link to the automation in the app.","type":"string","example":"https://example.example.com/series/1000438"},"error_code":{"description":"Machine-readable error category.","type":"string","example":"EDIT_DENIED"}},"type":"object"},"AutomationEditDetailsResource":{"description":"The automation after a successful edit.","required":["name","seriesId","benefits","description","removedActions","removedTriggers","truncated","schema","storedConfig"],"properties":{"name":{"description":"Automation name as stored on the series.","type":"string","example":"Welcome series"},"seriesId":{"description":"Id of the edited automation series.","type":"integer","example":1000438},"benefits":{"description":"Benefits paragraph for the automation.","type":"string","example":"Welcomes new subscribers with a single email."},"description":{"description":"Short description of what the automation does.","type":"string","example":"Sends one email when contacts join Engaged readers."},"removedActions":{"description":"Action types removed for this account during the edit. Empty when none were removed.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildRemovedCapability"}},"removedTriggers":{"description":"Trigger types removed for this account during the edit. Empty when none were removed.","type":"array","items":{"$ref":"#/components/schemas/AutomationBuildRemovedCapability"}},"truncated":{"description":"True when the workflow document was truncated for size limits.","type":"boolean","example":false},"schema":{"description":"Workflow document after the edit when one is returned; otherwise null. Shape is not expanded here.","type":["object","null"],"additionalProperties":true},"storedConfig":{"description":"Null on this route today.","type":["object","null"],"additionalProperties":true},"sendBlocks":{"description":"Send step to block pairings when the edit returns them; omitted otherwise.","type":["array","null"],"items":{"$ref":"#/components/schemas/AutomationBuildSendBlockPair"}}},"type":"object"},"AutomationEditEntitlementDeniedResponse":{"description":"The account lacks entitlements for one or more triggers or actions in the edit.","required":["message","error_code"],"properties":{"message":{"description":"Why the edit was refused, including disallowed trigger or action types when applicable.","type":"string","example":"I'm sorry, but your account is missing permissions needed to generate this automation."},"error_code":{"description":"Machine-readable error category.","type":"string","example":"AUTOMATION_ENTITLEMENT_PERMISSION"}},"type":"object"},"AutomationEditInProgressResponse":{"description":"An edit or build for this automation is already in progress.","required":["error","error_code"],"properties":{"error":{"description":"Why the edit was not started.","type":"string","example":"The requested automation cannot be edited at this time"},"error_code":{"description":"Machine-readable error category.","type":"string","example":"EDIT_IN_PROGRESS"}},"type":"object"},"AutomationEditOperationFailureResponse":{"description":"The edit could not be applied.","required":["error","error_code"],"properties":{"error":{"description":"Human-readable failure message.","type":"string","example":"Failed to edit automation"},"error_code":{"description":"Machine-readable error category.","type":"string","example":"SCHEMA_BUILDER"}},"type":"object"},"AutomationEditRequest":{"description":"A natural-language edit for one automation, plus optional composer context.","required":["prompt"],"properties":{"prompt":{"description":"What to change on the automation, in the customer's words.","type":"string","example":"Add a one-day wait before the welcome email on Engaged readers."},"labelId":{"description":"Folder id to store the automation in, when the caller sends one.","type":["integer","null"],"example":12},"failOnError":{"description":"When true, the edit stops on the first blocking error.","type":["boolean","null"],"example":true},"sessionId":{"description":"Automation agent session identifier when the caller is continuing a chat turn. A repeat call with the same session still runs the edit again.","type":["string","null"],"example":"sess_01h2x3y4z5"},"source":{"description":"Request source. Accepted and logged. It does not change whether the edit is allowed.","type":["string","null"],"example":"active-intelligence"},"currentSeriesId":{"description":"Series id the caller is viewing. Accepted and logged. It does not change whether the edit is allowed.","type":["integer","null"],"example":1000438},"referencedAssets":{"description":"Lists, tags, or other composer chips the caller attached to the prompt.","type":"array","items":{"$ref":"#/components/schemas/AutomationSchemaReferencedAsset"}},"skipCampaignGeneration":{"description":"When true, skip LLM campaign generation for send blocks the edit adds or rewrites.","type":"boolean","example":false},"externalEmailWriter":{"description":"When true, return send step to block pairings for an external email writer.","type":"boolean","example":false},"senderMessage":{"description":"The sender's own message for this turn, word for word, when the caller rewrote it into `prompt`. With `externalEmailWriter`, the edit is planned and its changes to existing steps are checked against it.","type":["string","null"],"example":"Add an email for contacts who did not open email 2"},"earlierSenderMessages":{"description":"The sender's own messages from earlier turns of the conversation, oldest first, word for word. Read with `sender_message` when it refers back to them.","type":"array","items":{"type":"string"},"example":["Add an email for contacts who did not open email 2"]},"contentEditedCampaignIds":{"description":"Campaigns the caller already edited the content of this turn. With `externalEmailWriter`, the edit does not replace or clear the email of a step that sends one of them.","type":"array","items":{"type":"integer"},"example":[77]}},"type":"object"},"AutomationEmailSummary":{"description":"One email the build is writing for a send block of the new automation.","properties":{"block_id":{"title":"Block Id","type":"integer"},"subject":{"default":"","title":"Subject","type":"string"},"builder_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Automation builder URL focused on this email's send block, for MCP Apps openLink.","title":"Builder Url"}},"required":["block_id"],"title":"AutomationEmailSummary","type":"object"},"AutomationGoalRecipe":{"description":"An automation recipe selected for a goal and personalized for the account. name and description are null until metadata personalization has run; the other optional keys are left out while empty.","required":["hash","name","description"],"properties":{"hash":{"description":"Hash of the automation recipe template this recipe was selected from. Pass it as recipeHash to import or re-personalize the recipe.","type":["string","null"],"example":"_uw6ffp"},"name":{"description":"Automation name personalized for the account. Null until metadata personalization is done.","type":["string","null"],"example":"Share new blog posts with your readers"},"description":{"description":"Automation description personalized for the account. Null until metadata personalization is done.","type":["string","null"],"example":"Email every new blog post to your subscribers to grow your readership and keep leads engaged."},"originalName":{"description":"The template's name. Left out when empty.","type":"string","example":"Deliver new blog posts"},"originalDescription":{"description":"The template's description. Left out when empty.","type":"string","example":"Deliver new blog posts to your subscribers to raise awareness of your content, grow your audience and nurture leads."},"touchpoints":{"description":"Number of emails the template sends. Left out when unknown.","type":"integer","example":1},"personalizationStatus":{"description":"Where personalization stands. queued: selected, personalization not started. in_progress: a personalization job is running. done: ready to import. error: a job failed; POST /ai/automations/personalize retries it. used: imported as an automation, seriesid names it. Left out when empty.","type":"string","enum":["queued","in_progress","done","error","used"],"example":"done"},"personalizedVariables":{"description":"Generated content for the template's variables, keyed by variable name as the template metadata declares it. Left out until variable personalization has run.","type":"object","example":{"NEW_BLOG_POST":{"name":"New post: 5 ways to grow your list","subject":"Fresh from the blog","email_text":"<p>Our latest post is live.</p>"}}},"seriesid":{"description":"Id of the automation (series) created from this recipe. Left out until the recipe is imported with markUsed.","type":"integer","example":42}},"type":"object"},"AutomationGoalRecipeDoneResponse":{"description":"Acknowledgement that the call ran to the end. It says nothing about the outcome of the work: a worker records failures on the stored recipe or goal and still answers this.","required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"}},"type":"object"},"AutomationGoalRecipeImportRequest":{"description":"Names the stored recipe to turn into an automation. The server resolves the recipe template and the stored personalized recipe from recipeHash and goal, and the folder from labelId.","required":["goal","recipeHash"],"properties":{"goal":{"description":"The goal the recipe is stored under. One of the onboarding goals; matched case-insensitively.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"},"recipeHash":{"description":"Hash of the recipe template, as hash in GET /ai/automations/goal/recipes. Must name a template and a recipe stored for the goal whose personalizationStatus is done; a recipe that is queued, in_progress, error or used is refused with 400.","type":"string","example":"_uw6ffp"},"personalizedRecipeRecord":{"description":"The stored recipe record. Resolved by the server from recipeHash and goal; not part of the payload.","type":"object","readOnly":true},"recipeData":{"description":"The recipe template. Resolved by the server from recipeHash; not part of the payload.","type":"object","readOnly":true},"personalizedRecipe":{"description":"The personalized recipe decoded from the stored record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"labelId":{"description":"Id of an existing automation label (folder) to add the new automation to, besides the \"AI - {goal}\" label it always gets. Null for none.","type":["integer","null"],"example":7},"folder":{"description":"The label named by labelId. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"markUsed":{"description":"True (the default) marks the stored recipe used and records the new automation id on it, so GET /ai/automations/goal/recipes stops listing it. False leaves the recipe importable again.","type":["boolean","null"],"example":true}},"type":"object"},"AutomationGoalRecipeImportedResponse":{"description":"The automation created from the recipe.","required":["id","errors"],"properties":{"id":{"description":"Id of the new automation (series). It is created inactive.","type":"integer","example":42},"errors":{"description":"Output the legacy import captured while building the blocks. Empty when nothing was printed.","type":"string","example":""}},"type":"object"},"AutomationGoalRecipePersonalizationDispatchRequest":{"description":"Queue payload for personalizing one stored recipe. RecipeSelectionService::dispatchPersonalization builds it once per selected recipe, and again from POST /ai/automations/personalize; the server resolves the stored recipe from hash and goal.","required":["goal","starttime","personalization_starttime","hash"],"properties":{"goal":{"description":"The goal the recipe is stored under. One of the onboarding goals; matched case-insensitively.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"},"starttime":{"description":"When the user started the flow, as a Unix timestamp with microseconds (microtime). Negative when the job comes from POST /ai/automations/personalize, which has no flow start. Used to time the whole run in metrics.","type":"number","format":"float","example":1761120000.123456},"personalization_starttime":{"description":"When this recipe was queued for personalization, as a Unix timestamp with microseconds. Used to time this job in metrics.","type":"number","format":"float","example":1761120003.654321},"hash":{"description":"Hash of the recipe template. Must name a recipe stored for the goal.","type":"string","example":"_uw6ffp"},"startpoint":{"description":"Where to start. metadata (the default) generates the personalized name and description first, then the variables. variables skips to the variables, for a recipe whose name and description are already personalized.","type":"string","enum":["metadata","variables"],"example":"metadata"},"recipe":{"description":"The stored recipe. Resolved by the server from hash and goal; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"AutomationGoalRecipeRepersonalizeRequest":{"description":"Names the stored recipe to personalize again. The server resolves the recipe template and the stored personalized recipe from recipeHash and goal.","required":["recipeHash","goal"],"properties":{"recipeHash":{"description":"Hash of the recipe template, as hash in GET /ai/automations/goal/recipes. Must name a template and a recipe stored for the goal whose personalizationStatus is error; a recipe that is queued, in_progress, done or used is refused with 400.","type":"string","example":"_uw6ffp"},"goal":{"description":"The goal the recipe is stored under. One of the onboarding goals; matched case-insensitively.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"},"templateRecipe":{"description":"The recipe template. Resolved by the server from recipeHash; not part of the payload.","type":"object","readOnly":true},"recipeRecord":{"description":"The stored recipe record. Resolved by the server from recipeHash and goal; not part of the payload.","type":"object","readOnly":true},"personalizedRecipe":{"description":"The personalized recipe decoded from the stored record. Resolved by the server; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"AutomationGoalRecipeSelectionDispatchRequest":{"description":"Queue payload for running recipe selection. RecipeSelectionService::initializeSelection builds it from POST /ai/automations/goal/recipes.","required":["goal","starttime"],"properties":{"goal":{"description":"The goal to select recipes for. One of the onboarding goals; matched case-insensitively.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"},"starttime":{"description":"When the user started the flow, as a Unix timestamp with microseconds (microtime). Used to time the whole selection and personalization run in metrics.","type":"number","format":"float","example":1761120000.123456}},"type":"object"},"AutomationGoalRecipeSelectionFailedResponse":{"description":"The selection job could not be queued.","required":["message","status"],"properties":{"message":{"description":"Always error.","type":"string","enum":["error"],"example":"error"},"status":{"description":"dispatch_failed: queueing the selection job threw; the lock on the goal was released, so the call can be repeated.","type":"string","enum":["dispatch_failed"],"example":"dispatch_failed"}},"type":"object"},"AutomationGoalRecipeSelectionStartedResponse":{"description":"Where recipe selection for the goal stands after the request.","required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"},"status":{"description":"done: recipes are already stored for the goal, nothing was dispatched. dispatched: the selection job was queued; poll GET /ai/automations/goal/recipes. redlocked: another request is already running selection for this goal; poll as for dispatched.","type":"string","enum":["done","dispatched","redlocked"],"example":"dispatched"}},"type":"object"},"AutomationGoalRecipesResponse":{"description":"The automation recipes stored for one goal.","required":["recipes"],"properties":{"recipes":{"description":"Every recipe stored for the goal that has not been imported yet (status used is filtered out), in storage order. A recipe may still be queued, in progress or failed: check personalizationStatus.","type":"array","items":{"$ref":"#/components/schemas/AutomationGoalRecipe"}}},"type":"object"},"AutomationGoalRecipesSelectRequest":{"description":"The goal to select automation recipes for.","required":["goal"],"properties":{"goal":{"description":"One of the onboarding goals, as key in GET /ai/automations/goal/industry; matched case-insensitively.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"}},"type":"object"},"AutomationGroup":{"type":"object","description":"One automation group record: a grant that lets the users of one user group see and work with one automation. Users outside the account's main admin group only see automations granted to one of their groups.","properties":{"automation":{"type":["string","integer","null"],"description":"ID of the automation the user group may access; null when the record holds 0. Read back as a string; PUT and PATCH echo a changed value as sent.","example":"12"},"group":{"type":["string","integer","null"],"description":"ID of the user group that has access; null when the record holds 0. Read back as a string; PUT and PATCH echo a changed value as sent.","example":"4"},"cdate":{"type":["string","null"],"description":"When the record was created, in ISO 8601; null when not recorded","example":"2026-10-15T10:52:26-05:00"},"links":{"type":"object","description":"URLs of the record's related reads","properties":{"automation":{"type":"string","description":"URL that returns the automation, GET /automationGroups/{id}/automation","example":"https://:account.api-us1.com/api/:version/automationGroups/5/automation"},"group":{"type":"string","description":"URL that returns the user group, GET /automationGroups/{id}/group","example":"https://:account.api-us1.com/api/:version/automationGroups/5/group"}}},"id":{"type":"string","description":"ID of the automation group record. It is not the user group ID.","example":"5"}}},"AutomationIndustryGoal":{"description":"One onboarding goal, worded for the account's industry.","required":["key","title"],"properties":{"key":{"description":"The goal. Pass it as goal to the /ai/automations/goal/* endpoints and to /ai/automations/import and /ai/automations/personalize.","type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"],"example":"Send targeted and effective campaigns"},"title":{"description":"Label for the goal in the account's language, worded for the industry recorded at onboarding (or the generic wording when the industry is unknown).","type":"string","example":"Targeted campaigns for online shoppers"}},"type":"object"},"AutomationLabel":{"type":"object","description":"One automation label record: the association that attaches one label to one automation. It is not the label itself; labels are managed under /labels.","properties":{"automation":{"type":["string","integer"],"description":"ID of the labelled automation. Read back as a string; PUT and PATCH echo a changed value as sent.","example":"12"},"label":{"type":["string","integer"],"description":"ID of the label. Read back as a string; PUT and PATCH echo a changed value as sent.","example":"3"},"created_timestamp":{"type":"string","description":"When the association was created, as YYYY-MM-DD HH:MM:SS","example":"2026-10-15 10:52:26"},"updated_timestamp":{"type":"string","description":"When the association last changed, as YYYY-MM-DD HH:MM:SS. PUT and PATCH return the value from before their change.","example":"2026-10-15 10:52:26"},"created_by":{"type":["string","null"],"description":"ID of the user who created the association. Null when it was created through this API, which does not set it.","example":null},"updated_by":{"type":["string","null"],"description":"ID of the user who last changed the association. Null when it was only changed through this API, which does not set it.","example":null},"title":{"type":"string","description":"Name of the label. Present only in GET /automationLabels with include_folder=1.","example":"Onboarding"},"color":{"type":"string","description":"Color of the label, a six-digit hex code without #. Present only in GET /automationLabels with include_folder=1.","example":"edf0f7"},"links":{"type":"object","description":"URLs of the record's related reads","properties":{"labels":{"type":"string","description":"URL of GET /automationLabels/{id}/labels","example":"https://:account.api-us1.com/api/:version/automationLabels/7/labels"},"series":{"type":"string","description":"URL of GET /automationLabels/{id}/series","example":"https://:account.api-us1.com/api/:version/automationLabels/7/series"}}},"id":{"type":"string","description":"ID of the automation label record. It is not the label ID; pass it to DELETE /automationLabels/{id} to take the label off the automation.","example":"7"}}},"AutomationOperation":{"enum":["edit","create","view"],"title":"AutomationOperation","type":"string"},"AutomationOutboundEmailSend":{"type":"object","description":"The send request the one-to-one email step queues.","required":["blockId","seriesId","subscriberId","subscriberSeriesId","dealConnectionId","dealId","uuid"],"properties":{"blockId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the one-to-one email step. Its settings give the subject, message, cc and bcc."},"seriesId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the automation. Saved with the sent email."},"subscriberId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the contact the email goes to."},"subscriberSeriesId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the contact's run through the automation. The result is recorded in its history."},"dealConnectionId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the deal connection (mailbox) that sends the email."},"dealId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the deal the email is about, used to personalize it and on the timeline. 0 when a contact, not a deal, started the automation."},"uuid":{"type":"string","description":"Unique ID of this send. A second request with the same uuid sends nothing."},"logId":{"$ref":"#/components/schemas/ContactAutomationHelperId","description":"ID of the run's legacy history entry to update. 0 or absent on most requests."}}},"AutomationOutcome":{"description":"How a run ended.","enum":["success","partial_success","needs_input","declined","answered","not_editable","not_permitted","failed"],"title":"AutomationOutcome","type":"string"},"AutomationRelationsTrackingRequest":{"description":"What an automation tracks: one conversion or one business goal","required":["relationType","relationId"],"properties":{"relationType":{"description":"Kind of record the automation tracks: `conversion` for a conversion, `initiative` for a business goal. Any other value is refused with 422.","type":"string","enum":["conversion","initiative"],"example":"conversion"},"relationId":{"description":"ID of the conversion, or of the business goal, to track. It is not looked up.","type":"integer","example":7}},"type":"object"},"AutomationRevisionValidity":{"type":"object","description":"Whether an automation revision can be restored, and why not.","required":["valid"],"properties":{"valid":{"type":"boolean","description":"True when the revision passes validation."},"error":{"description":"Present when `valid` is false. An object with the reason for a known validation failure, or a plain string when validation failed unexpectedly.","oneOf":[{"type":"object","properties":{"title":{"type":"string","description":"Translated reason, for example that the revision contains triggers or actions the plan no longer includes, or that it exceeds the block limit."},"description":{"type":"string","description":"For an entitlement violation, `Actions and triggers with entitlement violations: ` followed by their names; otherwise empty."}}},{"type":"string","description":"`This revision is no longer valid`."}]},"allow_revert":{"type":"boolean","description":"Present with an object `error`: whether the revision may still be restored despite the failure."}}},"AutomationRunListResponse":{"properties":{"runs":{"items":{"$ref":"#/components/schemas/RunListEntry"},"title":"Runs","type":"array"},"total":{"title":"Total","type":"integer"},"offset":{"title":"Offset","type":"integer"},"limit":{"title":"Limit","type":"integer"}},"required":["runs","total","offset","limit"],"title":"AutomationRunListResponse","type":"object"},"AutomationRunStartData":{"type":"object","description":"How one contact entered an automation, for the contact's automation history.","properties":{"id":{"type":["integer","string"],"description":"ID of the start trigger the contact entered through; `0` when the contact was added manually."},"title":{"type":"string","description":"Translated description of the trigger, or `Contact added to this automation manually`.","example":"Contact's field Full Name changes"},"type":{"type":"string","description":"Start trigger type, for example `subscribe`, `tag`, `field` or `dealstage`; `none` when the contact was added manually."},"icon":{"type":["string","null"],"description":"Icon for the trigger type, or null when the trigger has none or the contact was added manually."},"dealId":{"type":["string","null"],"description":"ID of the deal that started the run when the trigger is deal-related, otherwise null."},"dealTitle":{"type":["string","null"],"description":"Title of that deal, otherwise null."}}},"AutomationSchemaOperationFailureResponse":{"description":"The schema builder could not produce a proposal for this request.","properties":{"error":{"description":"Human-readable failure message.","type":"string","example":"Create schema must contain a single workflow"},"error_code":{"description":"Machine-readable error category.","type":"string","example":"ONE_WORKFLOW_PER_CALL"}},"type":"object"},"AutomationSchemaPermissionDeniedResponse":{"description":"The API user may not manage automations.","properties":{"success":{"description":"Always false for this error.","type":"boolean","example":false},"message":{"description":"Why the request was refused.","type":"string","example":"No permission to manage automations."},"error_code":{"description":"Machine-readable error category.","type":"string","example":"AUTOMATION_MANAGE_PERMISSION"}},"type":"object"},"AutomationSchemaProposal":{"description":"An automation workflow proposal from the schema builder. Nothing is saved until a separate build call.","required":["schema","removed_actions","removed_triggers"],"properties":{"schema":{"description":"Workflow document the builder produced for this prompt. Shape follows the internal automation schema format and is not expanded here.","type":"object","additionalProperties":true},"removed_actions":{"description":"Action block types removed from the proposal because the account cannot use them here.","type":"array","items":{"$ref":"#/components/schemas/AutomationSchemaRemovedCapability"}},"removed_triggers":{"description":"Start trigger types removed from the proposal because the account cannot use them here.","type":"array","items":{"$ref":"#/components/schemas/AutomationSchemaRemovedCapability"}}},"type":"object"},"AutomationSchemaReferencedAsset":{"description":"A list, tag, or other asset the automation composer attached to the prompt.","required":["pkey","asset_type","name"],"properties":{"pkey":{"description":"Primary key of the asset in its store.","type":"integer","example":42},"asset_type":{"description":"Asset type identifier, such as list or tag.","type":"string","example":"list"},"name":{"description":"Display name shown in the composer.","type":"string","example":"Engaged readers"}},"type":"object"},"AutomationSchemaRemovedCapability":{"description":"A trigger or action type removed from the proposal because the account cannot use it on this path.","properties":{"id":{"description":"Internal type identifier for the trigger or action.","type":"string","example":"subscribe"},"label":{"description":"Human-readable label for the removed type.","type":"string","example":"Subscribes to a list"}},"type":"object"},"AutomationSchemaRequest":{"description":"A natural-language prompt and optional composer context for drafting an automation.","required":["prompt"],"properties":{"prompt":{"description":"What the account wants the automation to do, in the customer's words.","type":"string","example":"Welcome new contacts on the Engaged readers list with one email."},"customerWords":{"description":"The customer's original words when the brief or prompt may omit a name the automation should reuse.","type":["string","null"],"example":"Tag people interested in drums"},"failOnError":{"description":"Whether a later build call should fail on the first blocking error. Accepted on this route for compatibility with the create sequence; this action does not read it.","type":["boolean","null"],"example":true},"sessionId":{"description":"Automation agent session identifier when the caller is continuing a chat turn.","type":["string","null"],"example":"sess_01h2x3y4z5"},"slug":{"description":"Recipe slug when the caller is starting from a stored recipe template.","type":["string","null"],"example":"welcome-series"},"referencedAssets":{"description":"Lists, tags, or other composer chips the caller attached to the prompt.","type":"array","items":{"$ref":"#/components/schemas/AutomationSchemaReferencedAsset"}},"externalEmailWriter":{"description":"When true, the build that follows passes externalEmailWriter, so a send step the proposal leaves without a source campaign or template is not given an attached one.","type":"boolean","example":false}},"type":"object"},"AutomationSegmentGenerationRequest":{"description":"The job an automation build queues for each step that needs a segment: which block or start to attach it to and who it should match. Sent only by Hosted's own background dispatcher.","required":["description","requestid"],"properties":{"blockid":{"description":"ID of the automation block whose condition to build (a wait or if/else step). Send exactly one of blockid and startid.","type":["integer","null"],"example":55021},"startid":{"description":"ID of the automation start (trigger) whose segment to build. Send exactly one of blockid and startid.","type":["integer","null"],"example":3101},"description":{"description":"Who the segment should match, as the automation schema described the step.","type":"string","example":"Contacts who opened the welcome email but did not click"},"requestid":{"description":"ID of the stored resource request tracking the automation build; must name a stored request.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"sessionid":{"description":"Automation agent session the build belongs to, for tracing.","type":["string","null"],"example":"sess_01h2x3y4z5"},"traceparent":{"description":"W3C traceparent of the build request, so the job rejoins its trace; the queue drops the headers.","type":["string","null"],"example":"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}},"type":"object"},"AutomationShowcase":{"type":"object","properties":{"entries":{"type":"integer","description":"Times contacts entered the automation."},"tags":{"type":"array","description":"Up to ten tags held by contacts who entered, most held first.","items":{"type":"object","properties":{"id":{"type":"string"},"tag":{"type":"string"},"count":{"type":"string","description":"Runs whose contact has the tag."}}}},"lists":{"type":"array","description":"Up to ten lists of contacts who entered, most held first.","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"count":{"type":"string","description":"Runs whose contact is on the list."}}}},"timespans":{"type":"array","description":"Runs grouped by how long they took, in seconds, in up to ten equal ranges, largest group first. When no run has a time yet, one group from 0 to 0 holds every run.","items":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"},"count":{"type":"integer"}}}}}},"AutomationStartsTrigger":{"type":"object","description":"One start trigger of an automation: the event that enters contacts into it. Numbers are returned as strings.","properties":{"seriesid":{"type":"string","description":"ID of the automation the trigger belongs to","example":"12"},"segmentid":{"type":"string","description":"ID of the segment whose conditions a contact must meet to enter; 0 for none","example":"0"},"multientry":{"type":"string","description":"1 when a contact may enter the automation more than once from this trigger, otherwise 0","example":"0"},"type":{"type":"string","description":"Trigger type, such as subscribe, unsubscribe, tagadd, tagrem, field, date, event, url or dealstage. An automation with no trigger has one of type none.","example":"tagadd"},"relid":{"type":"string","description":"ID of the record the trigger watches, such as the list of a subscribe trigger; 0 for any, and always 0 for date, event, field, tagadd, tagrem and url triggers","example":"0"},"params":{"type":["object","array"],"description":"The settings of the trigger, which depend on its type, for example the tag of a tagadd trigger. An empty array when the trigger has none.","items":{},"additionalProperties":true,"example":{"tag":"triggertag"}},"cdate":{"type":["string","null"],"format":"date-time","description":"When the trigger was created, in ISO 8601","example":"2026-10-15T10:52:26-05:00"},"mdate":{"type":["string","null"],"format":"date-time","description":"When the trigger was last changed, in ISO 8601","example":"2026-10-15T10:52:26-05:00"},"links":{"type":"array","description":"Always empty: the trigger has no related reads","items":{"type":"string"},"example":[]},"id":{"type":"string","description":"ID of the start trigger","example":"55"}}},"AutomationStep":{"description":"The progress steps the automation build emits while a run is running.","enum":["adding_steps","copying","creating","describing","editing","importing"],"title":"AutomationStep","type":"string"},"AutomationSummary":{"description":"The automation a run built or edited, as a caller reads it.\n\nRead from the run's stored result, which also carries the generated configuration; that stays\ninternal, so the published shape names only what a caller acts on.","properties":{"automation_id":{"title":"Automation Id","type":"integer"},"name":{"default":"","title":"Name","type":"string"},"description":{"default":"","title":"Description","type":"string"},"benefits":{"default":"","title":"Benefits","type":"string"},"operation":{"anyOf":[{"$ref":"#/components/schemas/AutomationOperation"},{"type":"null"}],"default":null},"truncated":{"default":false,"title":"Truncated","type":"boolean"},"emails_pending":{"default":false,"title":"Emails Pending","type":"boolean"},"emails":{"anyOf":[{"items":{"$ref":"#/components/schemas/AutomationEmailSummary"},"type":"array"},{"type":"null"}],"default":null,"title":"Emails"},"builder_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Automation builder URL for the automation, for MCP Apps openLink.","title":"Builder Url"}},"required":["automation_id"],"title":"AutomationSummary","type":"object"},"BetaOptInRequest":{"description":"The opt-in to store for the account.","required":["enabled"],"properties":{"enabled":{"description":"True to opt the account into the campaign generation beta, false to opt it out. Must be a JSON boolean; null is refused.","type":"boolean","example":true}},"type":"object"},"BetaOptInResponse":{"description":"Whether the account is opted into the campaign generation beta.","required":["enabled"],"properties":{"enabled":{"description":"True when the account is opted in. After a write, this is the value re-read from storage, not an echo of the request.","type":"boolean","example":true}},"type":"object"},"BlankEnum":{"enum":[""]},"BodyFileTypeEnum":{"enum":["URL","UPLOAD"],"type":"string","description":"* `URL` - Url\n* `UPLOAD` - Upload"},"BrandCandidateActiveRequest":{"description":"Which candidate to apply as the account's brand.","required":["candidateId"],"properties":{"candidateId":{"description":"Id of a candidate in the current set. Re-picking the committed candidate is allowed and changes nothing.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"}},"type":"object"},"BrandCandidateCommitRequest":{"description":"What made the customer commit. The body may be empty.","properties":{"trigger":{"description":"Why the candidate is being committed. keep, pick and send mean the customer took responsibility for the brand, so every field of the kit is stamped user-confirmed. Any other value, or no value, keeps the candidate's own source on the kit, which keeps the disclosure line offering a change. send is sent by Hosted itself on a campaign's first send.","type":"string","example":"keep"}},"type":"object"},"BrandCandidateCommitResponse":{"description":"The brand kit a commit produced, followed by the set it was committed from.","required":["brandkitUuid","created"],"type":"object","allOf":[{"$ref":"#/components/schemas/BrandCandidateSetResponse"},{"properties":{"brandkitUuid":{"description":"UUID of the brand kit created from the candidate. The same UUID is answered on every repeat of the same commit.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"created":{"description":"True when this call created the brand kit (201). False when the candidate had already been committed, or a retry adopted the kit an interrupted attempt wrote (200).","type":"boolean","example":true}},"type":"object"}]},"BrandCandidateFromAccountRequest":{"description":"Optional. Empty, or absent, for the ordinary build from the account details; a seedCandidateId makes the build a \"more like this\" refinement around that look.","properties":{"seedCandidateId":{"description":"A candidate id from the live set, or the UUID of one of the account's saved brand kits. When present the generated looks are proposed as neighbours of that look instead of alternatives to the saved brand, and the response is the refinement shape. Never blank when present.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"count":{"description":"How many generated looks the set shows, 3 to 5; 3 when absent. The lineup may come back smaller when proposals fail the gates.","type":["integer","null"],"maximum":5,"minimum":3,"example":3},"industry":{"description":"The account's industry as the caller read it from the account's customer context. A fallback only: used when the onboarding answer is missing or a placeholder such as \"Other\", and ignored otherwise; a placeholder here is ignored too. Plain build only, never blank when present, up to 100 characters.","type":["string","null"],"maxLength":100,"example":"Dental practice"}},"type":"object"},"BrandCandidateFromAccountResponse":{"description":"The candidates a model proposed from the account details, followed by the set they were added to.","required":["candidateIds","evidenceTier","seeded"],"type":"object","allOf":[{"$ref":"#/components/schemas/BrandCandidateSetResponse"},{"properties":{"candidateIds":{"description":"Ids of the llm-inferred candidates this call added to the set, in lineup order.","type":"array","items":{"type":"string"},"example":["018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b","018f3c2a-6c8e-7e4f-9a1b-2c3d4e5f6a7c"]},"evidenceTier":{"description":"How much the proposal had to go on: observed when a saved kit or an email palette anchored it, identified when the account named its business, labelled when only an industry label was known, none when there was nothing.","type":"string","enum":["observed","identified","labelled","none"],"example":"identified"},"seeded":{"description":"True when the proposal was built from a saved brand kit or the sent-campaigns candidate, so the looks are variations on it rather than invented from scratch.","type":"boolean","example":false}},"type":"object"}]},"BrandCandidateFromSendHistoryResponse":{"description":"The candidate read from the account's sent campaigns, followed by the set it was added to.","required":["candidateId","coverage","sampleSize"],"type":"object","allOf":[{"$ref":"#/components/schemas/BrandCandidateSetResponse"},{"properties":{"candidateId":{"description":"Id of the past-campaigns candidate this call added or replaced in the set.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"coverage":{"description":"For each brand field the sent-campaigns source looks for, whether enough campaigns agreed on a value.","type":"object","example":{"primary":true,"titleFont":false},"additionalProperties":{"type":"boolean"}},"sampleSize":{"description":"Number of sent campaigns the proposal was read from, after duplicates, placeholders and campaigns generated by AI were excluded. The per-field agreement figures on the candidate's evidence are shares of this.","type":"integer","example":12}},"type":"object"}]},"BrandCandidateFromWebsiteRequest":{"description":"The website to read a brand from.","required":["domain"],"properties":{"domain":{"description":"The site to read: a bare host or a full address; only the host is used. A social media profile or an email provider is refused, because reading it would yield that platform's brand.","type":"string","example":"acme.com"},"trigger":{"description":"What the customer did: rebrand when an account with a kit asked for a new look from its site, use-my-website when an account without one gave its address. Recorded on metrics; defaults to use-my-website.","type":"string","enum":["rebrand","use-my-website"],"example":"use-my-website"}},"type":"object"},"BrandCandidateFromWebsiteResponse":{"description":"The candidate read from the website, followed by the set it was added to.","required":["candidateId","scrapeOutcome","coverage"],"type":"object","allOf":[{"$ref":"#/components/schemas/BrandCandidateSetResponse"},{"properties":{"candidateId":{"description":"Id of the website-firecrawl candidate this call added or replaced in the set.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"scrapeOutcome":{"description":"Whether the site was read on this call (fetched, one scrape credit spent) or answered from the per-domain cache (cached, no credit spent).","type":"string","enum":["cached","fetched"],"example":"fetched"},"coverage":{"description":"For each brand field the website source looks for, whether the site provided it. A false means the candidate has no value for that field, not that the kit will.","type":"object","example":{"primary":true,"logo":false},"additionalProperties":{"type":"boolean"}}},"type":"object"}]},"BrandCandidateRefinementResponse":{"description":"The looks a model proposed around a chosen candidate or saved kit (\"more like this\"), followed by the fresh set they were written into.","required":["candidateIds","evidenceTier","seeded","seedCandidateId","refinedFromSetId"],"type":"object","allOf":[{"$ref":"#/components/schemas/BrandCandidateSetResponse"},{"properties":{"candidateIds":{"description":"Ids of the new llm-inferred looks, in lineup order. The seed and the carried-over candidates are not repeated here: the caller already holds them.","type":"array","items":{"type":"string"},"example":["018f3c2a-6c8e-7e4f-9a1b-2c3d4e5f6a7c"]},"evidenceTier":{"description":"How much the proposal had to go on; see the plain proposal response. A generated look re-anchored does not raise the tier, so it stays where the account's own evidence puts it.","type":"string","enum":["observed","identified","labelled","none"],"example":"identified"},"seeded":{"description":"Always true: a refinement is built around the seed.","type":"boolean","example":true},"seedCandidateId":{"description":"The seedCandidateId the request named, echoed back: a candidate id or a saved brand kit UUID.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"refinedFromSetId":{"description":"Id of the set the refinement was built from, whose candidates were carried into the new set as its lineup and history. Null when a saved kit was the seed and the account had no live set.","type":["string","null"],"example":"018f3c2a-0000-7e4f-9a1b-2c3d4e5f6a7b"}},"type":"object"}]},"BrandCandidateResource":{"description":"One proposed brand: kit values nobody has committed to yet. A candidate exists so a brand can be shown, previewed and picked without creating a brand kit.","required":["candidateId","source","kitBody","confidence","confidenceBasis","evidence","createdAt","role","label"],"properties":{"candidateId":{"description":"Id of the candidate, assigned by the server when the set is written.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"source":{"description":"Where the proposal came from: website-firecrawl for a read of the live site, past-campaigns for the account's sent campaigns, llm-inferred for a model's proposal from the account details. A candidate submitted by a caller carries whatever source it named; unknown is never claimed for a fresh write.","type":"string","enum":["website-scrape","past-campaigns","llm-inferred","user-provided","user-confirmed","default","unknown","website-firecrawl"],"example":"llm-inferred"},"kitBody":{"description":"A partial brand kit, in the same field names as Create a brand kit: only what the source found, so an absent colors, fonts or logos means the source could not find it. Keys the API does not model are returned exactly as written.","type":"object","example":{"name":"Acme","domain":"acme.com","colors":{"primary":"#112233"}},"additionalProperties":true},"confidence":{"description":"How sure the source is, between 0 and 1, on the scale confidenceBasis names. Null when the source records no number. Not comparable across different bases.","type":["number","null"],"format":"float","example":0.55},"confidenceBasis":{"description":"What confidence measures: sample-agreement is the share of sampled campaigns that carried the value, evidence-capped-self-report is a model's own figure capped by the evidence it was given, none means no number is recorded, unknown means a number arrived without its meaning. Rank candidates within one basis only.","type":"string","enum":["sample-agreement","evidence-capped-self-report","none","unknown"],"example":"evidence-capped-self-report"},"evidence":{"description":"What the proposal was derived from, in the source's own shape: the domain and field coverage for a website read, the sample and per-field agreement for sent campaigns, the account signals for a model proposal.","type":"object","example":{"domain":"acme.com","coverage":{"primary":true,"logo":false}},"additionalProperties":true},"createdAt":{"description":"When the candidate was proposed, ISO 8601 in UTC.","type":"string","format":"date-time","example":"2026-09-14T12:00:00Z"},"role":{"description":"Where the look sits in the Change look lineup: emails for the sent-campaigns palette when it earns its own card, calmer and bolder for the two model proposals built from a saved kit or an email palette, industry for the two built from neither. Null for every other candidate.","type":["string","null"],"enum":["emails","calmer","bolder","industry",null],"example":"calmer"},"label":{"description":"The look's name on its picker card, distinct within the set and never the business name. Null when role is null.","type":["string","null"],"example":"Copper Classic"}},"type":"object"},"BrandCandidateSetResponse":{"description":"The account's current set of proposed brands and which one is applied. One set per account, replaced wholesale. Hosted is the source of truth for activeCandidateId.","required":["setId","recommendedCandidateId","activeCandidateId","expiresAt","candidates","lineup","priorLineups","canRefine","committedCandidateId","committedBrandkitUuid","committedAt","plannedBrandkitUuid"],"properties":{"setId":{"description":"Id of the set. Changes whenever the set is replaced.","type":"string","example":"018f3c2a-0000-7e4f-9a1b-2c3d4e5f6a7b"},"recommendedCandidateId":{"description":"Id of the candidate the server recommends.","type":"string","example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"activeCandidateId":{"description":"Id of the candidate currently applied as the account's brand. Null when the set was built in the background and nothing has been chosen yet.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"expiresAt":{"description":"When the set stops being visible, ISO 8601 with a UTC offset. After this instant every read answers as if there were no set.","type":"string","format":"date-time","example":"2026-09-20T12:00:00Z"},"candidates":{"description":"The proposed brands, in the order they were written.","type":"array","items":{"$ref":"#/components/schemas/BrandCandidateResource"}},"lineup":{"description":"Ids of the candidates the picker shows as cards, in order. Candidates not listed here are history: looks from earlier \"more like this\" passes, kept so that a step back to them still resolves for pick, save and commit, and never drawn as cards of the current set. Every candidate, for any build but a refinement.","type":"array","items":{"type":"string"},"example":["018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"]},"priorLineups":{"description":"The lineups shown before this one, oldest first, as lists of candidate ids; at most three are kept. Empty for any build but a refinement.","type":"array","items":{"type":"array","items":{"type":"string"}},"example":[]},"canRefine":{"description":"Whether another \"more like this\" pass may be built from this set. False once three prior lineups are held, where a step back would stop resolving; a refinement asked for anyway is refused with 422.","type":"boolean","example":true},"committedCandidateId":{"description":"Id of the candidate a brand kit was, or is being, created from. Null until a commit is made. Once set, committing any other candidate is refused.","type":["string","null"],"example":null},"committedBrandkitUuid":{"description":"UUID of the brand kit created from committedCandidateId. Null until the commit has finished.","type":["string","null"],"format":"uuid","example":null},"committedAt":{"description":"When the commit was made, ISO 8601 in UTC. Null until a commit is made.","type":["string","null"],"format":"date-time","example":null},"plannedBrandkitUuid":{"description":"UUID the brand kit will have once an in-progress commit finishes. Internal bookkeeping that lets an interrupted commit be retried safely; clients can ignore it.","type":["string","null"],"format":"uuid","example":null}},"type":"object"},"BrandCandidatesWriteRequest":{"description":"A set of proposed brands to store for the account, replacing the one it has. Candidates are referred to by their position in candidates because their ids are assigned by the server.","required":["candidates","expiresAt","recommendedIndex"],"properties":{"candidates":{"description":"The proposed brands, at least one. Each entry is refused (422) when its source is not a known one, its kitBody is missing or cannot be built into a brand kit, or its kitBody names a social media profile or an email provider as the domain.","type":"array","items":{"required":["source","kitBody"],"properties":{"source":{"description":"Where the proposal came from. Any source except unknown.","type":"string","enum":["website-scrape","past-campaigns","llm-inferred","user-provided","user-confirmed","default","website-firecrawl"],"example":"llm-inferred"},"kitBody":{"description":"A partial brand kit, in the same field names as Create a brand kit: only what the source found.","type":"object","example":{"name":"Acme","colors":{"primary":"#112233"}},"additionalProperties":true},"confidence":{"description":"How sure the source is, between 0 and 1. Send confidenceBasis with it or the number is stored as unknown and cannot be ranked.","type":"number","format":"float","example":0.55},"confidenceBasis":{"description":"What confidence measures: sample-agreement or evidence-capped-self-report. Omit it, with confidence, when the source records no number.","type":"string","enum":["sample-agreement","evidence-capped-self-report","none"],"example":"evidence-capped-self-report"},"evidence":{"description":"What the proposal was derived from, in the source's own shape. Stored as given.","type":"object","example":{"signal":"account details"},"additionalProperties":true}},"type":"object"},"example":[{"source":"llm-inferred","kitBody":{"name":"Acme"},"confidence":0.55,"confidenceBasis":"evidence-capped-self-report","evidence":[]}]},"recommendedIndex":{"description":"Position in candidates of the one to recommend. 422 when it points at no submitted candidate.","type":"integer","example":0},"activeIndex":{"description":"Position in candidates of the one to apply as the account's brand. Defaults to recommendedIndex, so an account with a set always has a brand applied. 422 when it points at no submitted candidate.","type":"integer","example":0},"expiresAt":{"description":"When the set stops being visible: an absolute instant in the future with a Z or numeric UTC offset, such as 2026-09-21T12:00:00Z. A relative or timezone-less value, or one already in the past, is 422.","type":"string","format":"date-time","example":"2026-09-21T12:00:00Z"}},"type":"object"},"BrandHistoryChange":{"description":"One recorded change to a page between two scrapes.","required":["changedAt","diff","summarized"],"properties":{"changedAt":{"description":"When the change was recorded, ISO 8601 with a UTC offset.","type":"string","format":"date-time","example":"2026-07-05T10:00:00+00:00"},"diff":{"description":"What changed. A unified diff of the page markdown until the entry is summarized, then a short written summary of it.","type":"string","example":"@@ -1,3 +1,3 @@\\n-Spring sale: 20% off\\n+Summer sale: 30% off"},"summarized":{"description":"True once the diff has been replaced by a written summary.","type":"boolean","example":false}},"type":"object"},"BrandHistoryRequest":{"description":"The brand kit whose website history to scrape.","required":["brandkit_uuid"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"force":{"description":"True to scrape unconditionally. False skips a brand kit whose homepage was scraped within the last 24 hours.","type":"boolean","example":false},"image_run_id":{"description":"Id of the image scrape reservation made when this run was dispatched, so the worker can tell its own pending status from a later refresh's. Null for a run dispatched without one.","type":["string","null"],"example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"},"firecrawl_retry_attempts":{"description":"How many times to retry a failed page scrape on this run. Null keeps the scraper's default.","type":["integer","null"],"example":2}},"type":"object"},"BrandHistoryResponse":{"description":"The latest stored snapshot of the brand's homepage and how it has changed, with the important pages when includeSitePages is set.","required":["success","lastScrapedAt","markdown","history"],"properties":{"success":{"description":"Always true.","type":"boolean","example":true},"lastScrapedAt":{"description":"When the homepage was last scraped, as a UTC timestamp without an offset (Y-m-d H:i:s). This field keeps its older format; every other timestamp in the response is ISO 8601 with an offset.","type":"string","example":"2026-07-08 15:00:00"},"markdown":{"description":"The homepage content as markdown, from the last scrape.","type":"string","example":"# Acme\\n\\nSummer sale: 30% off all plans..."},"history":{"description":"Recorded changes to the homepage, newest first, capped at about 20,000 characters of diff text in total (older entries are dropped beyond that). Empty after the first scrape.","type":"array","items":{"$ref":"#/components/schemas/BrandHistoryChange"}},"sitePages":{"description":"The stored important pages of the website, without the homepage. Only present when includeSitePages is set; empty when none have been stored yet or they could not be read.","type":"array","items":{"$ref":"#/components/schemas/BrandHistorySitePage"}}},"type":"object"},"BrandHistorySitePage":{"description":"One stored important page of the brand's website, with the markdown captured by its last scrape and its recent changes.","required":["url","title","role","reason","markdown","scrapedAt","history"],"properties":{"url":{"description":"Address of the page.","type":"string","format":"uri","example":"https://acme.com/pricing"},"title":{"description":"Title of the page as scraped.","type":"string","example":"Pricing | Acme"},"role":{"description":"primary for the homepage, secondary for an important page found from it. The homepage is left out of sitePages because the top-level fields already carry it, so entries here are secondary.","type":"string","enum":["primary","secondary"],"example":"secondary"},"reason":{"description":"Why the page was judged important, in the model's words. Null when no reason was recorded.","type":["string","null"],"example":"Lists the plans and prices customers compare before buying."},"markdown":{"description":"The page content as markdown, from the last scrape.","type":"string","example":"# Pricing\\n\\nStarter: $29/month..."},"scrapedAt":{"description":"When the page was last scraped, ISO 8601 with a UTC offset.","type":"string","format":"date-time","example":"2026-07-08T15:00:00+00:00"},"history":{"description":"The page's five most recent changes, newest first. Empty when the page has been scraped once.","type":"array","items":{"$ref":"#/components/schemas/BrandHistoryChange"}}},"type":"object"},"BrandKit":{"type":"object","description":"A brand kit, in Hosted's own field names.","properties":{"id":{"type":"string","format":"uuid","description":"Brand kit UUID."},"brandkit":{"description":"The brand kit's manually authored fields, plus computed/response-only ones.","allOf":[{"$ref":"#/components/schemas/BrandKitData"}],"type":"object","properties":{"isPrimary":{"type":"boolean","description":"Whether this is the primary kit."},"uuid":{"type":"string","format":"uuid","description":"Same as the envelope's id."}}},"created_timestamp":{"type":"string"},"updated_timestamp":{"type":"string"}},"required":["id","brandkit"]},"BrandKitCreateRequest":{"description":"Provide exactly one of websiteUrl or brandData. If both are sent, brandData wins and websiteUrl is silently ignored.","oneOf":[{"type":"object","properties":{"websiteUrl":{"type":"string","description":"Public URL to extract brand data from."}},"required":["websiteUrl"]},{"type":"object","properties":{"brandData":{"allOf":[{"$ref":"#/components/schemas/BrandKitData"}],"type":"object","properties":{"competitors":{"type":"array","items":{"type":"string"},"description":"Up to 5 competitor names or domains. Triggers async enrichment. Not returned by Retrieve a brand kit; read it with Retrieve a brand kit's competitors."},"tone":{"type":"string","description":"Brand voice/tone. Triggers async enrichment. Not returned by Retrieve a brand kit; read it with Retrieve a brand kit's tone."},"websiteUrl":{"type":"string","description":"Website URL of the brand. When absent or empty, https:// followed by domain is stored instead."}}}},"required":["brandData"]}]},"BrandKitCreateResponse":{"type":"object","properties":{"brand":{"$ref":"#/components/schemas/BrandKit"}},"required":["brand"]},"BrandKitData":{"type":"object","description":"Manually authored brand kit fields.","properties":{"name":{"type":"string","description":"Brand/company name."},"shortDescription":{"type":"string","description":"One-line business description."},"longDescription":{"type":"string","description":"Longer business description."},"industries":{"type":"array","items":{"type":"string"}},"employeeCountRange":{"type":"string","description":"e.g. '11-50'."},"foundedYear":{"type":"integer"},"companyStructure":{"type":"string","description":"e.g. 'LLC'."},"companyLocation":{"type":"object","properties":{"city":{"type":"string"},"country":{"type":"string"},"countryCode":{"type":"string"},"region":{"type":"string"},"state":{"type":"string"},"subregion":{"type":"string"}}},"links":{"type":"array","description":"Social links.","items":{"type":"object","properties":{"name":{"type":"string","description":"e.g. 'twitter'."},"link":{"type":"string"}},"required":["name","link"]}},"colors":{"type":"object","description":"Color palette.","properties":{"primary":{"type":"string","description":"Hex, e.g. '#1A73E8'."},"lightBackground":{"type":"string","description":"Hex, light mode."},"darkBackground":{"type":"string","description":"Hex, dark mode."},"accents":{"type":"array","items":{"type":"string"},"description":"Hex accent colors."}}},"fonts":{"type":"object","description":"Brand fonts. Families must match the font catalogue; unrecognized values are dropped.","properties":{"titleFont":{"type":"string","description":"Title font family."},"bodyFont":{"type":"string","description":"Body font family."},"titleWeight":{"type":"string","description":"e.g. 'bold'."},"bodyWeight":{"type":"string","description":"e.g. 'normal'."}}},"language":{"type":"string","description":"e.g. 'english'."},"logos":{"type":"array","description":"Logo images, one per mode.","items":{"type":"object","properties":{"link":{"type":"string"},"mode":{"type":"string","enum":["light","dark"]},"fileId":{"type":"integer","description":"0 until the image is rehosted."}}}},"symbols":{"type":"array","description":"Symbol images, one per mode.","items":{"type":"object","properties":{"link":{"type":"string"},"mode":{"type":"string","enum":["light","dark"]},"fileId":{"type":"integer","description":"0 until the image is rehosted."}}}},"icons":{"type":"array","description":"Icon images, one per mode.","items":{"type":"object","properties":{"link":{"type":"string"},"mode":{"type":"string","enum":["light","dark"]},"fileId":{"type":"integer","description":"0 until the image is rehosted."}}}},"websiteUrl":{"type":"string","description":"The brand's website address, e.g. 'https://acme.com'."},"domain":{"type":"string","description":"e.g. 'acme.com'. Derived from websiteUrl when unset."},"brandkitName":{"type":"string","description":"Display name that tells same-named kits apart (language appended). Distinct from name."}}},"BrandKitPrimary":{"type":"object","description":"The primary brand kit, optionally with its site summary and stored page snapshots.","properties":{"id":{"type":"string","format":"uuid","description":"Brand kit UUID."},"brandkit":{"description":"The brand kit's manually authored fields, plus computed/response-only ones.","allOf":[{"$ref":"#/components/schemas/BrandKitData"}],"type":"object","properties":{"isPrimary":{"type":"boolean","description":"Whether this is the primary kit."},"siteSummary":{"type":"string","description":"LLM-generated site summary; only with includeSiteSummary."},"sitePages":{"type":"array","description":"Stored page snapshots the summary is built from; only with includeSitePages.","items":{"type":"object"}},"uuid":{"type":"string","format":"uuid","description":"Same as the envelope's id."}}},"created_timestamp":{"type":"string"},"updated_timestamp":{"type":"string"}},"required":["id","brandkit"]},"BrandKitUpdateRequest":{"type":"object","description":"The properties of the brand kit to change. A property left out keeps its stored value; one sent as null, an empty string or an empty list is cleared. Objects such as colors are merged key by key, and a list is replaced by the list sent.","properties":{"brandData":{"allOf":[{"$ref":"#/components/schemas/BrandKitData"}],"type":"object","properties":{"competitors":{"type":"array","items":{"type":"string"},"description":"Up to 5 competitor names or domains. Replaces the whole list, so to add or remove one, read the current list with Retrieve a brand kit's competitors and send the list you want; omit it to leave the current list unchanged. Triggers async enrichment. Not returned by Retrieve a brand kit."},"tone":{"type":"string","description":"Brand voice/tone. Triggers async enrichment. Not returned by Retrieve a brand kit; read it with Retrieve a brand kit's tone."},"websiteUrl":{"type":"string","description":"Website URL of the brand. When omitted the stored value is kept; when sent empty, https:// followed by domain is stored instead."}}}},"required":["brandData"]},"BrandfetchRefreshRequest":{"description":"The brand kit whose Brandfetch data to refresh.","required":["brandkit_uuid"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"force":{"description":"True to refresh even when the brand kit's Brandfetch data is less than 30 days old. False skips such a brand kit.","type":"boolean","example":false}},"type":"object"},"BrandfetchRefreshResponse":{"description":"The outcome of one Brandfetch refresh of a brand kit. A skip is reported as success so the queue does not retry it.","required":["success","result"],"properties":{"success":{"description":"Always true, including when the refresh was skipped.","type":"boolean","example":true},"result":{"description":"What the refresh did: refreshed (Brandfetch was read and compared with the brand kit), off (the refresh is switched off for the account), not_stale (the Brandfetch data is less than 30 days old and force was not set) or no_domain (the brand kit has no domain to look up).","type":"string","enum":["refreshed","off","not_stale","no_domain"],"example":"refreshed"}},"type":"object"},"BrandingJobResponse":{"description":"The outcome of one queued branding job. A skip is reported as success so the queue does not retry it.","required":["success"],"properties":{"success":{"description":"Always true, including when the job was skipped.","type":"boolean","example":true},"skipped":{"description":"True when the job was acknowledged without doing anything. Only the image scrape job sets it, for a legacy message without force; omitted otherwise.","type":"boolean","example":true}},"type":"object"},"BrandkitBackfillResponse":{"description":"What the one-time backfill did for the account.","required":["dispatched","brandkitUuids","alreadyBackfilled"],"properties":{"dispatched":{"description":"Number of brand kits a background extraction job was queued for. 0 when the backfill had already run, the account is excluded from it, or no kit needed it.","type":"integer","example":2},"brandkitUuids":{"description":"UUIDs of the brand kits a job was queued for.","type":"array","items":{"type":"string","format":"uuid"},"example":["0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"]},"alreadyBackfilled":{"description":"True when this backfill had already run for the account, so nothing was queued.","type":"boolean","example":false}},"type":"object"},"BrandkitCompetitorsExtractionRequest":{"description":"The brand kit whose competitors to extract.","required":["brandkit_uuid"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"BrandkitCompetitorsResponse":{"description":"The competitors of a brand kit and where their extraction stands.","required":["status","competitors"],"properties":{"status":{"description":"Where extraction stands. Only complete means the value is final; not_started, pending and failed mean it is not available yet.","type":"string","enum":["not_started","pending","complete","failed"]},"competitors":{"description":"Competitor names or domains. Empty when there are none or when they are not available yet; status says which.","type":"array","items":{"type":"string"}}},"type":"object"},"BrandkitImageMetadataRequest":{"description":"One image found on the brand's website, to judge and save.","required":["brandkit_uuid","scraped_url","record_id"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit the image belongs to. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"scraped_url":{"description":"Address of the image as found on the website. Must be https and reachable.","type":"string","format":"uri","example":"https://acme.com/images/hero.png"},"record_id":{"description":"UUID of the pending scraped-image record the outcome is written to.","type":"string","format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"}},"type":"object"},"BrandkitImageScrapeRequest":{"description":"The brand kit whose website images to scrape.","required":["brandkit_uuid"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"force":{"description":"True to wipe the stored image records and scrape the site again. False is acknowledged without doing anything, for messages queued by a retired producer.","type":"boolean","example":true},"image_run_id":{"description":"Id of the pending reservation made when this refresh was queued, so the worker can tell whether a later refresh has taken over. Null for a job queued before the id existed.","type":["string","null"],"example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"}},"type":"object"},"BrandkitImageSettings":{"description":"The image settings of a brand kit.","required":["autoAddImages"],"properties":{"autoAddImages":{"description":"Whether scheduled brand monitoring adds new website images to the brand kit. False for brand kits created before the option existed, until it is turned on. The first scrape and a manual refresh ignore it.","type":"boolean"}},"type":"object"},"BrandkitJobDispatchedResponse":{"description":"The brand kit a background job was queued for. Poll the matching read operation for progress.","required":["brandkitUuid"],"properties":{"brandkitUuid":{"description":"UUID of the brand kit, as given in the path.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"BrandkitMissingTemplatesResponse":{"description":"Which base templates were queued for generation, if any.","required":["message","dispatchedTemplates"],"properties":{"message":{"description":"Missing templates dispatched for generation with 201 when something was queued, No missing templates dispatched for generation with 200 otherwise.","type":"string","enum":["Missing templates dispatched for generation","No missing templates dispatched for generation"],"example":"Missing templates dispatched for generation"},"dispatchedTemplates":{"description":"Base template names queued; empty with the 200.","type":"array","items":{"type":"string"},"example":["boldheader","elegantambiance"]}},"type":"object"},"BrandkitScrapedImagesResponse":{"description":"Where the website image scrape of a brand kit stands, and the images it has added so far.","required":["status","imageStats","images"],"properties":{"status":{"description":"Where the scrape stands. not_started when no scrape has run, pending while images are still being fetched and judged, complete once every image has been processed, failed when the scrape job failed or outlived its timeout.","type":"string","enum":["not_started","pending","complete","failed"],"example":"complete"},"imageStats":{"description":"How many images the scrape found and what became of each.","required":["total","pending","complete","skipped","invalid","failed"],"properties":{"total":{"description":"Images still pending plus images that completed. Skipped, invalid and failed images are not counted.","type":"integer","example":9},"pending":{"description":"Images not yet fetched and judged.","type":"integer","example":3},"complete":{"description":"Images judged relevant and saved to the brand kit; these are the entries of images.","type":"integer","example":6},"skipped":{"description":"Images judged not relevant to the brand or not safe.","type":"integer","example":2},"invalid":{"description":"Images whose address could not be fetched as an allowed image, or that the model rejected.","type":"integer","example":1},"failed":{"description":"Images whose analysis or upload failed.","type":"integer","example":0}},"type":"object"},"images":{"description":"The completed images, most relevant first.","type":"array","items":{"required":["fileId","contentManagerUrl","relevanceScore"],"properties":{"fileId":{"description":"Id of the saved image in the content manager.","type":["integer","null"],"example":123},"contentManagerUrl":{"description":"Address of the saved image.","type":["string","null"],"format":"uri","example":"https://cdn.example.com/brand/acme-hero.png"},"relevanceScore":{"description":"How relevant the model judged the image to the brand, 0 to 100.","type":["integer","null"],"example":91}},"type":"object"}}},"type":"object"},"BrandkitTemplate":{"description":"One email template generated for a brand kit.","required":["uuid","slug","createdSuccessfully","templateId"],"properties":{"uuid":{"description":"UUID of the brand kit the template belongs to.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"slug":{"description":"Which base template and mode it is: the base template name followed by light or dark.","type":"string","enum":["welcomelight","welcomedark","promotelight","promotedark","monthlylight","monthlydark","whatsnewlight","whatsnewdark","announcementlight","announcementdark","letsmovelight","letsmovedark","cleanlight","cleandark","producthighlightlight","producthighlightdark","flashsalelight","flashsaledark","chillvibeslight","chillvibesdark","colorblockslight","colorblocksdark","fashioneditoriallight","fashioneditorialdark","flashsalecountdownlight","flashsalecountdowndark","boldheaderlight","boldheaderdark","freetrialcountdownlight","freetrialcountdowndark","elegantambiancelight","elegantambiancedark"],"example":"welcomelight"},"createdSuccessfully":{"description":"True when a template was saved; false when generation failed and templateId is 0.","type":"boolean","example":true},"templateId":{"description":"ID of the saved email template, 0 when generation failed.","type":"integer","example":1842}},"type":"object"},"BrandkitTemplateCreateWorkerRequest":{"description":"The job brand kit creation queues, one per base template: which template to generate for which kit. Sent only by Hosted's own background dispatcher.","required":["uuid","template"],"properties":{"uuid":{"description":"UUID of the brand kit.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"template":{"description":"Base template name to generate, in light and dark.","type":"string","enum":["welcome","promote","monthly","whatsnew","announcement","letsmove","flashsalecountdown","clean","producthighlight","elegantambiance","flashsale","chillvibes","colorblocks","fashioneditorial","boldheader","freetrialcountdown"],"example":"welcome"},"outputLang":{"description":"Language to write the template content in; omitted, the user's language.","type":["string","null"],"example":"en"},"startTime":{"description":"Unix time (with fraction) the brand kit generation started, for the latency metric; omitted, no metric is recorded.","type":["number","null"],"format":"float","example":1761220800.25},"process":{"description":"Why the template is being generated: create for a new kit, update after a kit edit, replace for a rebuild.","type":"string","enum":["create","update","replace"],"example":"create"},"brandkitUpdatedAt":{"description":"Timestamp of the brand kit version this job was queued for; a job for an older version than the stored kit is skipped.","type":["string","null"],"example":"2026-10-23 14:00:00"}},"type":"object"},"BrandkitTemplateCreatedResponse":{"description":"Both modes of the base template were generated and saved.","required":["templateIds"],"properties":{"templateIds":{"$ref":"#/components/schemas/BrandkitTemplateIds","description":"The saved templates."}},"type":"object"},"BrandkitTemplateIds":{"description":"The two templates one base template produces.","required":["light","dark"],"properties":{"light":{"description":"ID of the light-mode email template.","type":"integer","example":1842},"dark":{"description":"ID of the dark-mode email template.","type":"integer","example":1843}},"type":"object"},"BrandkitTemplatePreviewRequest":{"description":"Which base template to render and the brand kit to render it with.","required":["slug"],"properties":{"slug":{"description":"Base template and mode to render: the template name followed by light or dark.","type":"string","enum":["welcomelight","welcomedark","promotelight","promotedark","monthlylight","monthlydark","whatsnewlight","whatsnewdark","announcementlight","announcementdark","letsmovelight","letsmovedark","cleanlight","cleandark","producthighlightlight","producthighlightdark","flashsalelight","flashsaledark","chillvibeslight","chillvibesdark","colorblockslight","colorblocksdark","fashioneditoriallight","fashioneditorialdark","flashsalecountdownlight","flashsalecountdowndark","boldheaderlight","boldheaderdark","freetrialcountdownlight","freetrialcountdowndark","elegantambiancelight","elegantambiancedark"],"example":"welcomelight"},"brandkit":{"description":"The brand kit as a JSON object in the shape GET /ai/brand/{uuid} answers; rendered from this body, not from storage, so an unsaved kit can be previewed. Empty answers 400.","type":"object","example":{"name":"Acme","colors":{"primary":"#1a73e8"},"tone":"friendly"},"additionalProperties":true}},"type":"object"},"BrandkitTemplatePreviewResponse":{"description":"A rendered preview of one base template in the brand kit's colours and voice.","required":["html","css","usingPlaceholder","templateGenerationFailed"],"properties":{"html":{"description":"The template markup with the brand kit's content substituted in.","type":"string","example":"<table width=\"600\">...</table>"},"css":{"description":"The stylesheet that goes with html.","type":"string","example":".header{background:#1a73e8}"},"usingPlaceholder":{"description":"True when the copy is placeholder text rather than generated content (no stored content yet, or generation failed).","type":"boolean","example":false},"templateGenerationFailed":{"description":"True when the stored template for this slug failed to generate; a regeneration is then queued for a stored brand kit.","type":"boolean","example":false}},"type":"object"},"BrandkitTemplateSkippedResponse":{"description":"Nothing was written: a later save superseded this job, or another worker holds the lock for this template.","required":["skipped"],"properties":{"skipped":{"description":"Always true.","type":"boolean","enum":[true],"example":true}},"type":"object"},"BrandkitTemplatesMeta":{"description":"How many templates exist against how many could.","required":["totalAvailable","totalCompleted"],"properties":{"totalAvailable":{"description":"Templates that could exist: the number of slugs (32), times the number of brand kits seen when no uuid filters the list.","type":"integer","example":32},"totalCompleted":{"description":"Templates answered in the list.","type":"integer","example":30}},"type":"object"},"BrandkitTemplatesResponse":{"description":"The templates generated for one brand kit, or for all of them.","required":["templates","meta"],"properties":{"templates":{"description":"One entry per stored template; empty when none were generated yet.","type":"array","items":{"$ref":"#/components/schemas/BrandkitTemplate"}},"meta":{"$ref":"#/components/schemas/BrandkitTemplatesMeta","description":"Counts to show progress against."}},"type":"object"},"BrandkitToneExtractionRequest":{"description":"The brand kit whose tone to extract.","required":["brandkit_uuid"],"properties":{"brandkit_uuid":{"description":"UUID of the brand kit. Must exist on the calling account.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"BrandkitToneResponse":{"description":"The tone of a brand kit and where its extraction stands.","required":["status","tone","failureCode"],"properties":{"status":{"description":"Where extraction stands. Only complete means the value is final; not_started, pending and failed mean it is not available yet.","type":"string","enum":["not_started","pending","complete","failed"]},"tone":{"description":"The brand voice and tone. Empty when there is none or when it is not available yet; status says which.","type":"string"},"failureCode":{"description":"Why extraction failed, as a short code. Null when there is no failure to report.","type":["string","null"]}},"type":"object"},"BroadcastCreateRequest":{"type":"object","required":["name","body"],"properties":{"name":{"type":"string","description":"Name of the broadcast"},"address_id":{"type":"integer","nullable":true,"description":"ID for sender name"},"body":{"type":"string","description":"SMS message content"},"media_urls":{"type":"array","items":{"type":"string","format":"uri"},"description":"Media URLs for MMS"},"preview_url":{"type":"string","format":"uri"},"shorten_track_links_enabled":{"type":"boolean"},"status":{"type":"string","enum":["draft"]},"scheduled_date":{"type":"string","format":"date-time"},"sent_to_count":{"type":"integer"},"list_ids":{"type":"array","items":{"type":"integer"}},"segment_id":{"type":"string"},"custom_segment_id":{"type":"string","description":"custom segment id generated from segmentsV2 endpoint and passing in a valid audience","format":"uuid","nullable":true},"label_ids":{"type":"array","items":{"type":"integer"}}}},"BroadcastGenerateRequest":{"description":"What the new SMS broadcast should say.","required":["prompt","source","tone"],"properties":{"source":{"description":"Where the request comes from, recorded on the request: ai_index creates the broadcast.","type":"string","example":"ai_index"},"prompt":{"description":"What the message should say, in plain words.","type":"string","example":"Announce our spring sale on garden tools with 20% off this weekend"},"tone":{"description":"Voice to write in, one of the template content tones.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"}},"type":"object"},"BroadcastGenerateWorkerRequest":{"description":"The job POST /ai/broadcast/generation/generate queues. Sent only by Hosted's own background dispatcher.","required":["external_identifier","source","prompt","tone"],"properties":{"external_identifier":{"description":"UUID of the generation request record.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"source":{"description":"Where the request came from.","type":"string","example":"ai_index"},"prompt":{"description":"What the message should say.","type":"string","example":"Announce our spring sale on garden tools with 20% off this weekend"},"tone":{"description":"Voice to write in, one of the template content tones.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"}},"type":"object"},"BroadcastGenerationResultResponse":{"description":"The SMS broadcast was written and saved.","required":["status","message"],"properties":{"status":{"description":"Always success; a failure is an error status instead.","type":"string","enum":["success"],"example":"success"},"message":{"description":"Broadcast created successfully when the source is ai_index (a new broadcast), Broadcast updated successfully otherwise.","type":"string","enum":["Broadcast created successfully","Broadcast updated successfully"],"example":"Broadcast created successfully"}},"type":"object"},"BroadcastGenerationStartedResponse":{"description":"The request was recorded and its job queued.","required":["requestId"],"properties":{"requestId":{"description":"UUID of the generation request; poll GET /ai/broadcast/generation/{requestId} with it.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"BroadcastGenerationUpdateRequest":{"description":"Which SMS broadcast to rewrite and the fields to set with it.","required":["prompt","source","tone","broadcastId"],"properties":{"source":{"description":"Where the request comes from, recorded on the request (ai_builder or sms_index).","type":"string","example":"ai_builder"},"prompt":{"description":"What the message should say, in plain words.","type":"string","example":"Make it shorter and mention free shipping"},"tone":{"description":"Voice to write in, one of the template content tones.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"broadcastId":{"description":"ID of the SMS broadcast to update.","type":"integer","example":5120},"body":{"description":"Current message body, given to the model as the starting point.","type":["string","null"],"example":"Spring sale! 20% off garden tools this weekend."},"name":{"description":"Name to set on the broadcast.","type":["string","null"],"example":"Spring sale SMS"},"addressId":{"description":"ID of the sending address to set.","type":["integer","null"],"example":3},"listIds":{"description":"IDs of the lists to send to.","type":"array","items":{"type":"integer"},"example":[12,15]},"segmentId":{"description":"ID of the segment to send to.","type":["string","null"],"example":"77"},"customSegmentId":{"description":"ID of the custom segment to send to.","type":["string","null"],"example":"9f1c"},"customRunId":{"description":"ID of the custom segment run to send to.","type":["string","null"],"example":"run_51"},"scheduledDate":{"description":"When to send, as the SMS broadcast API accepts it.","type":["string","null"],"example":"2026-11-02T15:00:00+00:00"}},"type":"object"},"BroadcastList":{"properties":{"id":{"description":"ID of the list.","type":"integer"},"name":{"description":"Name of the list.","type":"string"},"subscriber_count":{"description":"Number of active subscribers on the list, 0 when the list has none counted yet.","type":"integer"}},"type":"object"},"BroadcastListResponse":{"type":"object","properties":{"broadcasts":{"type":"array","items":{"$ref":"#/components/schemas/BroadcastMessage"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of broadcasts"}}}}},"BroadcastListsResponse":{"properties":{"lists":{"description":"The SMS lists the requesting user may use, ordered by name.","type":"array","items":{"$ref":"#/components/schemas/BroadcastList"}},"meta":{"description":"Information about this page of results.","properties":{"total":{"description":"Number of lists in this response. It counts the lists returned on this page, not every list the user can see.","type":"integer"}},"type":"object"}},"type":"object"},"BroadcastMessage":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the broadcast"},"name":{"type":"string","description":"Name of the broadcast"},"address_id":{"type":"integer","nullable":true,"description":"ID used to get sender name"},"body":{"type":"string","description":"SMS message content"},"media_urls":{"type":"array","items":{"type":"string","format":"uri"},"description":"Media URLs for MMS messages"},"preview_url":{"type":"string","format":"uri","description":"URL for message preview"},"shorten_track_links_enabled":{"type":"boolean","description":"Whether link shortening is enabled"},"status":{"type":"string","enum":["draft","scheduled","sent","pending_review","sending"],"description":"Current status of the broadcast"},"sent_date":{"type":"string","format":"date-time","nullable":true,"description":"Date when broadcast was sent"},"scheduled_date":{"type":"string","format":"date-time","nullable":true,"description":"Scheduled send date (UTC)"},"custom_run_id":{"type":"string","format":"uuid","nullable":true,"description":"custom run id generated from segmentMatchSome endpoint"},"custom_segment_id":{"type":"string","format":"uuid","nullable":true,"description":"custom segment id generated from segmentsV2 endpoint and passing in a valid audience"},"scheduled_by":{"type":"integer","nullable":true,"description":"User ID who scheduled the broadcast"},"sent_to_count":{"type":"integer","nullable":true,"description":"Number of recipients"},"created_at":{"type":"string","format":"date-time","description":"Creation timestamp"},"created_by":{"type":"integer","description":"User ID who created the broadcast"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"updated_by":{"type":"integer","description":"User ID who last updated"},"deleted_at":{"type":"string","format":"date-time","nullable":true,"description":"Deletion timestamp (for soft deletes)"},"sift_approved":{"type":"integer","description":"Sift approval status"},"arc_approved":{"type":"integer","description":"ARC approval status"},"quiet_hours_enabled":{"type":"integer","nullable":true,"description":"Whether quiet hours are enabled"},"list_ids":{"type":"array","items":{"type":"integer"},"description":"Associated list IDs"},"segment_id":{"type":"string","nullable":true,"description":"Segment ID (can be UUID or integer string)"},"label_ids":{"type":"array","items":{"type":"integer"},"nullable":true,"description":"Associated label IDs"}}},"BroadcastMetrics":{"properties":{"id":{"description":"ID of the broadcast the figures belong to.","type":"integer"},"sends":{"description":"Number of messages sent for the broadcast in the date range.","type":"integer"},"deliveries":{"description":"Number of those messages that were delivered.","type":"integer"},"replies":{"description":"Number of replies received to the broadcast.","type":"integer"},"failures":{"description":"Number of messages that failed to send.","type":"integer"},"optOuts":{"description":"Number of recipients who opted out after the broadcast.","type":"integer"},"clicks":{"description":"Number of clicks on links in the broadcast.","type":"integer"},"revenue":{"description":"Revenue attributed to the broadcast in the requested currency. Present only when SMS attribution is enabled for the account, and 0 unless currency is given.","type":"number","format":"float"}},"type":"object"},"BroadcastMetricsResponse":{"properties":{"metrics":{"description":"The figures of each requested broadcast.","type":"array","items":{"$ref":"#/components/schemas/BroadcastMetrics"}}},"type":"object"},"BroadcastUpdateRequest":{"type":"object","properties":{"name":{"type":"string"},"address_id":{"type":"integer","nullable":true},"body":{"type":"string"},"media_urls":{"type":"array","items":{"type":"string","format":"uri"}},"preview_url":{"type":"string","format":"uri"},"shorten_track_links_enabled":{"type":"boolean"},"status":{"type":"string","description":"Status of the broadcast. pending_review starts kicks off the broadcast to be sent","enum":["draft","pending_review"]},"scheduled_date":{"type":"string","format":"date-time"},"sent_to_count":{"type":"integer"},"list_ids":{"type":"array","items":{"type":"integer"}},"segment_id":{"type":"string"},"custom_run_id":{"type":"string","description":"custom run id generated from segmentMatchSome endpoint and passing a valid segment id","format":"uuid","nullable":true},"custom_segment_id":{"type":"string","description":"custom segment id generated from segmentsV2 endpoint and passing in a valid audience","format":"uuid","nullable":true},"label_ids":{"type":"array","items":{"type":"integer"}}}},"BroadcastUpdateWorkerRequest":{"description":"The job PUT /ai/broadcast/generation/update queues. Sent only by Hosted's own background dispatcher.","required":["external_identifier","source","prompt","tone","broadcast_id"],"properties":{"external_identifier":{"description":"UUID of the generation request record.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"source":{"description":"Where the request came from.","type":"string","example":"ai_builder"},"prompt":{"description":"What the message should say.","type":"string","example":"Make it shorter and mention free shipping"},"tone":{"description":"Voice to write in, one of the template content tones.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"broadcast_id":{"description":"ID of the SMS broadcast to update.","type":"integer","example":5120},"body":{"description":"Current message body.","type":["string","null"],"example":"Spring sale! 20% off garden tools this weekend."},"name":{"description":"Name to set on the broadcast.","type":["string","null"],"example":"Spring sale SMS"},"address_id":{"description":"ID of the sending address to set.","type":["integer","null"],"example":3},"list_ids":{"description":"IDs of the lists to send to.","type":"array","items":{"type":"integer"},"example":[12,15]},"segment_id":{"description":"ID of the segment to send to.","type":["string","null"],"example":"77"},"custom_segment_id":{"description":"ID of the custom segment to send to.","type":["string","null"],"example":"9f1c"},"custom_run_id":{"description":"ID of the custom segment run to send to.","type":["string","null"],"example":"run_51"},"scheduled_date":{"description":"When to send.","type":["string","null"],"example":"2026-11-02T15:00:00+00:00"}},"type":"object"},"BulkMemoryRequest":{"description":"The complete set of memories to save for the user.","required":["memories"],"properties":{"memories":{"description":"Every memory the user should have. An empty array deletes them all.","type":"array","items":{"$ref":"#/components/schemas/MemoryRequest"}}},"type":"object"},"BulkPermissionRulesRequest":{"description":"The permission rules to merge into the user's stored rules.","required":["rules"],"properties":{"rules":{"description":"The rules to save, at most 200.","type":"array","items":{"$ref":"#/components/schemas/PermissionRuleRequest"}}},"type":"object"},"BusinessGoalAgentAsset":{"description":"One asset linked to a business goal (InitiativeAgentAsset::jsonSerialize()). `id` is the asset's own id (seriesid/campaignid/formid/broadcast id); `relId`, where present, is the id of the folder-relation row linking it to the business goal.","required":["id","name"],"properties":{"id":{"description":"The asset's own id: the automation, campaign, form or SMS broadcast id.","type":"integer"},"name":{"description":"The asset's name.","type":"string"},"relId":{"description":"Omitted when not set. Never present for SMS assets.","type":"integer"},"status":{"description":"Omitted when not set. For automations: draft/active/inactive/paused. For campaigns: draft/scheduled/preparing/paused/stopped/complete/disabled/approval. Forms never carry a status. SMS carries the broadcast's own raw status string.","type":"string"}},"type":"object"},"BusinessGoalAgentAssets":{"description":"Assets linked to a business goal, grouped by kind (InitiativeAgentAssetData::jsonSerialize()). Always has all four keys, each an array that may be empty.","required":["automations","campaigns","forms","sms"],"properties":{"automations":{"description":"Automations labeled with this business goal.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentAsset"}},"campaigns":{"description":"Campaigns labeled with this business goal.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentAsset"}},"forms":{"description":"Form assets never carry a `status` (not supplied by InitiativeAgentAsset::fromFormFolder()).","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentAsset"}},"sms":{"description":"SMS broadcast assets never carry a `relId` (InitiativeAgentAsset::fromBroadcastMessage() always passes null), and their `status` is the raw broadcast status string rather than one of the mapped values used for automations/campaigns.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentAsset"}}},"type":"object"},"BusinessGoalAgentConversion":{"description":"One conversion linked to a business goal (InitiativeAgentConversionData::jsonSerialize()).","required":["id","name","count"],"properties":{"id":{"description":"The conversion's id.","oneOf":[{"type":"integer"},{"type":"string"}]},"name":{"description":"The conversion's name.","type":"string"},"value":{"description":"The monetary value assigned to the conversion, not the number of times it fired. Omitted when not set.","type":"number"},"currency":{"description":"Omitted when not set.","type":"string"},"count":{"description":"The lifetime (all-time) number of times this conversion has fired. Not scoped to any date range. Always present, unlike value/currency/target.","type":"integer"},"target":{"description":"A human-readable description of the goal's target for this conversion, e.g. \"Reach $1,000.00 value by 2026-12-31\" or \"Reach 10 conversion count\". Formatted server-side, not a structured value. Present only when the conversion's linked conversion folder has a goal_type set.","type":"string"},"conversionEvents":{"description":"The segment-based triggers that fire this conversion. Only present (and only non-empty) when fetched via GET /businessGoals/data/{initiativeId} -- always omitted on the list endpoint.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentConversionEvent"}}},"type":"object"},"BusinessGoalAgentConversionEvent":{"description":"A segment-based trigger for a conversion (InitiativeAgentConversionTriggerData::jsonSerialize()). Only SEGMENT_EVENT_TYPE triggers with a segment_id are ever produced.","required":["event","id","type","modifier","value","dynamic","retroactive","meta"],"properties":{"event":{"description":"A human-readable description of the segment that fires this trigger (SegmentParser::parseSegmentToText()).","type":"string"},"id":{"description":"The trigger's id, serialized as a string.","type":"string"},"type":{"description":"The trigger type. Only the segment-event type is ever surfaced here.","type":"string"},"modifier":{"description":"How the trigger's value is matched, for example `matches` or `contains`.","type":"string"},"value":{"description":"The trigger's stored value, which the modifier is compared against.","type":"string"},"dynamic":{"description":"1 when the conversion value is passed in with the event that fires the trigger, 0 when the conversion's own value is used. Only event, manual and ecommerce triggers read it.","type":"integer"},"retroactive":{"description":"True when the trigger also converts contacts for activity that happened before it was created.","type":"boolean"},"meta":{"description":"Opaque trigger metadata. Shape is not constrained by this endpoint (ConversionTrigger::$meta is untyped); may be any JSON value or null.","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"object"},{"type":"array","items":{}},{"type":"null"}]},"segmentId":{"description":"Omitted when not set.","type":"string"},"segmentConfig":{"description":"The raw segment definition fetched from SegmentV2Service, decoded as JSON. Shape is the Segments v2 definition format and is not re-declared here. Omitted when not set.","type":"object"}},"type":"object"},"BusinessGoalAgentData":{"description":"A single business goal as served by the agent-data endpoints (InitiativeAgentData::jsonSerialize()). The underlying record is an Initiative, stored as a Folder row.","required":["id","name","description","color","creationSource","isFavorite","isArchived","conversions","assets"],"properties":{"id":{"description":"The business goal's id.","oneOf":[{"type":"integer"},{"type":"string"}]},"name":{"description":"The business goal's name. Sourced from the underlying Folder's `folder` column, not a `name` column.","type":"string"},"description":{"description":"The business goal's description.","type":"string"},"color":{"description":"Color of the goal's folder, as a hex code without the leading #.","type":"string"},"creationSource":{"description":"Human-readable label for how the goal was created (Folder::getSourceNameByCode()).","type":"string"},"isFavorite":{"description":"True when the goal is marked as a favorite.","type":"boolean"},"isArchived":{"description":"True when the goal is archived.","type":"boolean"},"targetEndDate":{"description":"Present only when the goal has useTargetEndDate enabled; omitted entirely otherwise (never sent as null).","type":"string","format":"date"},"conversions":{"description":"Always present. Empty when the goal has no linked conversions.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentConversion"}},"assets":{"description":"Always present. On the list endpoint, every list inside is empty unless includeAssets=true was passed; on the single-goal endpoint, always populated.","allOf":[{"$ref":"#/components/schemas/BusinessGoalAgentAssets"}]}},"type":"object"},"BusinessGoalAgentListResponse":{"description":"Returned directly from InitiativeAgentDataService::getInitiatives().","required":["businessGoals","totalActive","totalArchived"],"properties":{"businessGoals":{"description":"The business goals on this page.","type":"array","items":{"$ref":"#/components/schemas/BusinessGoalAgentData"}},"totalActive":{"description":"Count of non-archived business goals matching the current filters.","type":"integer"},"totalArchived":{"description":"Count of archived business goals matching the current filters.","type":"integer"}},"type":"object"},"CalendarUserSyncRequest":{"type":"object","description":"The calendar feed and a list of user IDs, in the Ember Data RESTSerializer shape the app sends","required":["calendar","calendarUser"],"properties":{"calendar":{"type":["integer","string"],"description":"ID of the calendar feed","example":"1"},"calendarUser":{"type":"array","description":"User IDs. Every entry must be a non-zero number, or the request is refused. An empty list is allowed.","items":{"type":["integer","string"]},"example":["2","3"]}}},"CalendarUserSyncResult":{"type":"object","description":"The calendar users this request created, and the IDs of those it deleted","properties":{"calendarUsers":{"type":"array","description":"The relations this request created; empty when every requested relation already existed","items":{"type":"object","properties":{"id":{"type":["string","integer"],"description":"ID of the calendar user relation","example":"5"},"calendar":{"type":["string","integer"],"description":"ID of the calendar feed","example":"1"},"user":{"type":["string","integer"],"description":"ID of the user","example":2},"cdate":{"type":"string","description":"When the relation was created, ISO 8601 with offset","example":"2018-11-15T22:26:35-06:00"},"mdate":{"type":"string","description":"When the relation was last changed, ISO 8601 with offset","example":"2018-11-15T22:26:35-06:00"},"links":{"type":"object","description":"URLs of the related calendar feed and user","properties":{"calendar":{"type":"string","description":"URL of the calendar feed","example":"https://:account.api-us1.com/api/:version/calendarUsers/5/calendar"},"user":{"type":"string","description":"URL of the user","example":"https://:account.api-us1.com/api/:version/calendarUsers/5/user"}}}}}},"meta":{"type":"object","description":"Present only when the request deleted relations","properties":{"deletedCalendarUserIds":{"type":"array","description":"IDs of the calendar user relations (not of the users) this request deleted","items":{"type":["string","integer"]},"example":["4"]}}}}},"CampaignApprovalResult":{"type":"object","description":"Outcome of continuing a campaign after its approval.","required":["message","code"],"properties":{"message":{"type":"string","description":"What happened, in English.","example":"Campaign has been approved."},"code":{"type":"integer","enum":[0,1,2],"description":"0 when the approval was accepted, 1 when the hash was refused (permanent, do not retry), 2 on a temporary failure (retry).","example":0}}},"CampaignAttachedMessage":{"description":"One message attached to a campaign: the campaign message association and the sending statistics kept on it. Every column comes back as a string.","properties":{"id":{"description":"ID of the campaign message association.","type":"string","example":"1"},"campaignid":{"description":"ID of the campaign.","type":"string","example":"1"},"messageid":{"description":"ID of the message this association sends.","type":"string","example":"3"},"percentage":{"description":"Share of the campaign's recipients this message is sent to, for a split (A/B) campaign.","type":"string","example":"50"},"initial_split_percentage":{"description":"The split percentage this message started with.","type":"string","example":"50"},"sourcesize":{"description":"Size of the source list at send time.","type":"string","example":"0"},"send_amt":{"description":"Number of sends attempted for this message.","type":"string","example":"500"},"total_amt":{"description":"Number of sends delivered for this message.","type":"string","example":"500"},"opens":{"description":"Total opens, including repeat opens.","type":"string","example":"241"},"uniqueopens":{"description":"Number of contacts who opened at least once.","type":"string","example":"180"},"verified_opens":{"description":"Opens confirmed as human.","type":"string","example":"160"},"verified_unique_opens":{"description":"Unique opens confirmed as human.","type":"string","example":"150"},"linkclicks":{"description":"Total link clicks, including repeat clicks.","type":"string","example":"64"},"uniquelinkclicks":{"description":"Number of distinct links clicked.","type":"string","example":"51"},"subscriberclicks":{"description":"Number of contacts who clicked at least one link.","type":"string","example":"48"},"forwards":{"description":"Total forwards.","type":"string","example":"2"},"uniqueforwards":{"description":"Number of contacts who forwarded at least once.","type":"string","example":"2"},"hardbounces":{"description":"Number of hard bounces.","type":"string","example":"1"},"softbounces":{"description":"Number of soft bounces.","type":"string","example":"3"},"unsubscribes":{"description":"Number of unsubscribes.","type":"string","example":"2"},"unsubreasons":{"description":"Number of unsubscribes that included a reason.","type":"string","example":"1"},"updates":{"description":"Number of contacts who updated their profile.","type":"string","example":"0"},"socialshares":{"description":"Number of social shares.","type":"string","example":"0"},"replies":{"description":"Total replies.","type":"string","example":"5"},"uniquereplies":{"description":"Number of contacts who replied at least once.","type":"string","example":"4"},"spamcheck_score":{"description":"Spam check score; -1 when the message has not been checked.","type":"string","example":"-1"},"spamcheck_max":{"description":"Maximum possible spam check score.","type":"string","example":"0"},"repair_timestamp":{"description":"When the statistics of this row were last repaired; null when they never were.","type":["string","null"],"example":null},"screenshot":{"description":"URL of the rendered preview image of the message.","type":"string","example":"//:account.img-us3.com/_screenshot_/915e875e-c68f-4683-9ee9-5e18f947a5fd.jpeg"},"subject":{"description":"Subject line of the message.","type":"string","example":"Your journey starts here"},"links":{"description":"API URLs of the related records.","properties":{"campaign":{"description":"URL of the campaign.","type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/campaign"},"message":{"description":"URL of the message.","type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/message"}},"type":"object"},"campaign":{"description":"ID of the related campaign; the same value as campaignid.","type":"string","example":"1"},"message":{"description":"ID of the related message; the same value as messageid.","type":"string","example":"3"}},"type":"object"},"CampaignAttachedMessageItem":{"description":"One message attached to a campaign, under campaignMessage.","required":["campaignMessage"],"properties":{"campaignMessage":{"$ref":"#/components/schemas/CampaignAttachedMessage","description":"The campaign message association."}},"type":"object"},"CampaignAttachedMessageList":{"description":"One page of the messages attached to a campaign.","required":["campaignMessages","meta"],"properties":{"campaignMessages":{"description":"The campaign message associations of the campaign on this page. Empty when there are none.","type":"array","items":{"$ref":"#/components/schemas/CampaignAttachedMessage"}},"campaigns":{"description":"The campaigns the listed associations belong to, as GET /campaigns/{id} returns them. Present only when include names campaign.","type":"array","items":{"type":"object"}},"messages":{"description":"The messages the listed associations send, as GET /messages/{id} returns them. Present only when include names message.","type":"array","items":{"type":"object"}},"meta":{"description":"Paging information.","required":["total"],"properties":{"total":{"description":"Number of the campaign's associations the request matches, across every page.","type":"integer","example":2}},"type":"object"}},"type":"object"},"CampaignCadence":{"description":"One campaign creator's sending cadence over the last 26 full weeks.","required":["user_id","name","label","median_gap_days","campaign_count","last_campaign_at","usual_day","usual_day_of_month","usual_hour","recent_campaigns"],"properties":{"user_id":{"description":"ID of the user who created the campaigns.","type":"integer","example":3},"name":{"description":"The creator's first and last name; null when the user no longer exists or has no name.","type":["string","null"],"example":"Ana Pérez"},"label":{"description":"dormant: no send in the last 8 weeks. insufficient_history: fewer than 4 send days. weekly, biweekly, monthly: median gap between send days of 5–9, 12–16 or 26–35 days with a coefficient of variation below 0.5. multi_weekly: median gap under 5 days and sends in at least 60% of weeks. sporadic: anything else.","type":"string","enum":["dormant","insufficient_history","weekly","biweekly","monthly","multi_weekly","sporadic"],"example":"weekly"},"median_gap_days":{"description":"Median number of days between send days, rounded to one decimal; null with a single send day.","type":["number","null"],"format":"float","example":7},"campaign_count":{"description":"Number of campaigns the creator sent in the window.","type":"integer","example":24},"last_campaign_at":{"description":"When the latest campaign was sent, ISO 8601 in the account time zone.","type":"string","example":"2026-10-19T10:02:00-04:00"},"usual_day":{"description":"Weekly and biweekly creators only: the weekday of at least half the send days, when no other weekday ties it; otherwise null.","type":["string","null"],"enum":["monday","tuesday","wednesday","thursday","friday","saturday","sunday"],"example":"monday"},"usual_day_of_month":{"description":"Monthly creators only: the most frequent day of the month, when at least half the send days fall within one day of it; otherwise null.","type":["integer","null"],"example":null},"usual_hour":{"description":"Hour (0–23) of the first send of at least half the send days, when no other hour ties it; otherwise null.","type":["integer","null"],"example":10},"recent_campaigns":{"description":"The creator's latest 3 campaigns, newest first.","type":"array","items":{"$ref":"#/components/schemas/CampaignCadenceRecentCampaign"}}},"type":"object"},"CampaignCadenceRecentCampaign":{"description":"One of the latest campaigns a creator sent.","required":["name","subject","sent_at"],"properties":{"name":{"description":"Campaign name.","type":"string","example":"Weekly newsletter #42"},"subject":{"description":"Subject of the campaign's first message; null when it has none.","type":["string","null"],"example":"This week at Acme"},"sent_at":{"description":"When it was sent, ISO 8601 in the account time zone.","type":"string","example":"2026-10-19T10:02:00-04:00"}},"type":"object"},"CampaignDomainValidationTokenResult":{"type":"object","properties":{"meta":{"type":"object","description":"The outcome.","properties":{"success":{"type":"boolean","description":"Whether the domain is now verified. True, despite the 422, when `token` or `domain` is missing.","example":true},"message":{"type":"string","enum":["Invalid Token or Domain","Token Expired","Domain Not Verified"],"description":"Why the domain was not verified: no matching token or unverified domain, a token more than 7 days old, or the domain could not be saved. Present only on failure.","example":"Token Expired"},"redirect_url":{"type":"string","description":"Where the verification email asked to send the user afterwards, when the request that sent it named one. Present on success and on an expired token.","example":"https://app.example.com/settings"}}}}},"CampaignEditResultsCampaign":{"description":"The campaign the edited message belongs to.","required":["id","name","type","canSplitContent"],"properties":{"id":{"description":"Id of the campaign.","type":"integer","example":4821},"name":{"description":"Name of the campaign.","type":"string","example":"October newsletter"},"type":{"description":"Campaign type as stored on the campaign.","type":"string","example":"single"},"canSplitContent":{"description":"Always false: this flow edits a single campaign, never a split test.","type":"boolean","example":false}},"type":"object"},"CampaignEditResultsMessage":{"description":"The campaign message after the edit, as stored.","required":["campaignId","id","subject","preHeader","fromEmail","fromName","replyToEmail","format"],"properties":{"campaignId":{"description":"Id of the campaign the message belongs to.","type":"integer","example":4821},"id":{"description":"Id of the message.","type":"integer","example":9134},"subject":{"description":"Subject line after the edit.","type":["string","null"],"example":"Your October picks are here"},"preHeader":{"description":"Preheader text after the edit.","type":["string","null"],"example":"New arrivals, member offers and more"},"fromEmail":{"description":"Sender address of the message.","type":["string","null"],"example":"hello@example.com"},"fromName":{"description":"Sender name of the message.","type":["string","null"],"example":"Example Shop"},"replyToEmail":{"description":"Reply-to address of the message.","type":["string","null"],"example":"support@example.com"},"format":{"description":"Message format as stored: html, text or mime.","type":["string","null"],"example":"mime"}},"type":"object"},"CampaignEditResultsResponse":{"description":"The edited campaign and message, and what the edit was styled and sourced from.","required":["campaign","message","brandkitUuid","summarizationUuid"],"properties":{"campaign":{"$ref":"#/components/schemas/CampaignEditResultsCampaign","description":"The campaign the edited message belongs to."},"message":{"$ref":"#/components/schemas/CampaignEditResultsMessage","description":"The message after the edit."},"brandkitUuid":{"description":"UUID of the brand kit stored on the edit request, or null when none was applied.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of the content summarization the last edit drew on, or null when none.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"}},"type":"object"},"CampaignEditRevertErrorResponse":{"description":"Why the queued revert did not run.","required":["message"],"properties":{"message":{"description":"What stopped the revert.","type":"string","example":"Stuck at editing. Cancelling revert request."}},"type":"object"},"CampaignEditRevertStatusResponse":{"description":"Outcome of a revert: whether the original email is back in place or the revert is waiting on a running edit.","required":["status"],"properties":{"status":{"description":"reverted: the message markup, subject and preheader are restored to what was stored before the edits and the request is back to classified. reverting: an edit is still running, so the revert was queued and runs once the request reaches done or error.","type":"string","enum":["reverted","reverting"],"example":"reverted"}},"type":"object"},"CampaignEditStatusResponse":{"description":"An AI campaign edit request and the stage it is at.","required":["requestId","status"],"properties":{"requestId":{"description":"UUID of the edit request; every later call names the request by it.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"status":{"description":"Stage of the request. pending: record created, parsing not finished. classifying: the text blocks are queued for classification. classified: the blocks are classified and the email is ready to edit; also the state a revert restores. editing: an edit or template swap is queued or running. done: the edit was applied to the message. error: a step failed.","type":"string","enum":["pending","classifying","classified","editing","done","error"],"example":"classifying"}},"type":"object"},"CampaignEditWorkerDoneResponse":{"description":"Acknowledgement that the queued job rewrote the message and marked the edit request done.","required":["status"],"properties":{"status":{"description":"Always Successful.","type":"string","enum":["Successful"],"example":"Successful"}},"type":"object"},"CampaignEditWorkerErrorResponse":{"description":"The queued job failed. The edit request is marked error; the message was not changed by this job.","required":["error"],"properties":{"error":{"description":"What failed, in fixed wording per job.","type":"string","enum":["Unable to classify email blocks","Unable to edit email content","Unable to classify new html for template swap","Unable to swap templates for email"],"example":"Unable to edit email content"}},"type":"object"},"CampaignFollowupCreatedResponse":{"description":"The automation created for the followup, whose email is still being generated.","required":["seriesId"],"properties":{"seriesId":{"description":"Id of the new automation (series). Poll GET /ai/campaigns/followup/status/{seriesId} with it until the email is in the send block.","type":"integer","example":57}},"type":"object"},"CampaignFollowupGeneratedResponse":{"description":"Confirmation that the followup email was generated and placed in the automation's send block.","required":["message","campaignId"],"properties":{"message":{"description":"Always \"Campaign followup email generated\".","type":"string","example":"Campaign followup email generated"},"campaignId":{"description":"Id of the automation campaign created for the send block.","type":"integer","example":4822}},"type":"object"},"CampaignGenerationAssetDraftResponse":{"description":"The asset draft the generation wrote; no campaign row exists until it is committed.","required":["isAssetDraft","assetDraft"],"properties":{"isAssetDraft":{"description":"Always true in this body.","type":"boolean","enum":[true],"example":true},"assetDraft":{"$ref":"#/components/schemas/CampaignGenerationRecord","description":"The generation record as stored, with assetDraftId set and campaignId null."}},"type":"object"},"CampaignGenerationAssetDraftResultResponse":{"description":"A finished generation that wrote an asset draft: the campaign and message the draft describes, and the inputs the content was generated from.","required":["campaign","message","brandkitUuid","summarizationUuid","template","blocks","summary","assetDraftId","isAssetDraft"],"properties":{"campaign":{"$ref":"#/components/schemas/CampaignGenerationDraftCampaign","description":"The campaign the draft describes."},"message":{"$ref":"#/components/schemas/CampaignGenerationDraftMessage","description":"The message the draft describes."},"brandkitUuid":{"description":"UUID of the brand kit the content was styled with, or null.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of the content summarization the copy drew on, or null.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"template":{"description":"Key of the layout the draft was generated on, or an empty string for markup saved straight from the engine.","type":"string","example":"promote"},"blocks":{"description":"The additional blocks placed in the layout, each with its type and configuration.","type":"array","items":{"required":["type","config"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"summary":{"description":"The model's one-paragraph summary of the email, or an empty string when none was stored.","type":"string","example":"A short newsletter announcing the October arrivals."},"assetDraftId":{"description":"Id of the asset draft, to pass as id to POST /ai/campaign/generation/commit.","type":"string","example":"ad_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"isAssetDraft":{"description":"Always true in this body.","type":"boolean","enum":[true],"example":true}},"type":"object"},"CampaignGenerationCampaign":{"description":"The campaign the generation wrote.","required":["id","name","type","canSplitContent"],"properties":{"id":{"description":"Id of the campaign.","type":"integer","example":4821},"name":{"description":"Name of the campaign.","type":"string","example":"October newsletter"},"type":{"description":"Campaign type as stored on the campaign.","type":"string","example":"single"},"canSplitContent":{"description":"Always false: this flow writes a single campaign, never a split test.","type":"boolean","example":false}},"type":"object"},"CampaignGenerationCampaignResponse":{"description":"The campaign and message the request wrote.","required":["campaign","message"],"properties":{"campaign":{"$ref":"#/components/schemas/CampaignGenerationCampaign","description":"The campaign."},"message":{"$ref":"#/components/schemas/CampaignGenerationMessage","description":"Its message."}},"type":"object"},"CampaignGenerationDeleteStatusResponse":{"description":"Outcome of deleting a generation request and what it produced.","required":["status"],"properties":{"status":{"description":"deleted: the campaign, its message, its design IR, its folder association and the request record are gone. deleting: the generation is still running, so the delete was queued to POST /ai/campaign/generation/delete and runs once it finishes. partial delete: the request was in error, so whatever it had written was removed on a best-effort basis and the record deleted.","type":"string","enum":["deleted","deleting","partial delete"],"example":"deleted"}},"type":"object"},"CampaignGenerationDraftCampaign":{"description":"The campaign the draft describes; it has no id until the draft is committed.","required":["name","type","canSplitContent"],"properties":{"name":{"description":"Name the campaign will be created with.","type":"string","example":"October newsletter"},"type":{"description":"automation when the draft targets an automation, otherwise single.","type":"string","enum":["single","automation"],"example":"single"},"canSplitContent":{"description":"Always false: this flow writes a single campaign, never a split test.","type":"boolean","example":false}},"type":"object"},"CampaignGenerationDraftMessage":{"description":"The message the draft describes; it has no id until the draft is committed.","required":["subject","preHeader","fromEmail","fromName","replyToEmail","format"],"properties":{"subject":{"description":"Subject line held on the draft.","type":"string","example":"Your October picks are here"},"preHeader":{"description":"Preheader text held on the draft.","type":"string","example":"New arrivals, member offers and more"},"fromEmail":{"description":"Sender address held on the draft, or an empty string when none is set yet.","type":"string","example":"hello@example.com"},"fromName":{"description":"Sender name held on the draft, or an empty string when none is set yet.","type":"string","example":"Example Shop"},"replyToEmail":{"description":"Reply-to address held on the draft, or an empty string when none is set yet.","type":"string","example":"support@example.com"},"format":{"description":"Always an empty string: a draft has no stored message format.","type":"string","enum":[""],"example":""}},"type":"object"},"CampaignGenerationMarkupAssetDraftResponse":{"description":"The asset draft the markup was saved as; no campaign row exists until it is committed.","required":["isAssetDraft","assetDraftId"],"properties":{"isAssetDraft":{"description":"Always true in this body.","type":"boolean","enum":[true],"example":true},"assetDraftId":{"description":"Id of the asset draft, to pass as id to POST /ai/campaign/generation/commit.","type":"string","example":"ad_01HZX3K9Q2M8N7P6R5T4V3W2Y1"}},"type":"object"},"CampaignGenerationMarkupTemplateResponse":{"description":"The library template the markup was saved as; no campaign and no draft were created.","required":["template"],"properties":{"template":{"$ref":"#/components/schemas/CampaignGenerationSavedTemplate","description":"The saved template."}},"type":"object"},"CampaignGenerationMessage":{"description":"The campaign message as stored after the generation.","required":["campaignId","id","subject","preHeader","fromEmail","fromName","replyToEmail","format"],"properties":{"campaignId":{"description":"Id of the campaign the message belongs to.","type":"integer","example":4821},"id":{"description":"Id of the message.","type":"integer","example":9134},"subject":{"description":"Subject line of the message.","type":["string","null"],"example":"Your October picks are here"},"preHeader":{"description":"Preheader text of the message.","type":["string","null"],"example":"New arrivals, member offers and more"},"fromEmail":{"description":"Sender address of the message.","type":["string","null"],"example":"hello@example.com"},"fromName":{"description":"Sender name of the message.","type":["string","null"],"example":"Example Shop"},"replyToEmail":{"description":"Reply-to address of the message.","type":["string","null"],"example":"support@example.com"},"format":{"description":"Message format as stored: html, text or mime.","type":["string","null"],"example":"mime"}},"type":"object"},"CampaignGenerationRecord":{"description":"A campaign generation request as stored: what was asked for, where it stands and what it produced.","required":["template","source","status","step","content","campaignId","messageId","brandkitUuid","summarizationUuid","useSummarizationLink","blocks","images","userId","isAssetDraft","assetDraftId","errorCode"],"properties":{"template":{"description":"Key of the layout the campaign was generated on, or an empty string before the template is selected.","type":"string","example":"promote"},"source":{"description":"Where the request came from, as the caller named it.","type":"string","example":"agent"},"status":{"description":"in_progress while queued or running, success once written, error when a step failed.","type":"string","enum":["success","error","in_progress"],"example":"success"},"step":{"description":"The stage a generation has reached, or null for an update or a record that pre-dates steps.","type":["string","null"],"example":"completed"},"content":{"description":"The generated content as the model returned it, keyed by block, plus summary, changesSummary and hasChanges once known. An object once content exists; an empty array ([]) while nothing has been generated yet.","example":{"summary":"A short newsletter announcing the October arrivals."},"oneOf":[{"type":"object","additionalProperties":true},{"type":"array","items":{"type":"string"},"maxItems":0}]},"campaignId":{"description":"Id of the campaign written, or null until it exists or when the result is an asset draft.","type":["integer","null"],"example":4821},"messageId":{"description":"Id of the campaign message written, or null until it exists.","type":["integer","null"],"example":9134},"brandkitUuid":{"description":"UUID of the brand kit the content was styled with, or null.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of the content summarization the copy drew on, or null.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"useSummarizationLink":{"description":"Whether the email buttons link to the summarized page.","type":["boolean","null"],"example":false},"blocks":{"description":"The additional blocks placed in the layout, each with its type and configuration.","type":"array","items":{"required":["type","config"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"images":{"description":"The images the caller asked to place, or null when none were given.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}},"userId":{"description":"Id of the user who started the request, or null for records that pre-date the field.","type":["integer","null"],"example":3},"isAssetDraft":{"description":"True when the request writes an asset draft instead of a live campaign.","type":"boolean","example":false},"assetDraftId":{"description":"Id of the asset draft written, or null for a live campaign or while nothing is written yet.","type":["string","null"],"example":"ad_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"errorCode":{"description":"timeout or content_too_large when an update failed on a classified model error; null otherwise.","type":["string","null"],"enum":["timeout","content_too_large",null],"example":null}},"type":"object"},"CampaignGenerationRequestIdResponse":{"description":"The campaign generation request that was queued.","required":["requestId"],"properties":{"requestId":{"description":"UUID of the generation request; poll GET /ai/campaign/generation/poll/{requestId} with it and read the result from GET /ai/campaign/generation/{requestId}.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"CampaignGenerationResultResponse":{"description":"A finished campaign generation: the campaign and message written, and the inputs the content was generated from.","required":["campaign","message","brandkitUuid","summarizationUuid","template","blocks","summary","isAssetDraft","assetDraftId"],"properties":{"campaign":{"$ref":"#/components/schemas/CampaignGenerationCampaign","description":"The campaign."},"message":{"$ref":"#/components/schemas/CampaignGenerationMessage","description":"Its message."},"brandkitUuid":{"description":"UUID of the brand kit the content was styled with, or null.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of the content summarization the copy drew on, or null.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"template":{"description":"Key of the layout the campaign was generated on.","type":"string","example":"promote"},"blocks":{"description":"The additional blocks placed in the layout, each with its type and configuration.","type":"array","items":{"required":["type","config"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"summary":{"description":"The model's one-paragraph summary of the email, or an empty string when none was stored.","type":"string","example":"A short newsletter announcing the October arrivals."},"isAssetDraft":{"description":"False in this body: the request wrote a live campaign.","type":"boolean","example":false},"assetDraftId":{"description":"Null in this body; set only on an asset draft result.","type":["string","null"],"example":null}},"type":"object"},"CampaignGenerationSavedTemplate":{"description":"The library template the markup was saved as.","required":["id","name","url"],"properties":{"id":{"description":"Id of the template.","type":"integer","example":517},"name":{"description":"Name of the template in the library.","type":"string","example":"October newsletter layout"},"url":{"description":"URL of the template in the account's template editor.","type":"string","example":"https://example.activehosted.com/campaign/template/?tid=517"}},"type":"object"},"CampaignGenerationStatusResponse":{"description":"Where a campaign generation or update request stands. The HTTP status mirrors status: 200 for success, 409 while in_progress, and 500, 504 or 413 for error depending on errorCode.","required":["status","step","campaignId","generationUuid","isAssetDraft","assetDraftId","changesSummary","hasChanges","errorCode"],"properties":{"status":{"description":"in_progress: the generation or update is queued or running. success: the campaign or asset draft is written and GET /ai/campaign/generation/{requestId} answers it. error: the run failed; errorCode says whether a model timeout or truncation was the cause.","type":"string","enum":["success","error","in_progress"],"example":"in_progress"},"step":{"description":"The stage a generation has reached, for progressive loading. Null for an update, which records no steps, and for records that pre-date steps.","type":["string","null"],"enum":["initiated","selecting_template","generating_content","generating_image_keywords","selecting_images","finalizing","completed","remapping_content","processing_images","compiling","saving",null],"example":"generating_content"},"campaignId":{"description":"Id of the campaign the request created or is editing, or null until the campaign row exists or when the result is an asset draft.","type":["integer","null"],"example":4821},"generationUuid":{"description":"The requestId polled, echoed back.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"isAssetDraft":{"description":"True when the request writes an asset draft instead of a live campaign.","type":"boolean","example":false},"assetDraftId":{"description":"Id of the asset draft the request wrote, or null for a live campaign or while nothing is written yet.","type":["string","null"],"example":"ad_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"changesSummary":{"description":"Short description of what the last update changed. Meaningful only when status is success; null while in progress, on error, when the update changed nothing, and for records that pre-date the field.","type":["string","null"],"example":"Shortened the hero copy and swapped the call to action."},"hasChanges":{"description":"Tri-state. Meaningful only when status is success: true when the update changed the message, false when it ran but produced no observable change. Null while in progress, on error, and for records that pre-date the field; do not read null as false.","type":["boolean","null"],"example":true},"errorCode":{"description":"Meaningful only when status is error. timeout when the model did not answer in time (HTTP 504), content_too_large when its output was truncated (HTTP 413); null for every other error (HTTP 500) and for every non-error status.","type":["string","null"],"enum":["timeout","content_too_large",null],"example":null}},"type":"object"},"CampaignGenerationStoredRequestResponse":{"description":"The generation request stored for a campaign: its id and the record as stored.","required":["requestId","generatedCampaign"],"properties":{"requestId":{"description":"UUID of the generation request the campaign was created or last updated by.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"generatedCampaign":{"$ref":"#/components/schemas/CampaignGenerationRecord","description":"The record as stored."}},"type":"object"},"CampaignGenerationTemplatesItem":{"description":"One base template the campaign generation engine can compose a campaign from.","required":["key","label"],"properties":{"key":{"description":"The template's key, as passed to the generation endpoints to pick this template.","type":"string","example":"welcome"},"label":{"description":"The template's display name, translated into the account's language.","type":"string","example":"Welcome"}},"type":"object"},"CampaignGenerationTemplatesResponse":{"description":"The base templates the campaign generation engine can compose a campaign from.","required":["templates"],"properties":{"templates":{"description":"Every template available for generation, in the order the picker shows them. The list is fixed in code and the same for every account.","type":"array","items":{"$ref":"#/components/schemas/CampaignGenerationTemplatesItem"}}},"type":"object"},"CampaignGenerationUpdateFailedResponse":{"description":"The queued update failed on a model timeout or truncation; the failure is recorded on the request for poll to report, and the job must not be retried.","required":["error","errorCode"],"properties":{"error":{"description":"Always Campaign update failed.","type":"string","enum":["Campaign update failed."],"example":"Campaign update failed."},"errorCode":{"description":"timeout when the model did not answer in time, content_too_large when its output was truncated. Poll answers 504 or 413 for the request accordingly.","type":"string","enum":["timeout","content_too_large"],"example":"timeout"}},"type":"object"},"CampaignInteractionTrend":{"type":"object","description":"Chart data for the unique open rates of recently sent campaigns.","required":["series","graph","pie","extras"],"properties":{"series":{"type":"array","description":"The last send date of each charted campaign, as Y-m-d H:i:s, newest first; a dash for each placeholder point.","items":{"type":"string"},"example":["2026-10-01 14:00:00","2026-09-24 14:00:00"]},"graph":{"type":"array","description":"The unique open rate of each charted campaign in percent, rounded to two decimals, in the order of series.","items":{"type":"number"},"example":[24.5,21.13]},"pie":{"type":"array","description":"Always empty.","items":{},"example":[]},"extras":{"type":"object","description":"Summary figures for the chart.","required":["avg","max","cnt","sum","last","empty"],"properties":{"avg":{"type":"number","description":"Average of the rates in graph, rounded to two decimals.","example":22.82},"max":{"type":"number","description":"Highest rate in graph.","example":24.5},"cnt":{"type":"integer","description":"Number of points in graph.","example":2},"sum":{"type":"integer","description":"Total unique opens of the charted campaigns.","example":330},"last":{"type":"number","description":"Rate of the last point in graph, the oldest campaign.","example":21.13},"empty":{"type":"boolean","description":"True when no charted campaign was opened, so graph holds placeholder values.","example":false}}}}},"CampaignMessagePercentage":{"description":"The share of a split campaign's recipients one of its messages is sent to.","required":["messageId","percentage"],"properties":{"messageId":{"description":"ID of a message attached to the campaign: the messageid of its campaign message association.","type":"integer","example":3},"percentage":{"description":"Percentage of the campaign's recipients the message is sent to, as a whole number.","type":"integer","example":45}},"type":"object"},"CampaignMessagePercentages":{"description":"The split percentages of every message attached to a campaign.","required":["campaignId","messages","meta"],"properties":{"campaignId":{"description":"ID of the campaign, from the path.","type":"integer","example":12},"messages":{"description":"One entry per message attached to the campaign.","type":"array","items":{"$ref":"#/components/schemas/CampaignMessagePercentage"}},"meta":{"description":"Outcome of the request.","required":["success"],"properties":{"success":{"description":"Always true on a 200.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"CampaignMessagePercentagesUpdate":{"description":"The split percentages to store, one entry for every message attached to the campaign.","required":["messages"],"properties":{"messages":{"description":"Every message attached to the campaign with its percentage, a positive whole number (a numeric string is accepted). A list that leaves out an attached message, or names one that is not attached, is refused; a message named twice keeps its last entry.","type":"array","items":{"$ref":"#/components/schemas/CampaignMessagePercentage"},"minItems":1}},"type":"object"},"CampaignRecipientCount":{"type":"object","description":"How many contacts a campaign would be sent to now, and whether that is over the account sending limit.","required":["numberOfRecipients","numberOfRecipientsFormatted","numRecipientsPastLimit"],"properties":{"numberOfRecipients":{"type":"integer","description":"Number of contacts the campaign would be sent to; -1 when its segment could not be found.","example":1250},"numberOfRecipientsFormatted":{"type":"string","description":"numberOfRecipients formatted for display with thousands separators.","example":"1,250"},"numRecipientsPastLimit":{"type":"boolean","description":"True when sending to numberOfRecipients contacts would take the account past its sending limit. Always false for an automation campaign.","example":false},"meta":{"type":"object","description":"Present only when query logging is on for the request, which is a debugging aid.","properties":{"queryLog":{"type":"object","description":"Report of the database queries the request ran."}}}}},"CampaignReportInsightsResponse":{"description":"One campaign reporting insight: which one it is, and the generated answer with the metrics it was based on.","required":["insight","answer"],"properties":{"insight":{"description":"The insight that was generated, echoing the insight query parameter.","type":"string","enum":["business_comparison","subject_line_recommendation","recent_campaigns","campaign_comparison","future_improvements","campaign_success"],"example":"business_comparison"},"answer":{"description":"The generated answer. Its keys depend on the insight. business_comparison: openRate, industryOpenRate, clickRate, industryClickRate, clickImprovement, openImprovement, industry. subject_line_recommendation: topSubjectLines, recommendedSubjectLines, explanation. recent_campaigns: insights, averageOpenRate, averageClickRate, averageUnsubRate. campaign_comparison: insights, campaignOpenRate, campaignClickRate, campaignUnsubRate, campaignClickToOpenRate, averageOpenRate, averageClickRate, averageUnsubRate, averageClickToOpenRate. future_improvements: openRateInsight, clickRateInsight, unsubRateInsight, openRate, clickRate, unsubRate, averageOpenRate, averageClickRate, averageUnsubRate. campaign_success: insights, openRate, clickRate, unsubRate, averageOpenRate, averageClickRate, averageUnsubRate. Rates are numbers; the insight, improvement and explanation fields are text written by the model, and insights, topSubjectLines and recommendedSubjectLines are lists.","type":"object","example":{"openRate":24.1,"industryOpenRate":21.5,"clickRate":2.8,"industryClickRate":2.3,"clickImprovement":"Your click rate already beats the industry; keep calls to action above the fold.","openImprovement":"Test shorter subject lines to lift opens further.","industry":"Retail"},"additionalProperties":true}},"type":"object"},"CampaignRssCheck":{"type":"object","description":"The result of checking every RSS feed a campaign uses.","required":["campaignId","rssFeeds"],"properties":{"campaignId":{"type":"string","description":"ID of the campaign, as given in the path.","example":"12"},"rssFeeds":{"type":"object","description":"One entry per feed URL, keyed by the URL, plus completeSuccess.","required":["completeSuccess"],"properties":{"completeSuccess":{"type":"boolean","description":"True when every feed checked out, and when the campaign uses no feed.","example":true}},"additionalProperties":{"$ref":"#/components/schemas/CampaignRssFeedCheck"}}}},"CampaignRssFeedCheck":{"type":"object","description":"Where a campaign uses one RSS feed, and the result of fetching it.","required":["campaignObject","messages","checkTime","checkSuccess","checkResponse"],"properties":{"campaignObject":{"type":"boolean","description":"True when this is the feed of an RSS-triggered campaign, set on the campaign itself.","example":false},"messages":{"type":"array","description":"The message bodies the feed appears in.","items":{"type":"object","required":["id","format"],"properties":{"id":{"type":"integer","description":"ID of the message.","example":123},"format":{"type":"string","enum":["html","text"],"description":"Which body of the message the feed is in.","example":"html"}}}},"checkTime":{"type":"integer","description":"When the feed was fetched, as a Unix timestamp.","example":1760540400},"checkSuccess":{"type":"boolean","description":"True when the fetch reported no error and found at least one item.","example":true},"checkResponse":{"type":"string","description":"The fetch result, PHP-serialized, for debugging."}}},"CampaignSetCohortsRequest":{"description":"The cohorts of a set once the engine has answered, one entry per cohort in key order.","required":["cohorts"],"properties":{"cohorts":{"description":"One entry per cohort, 2 to 5, keyed c1, c2 and so on in order. A cohort the engine composed carries the assetDraftId of its draft, labelled {cohortSetId}:{cohortKey}; one that failed carries no draft and a failureReason code. At least one must carry a draft. Sending the same list again answers 200 with the stored set; a different list is refused with 409.","type":"array","items":{"required":["cohortKey"],"properties":{"cohortKey":{"description":"c1 to c5, in proposal order.","type":"string","example":"c1"},"assetDraftId":{"description":"The asset draft the cohort was composed as. Absent for a cohort that failed to compose.","type":"string","example":"draft-7c2e"},"failureReason":{"description":"For a cohort with no draft: a lowercase failure code, at most 64 characters. Omitted, compose_failed.","type":"string","example":"compose_timeout"}},"type":"object"},"maxItems":5,"minItems":2,"example":[{"cohortKey":"c1","assetDraftId":"draft-7c2e"},{"cohortKey":"c2","assetDraftId":"draft-9d10"},{"cohortKey":"c3","failureReason":"compose_timeout"}]}},"type":"object"},"CampaignSetReserveRequest":{"description":"A reservation for a cohort set: the id the agent minted when the person accepted the proposed cohorts.","required":["cohortSetId"],"properties":{"cohortSetId":{"description":"The set's id, a lowercase UUID; every later call and every cohort's draft label names the set by it. Reserving again under the same id answers 200 with the existing set and takes no second slot.","type":["string","null"],"example":"8f14e45f-ceea-467a-9b36-0c5d7a1e2b3c"}},"type":"object"},"CampaignTurnLeaseCapabilities":{"description":"What the campaign turn lease store can promise, so a caller can refuse to bind it at startup rather than discover mid-turn that a lease excluded nothing.","required":["seesEveryWorker","maxTtlSeconds"],"properties":{"seesEveryWorker":{"description":"True when every web worker and replica reads the same lease store, so a lease held here excludes every other worker.","type":"boolean","example":true},"maxTtlSeconds":{"description":"The longest hold a caller may ask for in ttlSeconds, in seconds; a longer request is refused with 422.","type":"integer","example":900}},"type":"object"},"CampaignTurnLeaseRequest":{"description":"A request to take or renew a campaign's generation turn for one owner token.","required":["owner","ttlSeconds"],"properties":{"owner":{"description":"The caller's token for this turn, at most 200 characters. Only the same token can renew or release the lease it took.","type":"string","example":"worker-a:turn-7f3c"},"ttlSeconds":{"description":"How many seconds the lease should hold, 1 to 900. A turn takes minutes, so ask for enough to cover one and renew if it overruns.","type":"integer","example":300}},"type":"object"},"CampaignTurnLeaseState":{"description":"The state of a campaign's generation turn lease after an acquire or release: what the call did, who holds the lease now and for how long.","required":["status","owner","expiresInSeconds"],"properties":{"status":{"description":"What the call did. acquired: the campaign was free and is now this owner's. renewed: this owner already held it and the hold was extended. held_by_other: another owner holds it and nothing was changed. released: this owner held it and no longer does. expired: nobody held it, so the turn ran past its own lease. An acquire answers acquired, renewed or held_by_other; a release answers released, expired or held_by_other.","type":"string","enum":["acquired","renewed","held_by_other","released","expired"],"example":"acquired"},"owner":{"description":"The owner token that holds the lease now, or null when nobody does.","type":["string","null"],"example":"worker-a"},"expiresInSeconds":{"description":"How many seconds the current holder has left; 0 when the lease is not held.","type":"integer","example":300}},"type":"object"},"CampaignVariant":{"description":"One take of a set: the key the picker names it by, the angle it led with, the draft it became, and whether it was picked. Carries no campaign content.","required":["variantKey","angle","layout","assetDraftId","picked"],"properties":{"variantKey":{"description":"Short lowercase key the picker names the take by, unique within the set.","type":"string","example":"a"},"angle":{"description":"The angle the take led with, from the engine's closed wheel.","type":"string","example":"outcome"},"layout":{"description":"The layout the take was composed in, or null when the engine named none.","type":["string","null"],"example":"hero-first"},"assetDraftId":{"description":"The asset draft the take became, or null for a take that failed to compose and so cannot be picked.","type":["string","null"],"example":"draft-7c2e"},"picked":{"description":"True on the one take the pick committed.","type":"boolean","example":false}},"type":"object"},"CampaignVariantSet":{"description":"The choice record for one set of takes: which were shown, which was picked, and the one campaign the pick created. Carries no campaign content.","required":["requestId","variants","reservedAt","shownAt","expiresAt","pickedVariantKey","pickedAt","campaignId","messageId"],"properties":{"requestId":{"description":"The caller's key for the set, which every call names it by.","type":"string","example":"toolu_01MdDJX8YPKg"},"reservedAt":{"description":"When the set was reserved, as an ISO-8601 instant in UTC.","type":"string","example":"2026-10-08T12:00:00Z"},"shownAt":{"description":"When the takes were recorded, or null while the set is only reserved.","type":["string","null"],"example":"2026-10-08T12:00:41Z"},"expiresAt":{"description":"When the set stops being pickable. A pick after this answers 410; a replay of a pick already made still answers.","type":"string","example":"2026-10-09T12:00:00Z"},"pickedVariantKey":{"description":"The key of the picked take, or null while no pick has been made. Set from the moment a pick is claimed, before its campaign exists.","type":["string","null"],"example":"b"},"pickedAt":{"description":"When the pick was made, or null.","type":["string","null"],"example":"2026-10-08T12:03:17Z"},"campaignId":{"description":"Id of the one campaign the pick created, or null until the pick has finished.","type":["integer","null"],"example":4821},"messageId":{"description":"Id of that campaign's message, or null until the pick has finished.","type":["integer","null"],"example":9134},"variants":{"description":"The takes in the order shown. Empty while the set is only reserved.","type":"array","items":{"$ref":"#/components/schemas/CampaignVariant"}}},"type":"object"},"CampaignsValidationRequest":{"description":"The campaign IDs to check against what the user may access.","required":["ids"],"properties":{"ids":{"description":"IDs of the campaigns to check. Must not be empty; every value must be a positive number.","type":"array","items":{"type":"integer"},"example":[12,13,99]}},"type":"object"},"CanduConfig":{"type":"object","description":"What the app passes to Candu to identify the user and target onboarding content.","required":["userId","clientToken","traits","variables"],"properties":{"userId":{"type":"string","description":"Candu user ID: the user ID, account ID and environment (`production`, `staging` or `dev`) joined by hyphens.","example":"1-12345-production"},"clientToken":{"type":"string","description":"Candu client token for the environment the service runs in."},"traits":{"$ref":"#/components/schemas/CanduConfigTraits"},"variables":{"$ref":"#/components/schemas/CanduConfigVariables"}}},"CanduConfigTraits":{"type":"object","description":"Account and usage facts Candu targets content by.","required":["accountId","acv","isTrial","industry","onboardingTools","onboardingEmployeeCount","onboardingContacts","onboardingCurrentTool","onboardingVersion","language","entitlements","isInFirst90Days","hasAddress","activeAutomations","inactiveAutomations","activeContacts","customContactFields","pipelines","tags","draftCampaigns","scheduledCampaigns","campaignSentInLast14Days","campaignSentInLast30Days","forms","connectedIntegrations","paidDomain"],"properties":{"accountId":{"type":"integer","description":"ID of the account.","example":12345},"acv":{"type":"integer","description":"The account's annual contract value, as stored on the account.","example":0},"isTrial":{"type":"boolean","description":"True when the account is on a trial.","example":true},"industry":{"type":"string","description":"Business industry, from the account's onboarding answers; empty when there is none.","example":"Retail"},"onboardingTools":{"type":"string","description":"Products the account said it uses, from the account's onboarding answers; empty when there is none."},"onboardingEmployeeCount":{"type":"string","description":"Employee count range, from the account's onboarding answers; empty when there is none."},"onboardingContacts":{"type":"string","description":"Contact count range, from the account's onboarding answers; empty when there is none."},"onboardingCurrentTool":{"type":"string","description":"Tool the account used before, from the account's onboarding answers; empty when there is none."},"onboardingVersion":{"type":"string","description":"Version of the onboarding flow the account went through, from the account's onboarding answers; empty when there is none."},"language":{"type":"string","description":"The account's language; `english` when it has none.","example":"english"},"entitlements":{"type":"array","description":"Names of the account's entitlements.","items":{"type":"string"}},"isInFirst90Days":{"type":"boolean","description":"True when the account registered 90 days ago or less.","example":true},"hasAddress":{"type":"boolean","description":"True when the account has at least one saved address.","example":false},"activeAutomations":{"type":"integer","description":"Number of active automations.","example":2},"inactiveAutomations":{"type":"integer","description":"Number of inactive automations.","example":1},"activeContacts":{"type":"integer","description":"Number of active contacts; 0 when it cannot be counted.","example":150},"customContactFields":{"type":"integer","description":"Number of contact custom fields.","example":3},"pipelines":{"type":"integer","description":"Number of deal pipelines.","example":1},"tags":{"type":"integer","description":"Number of tags.","example":4},"draftCampaigns":{"type":"integer","description":"Number of draft campaigns.","example":1},"scheduledCampaigns":{"type":"integer","description":"Number of scheduled campaigns.","example":0},"campaignSentInLast14Days":{"type":"boolean","description":"True when a campaign was sent in the last 14 days.","example":false},"campaignSentInLast30Days":{"type":"boolean","description":"True when a campaign was sent in the last 30 days.","example":false},"forms":{"type":"integer","description":"Number of forms.","example":1},"connectedIntegrations":{"type":"array","description":"Lower-cased service names of the account's active connections, followed by the names of its connected apps from the integration layer. An app whose record carries no name is listed as null.","items":{"type":["string","null"]}},"paidDomain":{"type":"boolean","description":"True when the account's email address is not on a free email provider's domain.","example":true},"checklistActiveContacts":{"type":"boolean","description":"Only when the request came from the Getting Started page: true when at least 10 contacts have an active list subscription."},"checklistConnectedIntegrations":{"type":"boolean","description":"Only when the request came from the Getting Started page: true when the account has an active connection."},"checklistCampaigns":{"type":"boolean","description":"Only when the request came from the Getting Started page: true when a campaign outside automations and forms is scheduled, or a campaign was sent in the last 14 days."},"checklistAutomations":{"type":"boolean","description":"Only when the request came from the Getting Started page: true when the account has an active automation."}}},"CanduConfigVariables":{"type":"object","description":"Values Candu content can insert.","required":["firstName","lastName","daysRemainingInTrial"],"properties":{"firstName":{"type":"string","description":"The signed-in user's first name.","example":"Jane"},"lastName":{"type":"string","description":"The signed-in user's last name.","example":"Doe"},"daysRemainingInTrial":{"type":"number","description":"Whole days until the account expires, rounded up; negative once it has expired.","example":14}}},"CategorizeRequest":{"description":"Queue payload for classifying the text blocks of an email under edit. CampaignEditsService::dispatchClassification builds it; the server resolves the stored request, campaign, message and markup from requestid.","required":["requestid","textblocks"],"properties":{"requestid":{"description":"UUID of the edit request, as answered by POST /ai/campaigns/edit. Must name a stored edit request that is past pending and not in error.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"textblocks":{"description":"The text blocks extracted from the email, at least one, each with its block id, text and size bucket.","type":"array","items":{"required":["aiBlockId","text","size"],"properties":{"aiBlockId":{"description":"The data-ai-block-id attribute the block carries in the saved markup.","type":"string","example":"ai-block-3"},"text":{"description":"Text content of the block.","type":"string","example":"Save 20% on your next order this weekend only."},"size":{"description":"Size bucket of the text, by word count: under 3 words xsmall, under 10 small, under 40 medium, under 100 large, otherwise xlarge.","type":"string","enum":["xsmall","small","medium","large","xlarge"],"example":"small"}},"type":"object"}},"record":{"description":"The stored edit request. Resolved by the server from requestid; not part of the payload.","type":"object","readOnly":true},"emailEditRequest":{"description":"The edit request decoded from the stored record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"campaign":{"description":"The campaign under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"message":{"description":"The message under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"messageMarkup":{"description":"The editor markup of the message. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"CategorizedBlocksResponse":{"description":"The text blocks of the email with the classification the model gave each.","required":["result"],"properties":{"result":{"description":"One entry per text block, in document order.","type":"array","items":{"required":["aiBlockId","text","size"],"properties":{"aiBlockId":{"description":"The data-ai-block-id attribute the block carries in the saved markup.","type":"string","example":"ai-block-3"},"text":{"description":"Text content of the block.","type":"string","example":"Save 20% on your next order this weekend only."},"size":{"description":"Size bucket of the text, by word count: under 3 words xsmall, under 10 small, under 40 medium, under 100 large, otherwise xlarge.","type":"string","enum":["xsmall","small","medium","large","xlarge"],"example":"small"},"group":{"description":"Part of the email the block belongs to, as the classifier labelled it. Missing when the classifier returned no label.","type":"string","example":"body"},"functionality":{"description":"Role of the block within its group, as the classifier labelled it. Missing when the classifier returned no label.","type":"string","example":"offer"}},"type":"object"}}},"type":"object"},"CategoryEnum":{"enum":["ACCOUNT_UPDATE","PAYMENT_UPDATE","PERSONAL_FINANCE_UPDATE","SHIPPING_UPDATE","RESERVATION_UPDATE","ISSUE_RESOLUTION","APPOINTMENT_UPDATE","TRANSPORTATION_UPDATE","TICKET_UPDATE","ALERT_UPDATE","AUTO_REPLY","TRANSACTIONAL","MARKETING","OTP","AUTHENTICATION","UTILITY"],"type":"string","description":"* `ACCOUNT_UPDATE` - Account Update\n* `PAYMENT_UPDATE` - Payment Update\n* `PERSONAL_FINANCE_UPDATE` - Personal Finance Update\n* `SHIPPING_UPDATE` - Shipping Update\n* `RESERVATION_UPDATE` - Reservation Update\n* `ISSUE_RESOLUTION` - Issue Resolution\n* `APPOINTMENT_UPDATE` - Appointment Update\n* `TRANSPORTATION_UPDATE` - Transportation Update\n* `TICKET_UPDATE` - Ticket Update\n* `ALERT_UPDATE` - Alert Update\n* `AUTO_REPLY` - Auto Reply\n* `TRANSACTIONAL` - Transactional\n* `MARKETING` - Marketing\n* `OTP` - Otp\n* `AUTHENTICATION` - Authentication\n* `UTILITY` - Utility"},"ChannelProviderEnum":{"enum":["META_CLOUD_API","TECH_PROVIDER_CLOUD_API","D360_CLOUD_API","360DIALOG"],"type":"string","description":"* `META_CLOUD_API` - Meta Cloud Api\n* `TECH_PROVIDER_CLOUD_API` - Tech Provider Cloud Api\n* `D360_CLOUD_API` - D360 Cloud Api\n* `360DIALOG` - Dialog360"},"ChannelStatusEnum":{"enum":["NEW","ACTIVE","INACTIVE"],"type":"string","description":"* `NEW` - New\n* `ACTIVE` - Active\n* `INACTIVE` - Inactive"},"ChannelTypeEnum":{"enum":["WHATSAPP","EMAIL","INSTAGRAM","FB_MESSENGER","TELEGRAM","SMS","VOICE"],"type":"string","description":"* `WHATSAPP` - Whatsapp\n* `EMAIL` - Email\n* `INSTAGRAM` - Instagram\n* `FB_MESSENGER` - Fb Messenger\n* `TELEGRAM` - Telegram\n* `SMS` - Sms\n* `VOICE` - Voice"},"CohortSet":{"description":"The record of one cohort set: its state, its cohorts and the campaign each became. Carries no campaign content.","required":["cohortSetId","state","cohorts","reservedAt","recordedAt"],"properties":{"cohortSetId":{"description":"The set's id, a lowercase UUID minted by the agent when the person accepts the proposed cohorts.","type":"string","example":"8f14e45f-ceea-467a-9b36-0c5d7a1e2b3c"},"state":{"description":"Where the set is.","enum":["proposing","composing","review","sending","sent","partially_sent","cancelled"],"example":"review"},"reservedAt":{"description":"When the set was reserved, as an ISO-8601 instant in UTC.","type":"string","example":"2026-10-28T12:00:00Z"},"recordedAt":{"description":"When the cohorts were recorded, or null while the set is only reserved.","type":["string","null"],"example":"2026-10-28T12:01:10Z"},"cohorts":{"description":"The cohorts in key order, removed ones included. Empty while the set is only reserved.","type":"array","items":{"$ref":"#/components/schemas/CohortSetCohort"}}},"type":"object"},"CohortSetCohort":{"description":"One cohort of a cohort set. Carries no campaign content.","required":["cohortKey","state","assetDraftId","campaignId","messageId","edited","removalMode","failureReason"],"properties":{"cohortKey":{"description":"The cohort's key within its set, c1 to c5 in proposal order. Never reused: a removed cohort keeps its key.","type":"string","example":"c2"},"state":{"description":"Where the cohort is.","enum":["proposed","composing","previewed","promoted","scheduled","sent","removed","failed"],"example":"previewed"},"assetDraftId":{"description":"The asset draft the cohort was composed as, labelled {cohortSetId}:{cohortKey}, or null when it failed to compose.","type":["string","null"],"example":"draft-7c2e"},"campaignId":{"description":"Id of the campaign the cohort was promoted to, or null until it is promoted.","type":["integer","null"],"example":4821},"messageId":{"description":"Id of that campaign's message, or null until the cohort is promoted.","type":["integer","null"],"example":9134},"edited":{"description":"Whether the person edited the promoted campaign. A rewrite of the set skips an edited cohort.","type":"boolean","example":false},"removalMode":{"description":"What happened to a removed cohort's contacts, or null unless the cohort was removed.","enum":["redistributed","dropped"],"example":null},"failureReason":{"description":"A failed cohort's failure code, or null unless the cohort failed.","type":["string","null"],"example":null}},"type":"object"},"CommitAssetDraftRequest":{"description":"An asset draft to turn into a live campaign: the draft id, its generation request and the draft data as the asset-draft service holds it. The server validates data against the asset type and hydrates it.","required":["id","asset_type","data"],"properties":{"id":{"description":"Id of the asset draft, as answered by the generation that wrote it.","type":"string","example":"ad_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"external_identifier":{"description":"UUID of the generation request the draft belongs to, or null to use the one held in data. One of the two must be set.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"asset_type":{"description":"Type of the draft; this endpoint commits campaign drafts.","type":"string","enum":["campaign"],"example":"campaign"},"data":{"description":"The draft data as held by the asset-draft service, with at least one key: name, subject, pre_header, html, template_content {html, css}, campaign_type, series_id, label_id, source, user_id, generated_content, template, blocks, brandkit_uuid, summarization_uuid, use_summarization_link, tone, images, lang, prompt, cta_url, from_name, from_email, reply_to_email, design_ir and candidate_id, plus external_identifier when the top-level one is null.","type":"object","example":{"external_identifier":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","name":"October newsletter","subject":"Your October picks are here","pre_header":"New arrivals, member offers and more","html":"<html><body><h1>October arrivals</h1></body></html>","source":"agent","template":"promote"}},"asset_data":{"description":"The draft data hydrated for its asset type, from data. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"attribution":{"description":"Which insight the commit is attributed to, or null for none. Best-effort analytics metadata; extra keys are allowed and blank values count as absent.","properties":{"resourceId":{"description":"Id of the insight resource.","type":"string","example":"ins_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"traceId":{"description":"Trace id of the conversation that led to the commit.","type":"string","example":"trace_01HZX3K9Q2M8N7P6R5T4V3W2Y1"}},"type":"object"}},"type":"object"},"ComparisonEnum":{"enum":["exact","!exact","gte","gt","lte","lt","isnull","!isnull","icontains","!icontains"],"type":"string","description":"* `exact` - Exact\n* `!exact` - Different\n* `gte` - Gte\n* `gt` - Gt\n* `lte` - Lte\n* `lt` - Lt\n* `isnull` - Is Null\n* `!isnull` - Not Null\n* `icontains` - Contains\n* `!icontains` - Not Contains"},"ConditionDO":{"title":"ConditionDO","required":["object_type","source_system","fields"],"type":"object","properties":{"field_aggregate":{"$ref":"#/components/schemas/AggregateDO"},"fields":{"type":"array","description":"Defines the fields, values, types, and their operators. These act as search criteria for the Segment's condition.","items":{"$ref":"#/components/schemas/FieldDO"}},"hash":{"type":"string","description":"Sha1 Hash of the Condition's simple logic and its aggregation logic","readOnly":true},"hash_simple":{"type":"string","description":"Sha1 Hash of the Condition's simple logic","readOnly":true},"id":{"type":"string","description":"Numeric unique identifier for the Condition","example":"1"},"object_type":{"type":"string","description":"Name of the Object being evaluated","example":"tag"},"source_system":{"type":"string","description":"Namespace of Object being evaluated","example":"activecampaign"}}},"ConditionGroupDO":{"title":"ConditionGroupDO","type":"object","properties":{"id":{"type":"string","description":"id's should be numeric strings","example":"1"},"operator":{"type":"string","description":"The operator that applies to the conditions in this group","enum":["and","or"],"example":"and"},"values":{"type":"array","description":"A list of conditions in the group. All items in the \"values\" array must have the same \"type\"","items":{"$ref":"#/components/schemas/ConditionGroupFieldDO"}}}},"ConditionGroupFieldDO":{"title":"ConditionGroupFieldDO","required":["type"],"type":"object","properties":{"id":{"type":"string","description":"Id of the Condition that belongs to this Condition Group. Conditions must not be in more than one group","example":"1"},"type":{"type":"string","description":"Required. Type of \"condition\" indicates that the \"id\" attribute is a condition id.","enum":["condition"]}}},"ConfirmRequest":{"properties":{"campaign_id":{"description":"Id of the campaign.","examples":[42],"exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"confirmation_token":{"description":"confirmation_token returned by the prepare call for this campaign.","maxLength":200,"minLength":1,"title":"Confirmation Token","type":"string"}},"required":["campaign_id","confirmation_token"],"title":"ConfirmRequest","type":"object"},"Contact":{"title":"Contact","type":"object","description":"The contact record as the API returns it: the stored columns plus id and links. Numbers and flags are returned as strings. The dates cdate, adate, udate and edate are ISO 8601 with the account's UTC offset; the other dates are YYYY-MM-DD or YYYY-MM-DD HH:MM:SS. Ids of related records vary by operation and are described on each operation.","properties":{"cdate":{"type":["string","null"],"description":"When the contact was created, in ISO 8601 with the account's UTC offset. Null when not recorded.","example":"2007-05-05T12:49:09-05:00"},"email":{"type":["string","null"],"description":"The contact's email address. Null when the contact was created without one.","example":"sam@example.com"},"phone":{"type":"string","description":"The contact's phone number. Empty when not set.","example":""},"firstName":{"type":"string","description":"The contact's first name. Empty when not set.","example":"Sam"},"lastName":{"type":"string","description":"The contact's last name. Empty when not set.","example":"Example"},"orgid":{"type":"string","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none. The current account link is accountContacts.","example":"0"},"orgname":{"type":"string","description":"Name of the account named by orgid. Empty when there is none. Kept in step with orgid when the contact is saved.","example":""},"segmentio_id":{"type":"string","description":"Id of the contact in the Segment integration. Empty when the contact did not come from Segment.","example":""},"bounced_hard":{"type":"string","description":"Number of hard bounces recorded for the contact. Some update paths reset it to \"0\" when the email address changes.","example":"0"},"bounced_soft":{"type":"string","description":"Number of soft bounces recorded for the contact.","example":"0"},"bounced_date":{"type":["string","null"],"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced.","example":null},"ip":{"type":"string","description":"IPv4 address the contact was added from, stored as a whole number in the form PHP's ip2long produces. \"0\" when not recorded.","example":"0"},"ua":{"type":["string","null"],"description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded.","example":null},"hash":{"type":"string","description":"A 32-character identifier for the contact. Set by the database when the contact is created and replaced by the database when the email address changes. Some older creation paths derive it from the id and email address.","example":"0d9c41ae7a4de516313673e2341f6003"},"socialdata_lastcheck":{"type":["string","null"],"description":"When social profile data was last looked up for the contact, as YYYY-MM-DD HH:MM:SS. Null when never looked up.","example":null},"email_local":{"type":"string","description":"The part of the email address before the @ sign. Not maintained by current code, so usually empty.","example":""},"email_domain":{"type":"string","description":"The part of the email address after the @ sign. Set by the database when the contact is inserted and whenever the email address changes.","example":"example.com"},"sentcnt":{"type":"string","description":"Number of campaigns that have been sent to the contact.","example":"0"},"rating_tstamp":{"type":["string","null"],"description":"Date the contact's engagement rating last changed, as YYYY-MM-DD. Null when never rated. The rating itself is not returned.","example":null},"gravatar":{"type":"string","description":"Gravatar lookup status. \"0\" not looked up yet, \"1\" looked up and no image found, \"2\" looked up and an image found, \"3\" use the image from the contact's appended social profile data (plusAppend) instead.","example":"0"},"deleted":{"type":"string","description":"\"1\" when the contact has been soft-deleted. A deleted contact is moved to the archive, so contacts returned here normally have \"0\".","example":"0"},"anonymized":{"type":"string","description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise.","example":"0"},"adate":{"type":["string","null"],"description":"When activity was last generated for the contact, in ISO 8601 with the account's UTC offset. Null when activity has never been generated.","example":null},"udate":{"type":["string","null"],"description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Moves on any save of the record, including saves that change nothing, and, through database triggers, on list, tag, custom field, score, note and task changes.","example":"2007-05-05T12:49:09-05:00"},"edate":{"type":["string","null"],"description":"Watermark for email activity generation: the contact's stored emails have been turned into activities up to this time. In ISO 8601 with the account's UTC offset. Null when email activity has never been generated for the contact.","example":null},"deleted_at":{"type":["string","null"],"description":"When the contact was soft-deleted, as YYYY-MM-DD HH:MM:SS. Null for a contact that has not been deleted.","example":null},"created_utc_timestamp":{"type":"string","description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS. Set by the database.","example":"2007-05-05 12:49:09"},"updated_utc_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Set by the database on every change and by the application on save. Despite the name it is not in UTC; it moves on every change to the row, including counters such as sentcnt that do not move udate.","example":"2007-05-05 12:49:09"},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS. Set by the database.","example":"2007-05-05 12:49:09"},"updated_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Set by the database on every change and by the application on save.","example":"2007-05-05 12:49:09"},"created_by":{"type":["string","null"],"description":"Id of the user who created the contact. Null when not recorded.","example":null},"updated_by":{"type":["string","null"],"description":"Id of the user who last changed the contact. Null when not recorded.","example":null},"mpp_tracking":{"type":"string","description":"\"1\" when the contact has been detected as using Apple Mail Privacy Protection, \"0\" otherwise.","example":"0"},"last_click_date":{"type":["string","null"],"description":"When the contact last clicked a link in an email, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"last_open_date":{"type":["string","null"],"description":"When the contact last opened an email, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"last_mpp_open_date":{"type":["string","null"],"description":"When an open from Apple Mail Privacy Protection was last recorded for the contact, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"best_send_hour":{"type":["string","null"],"description":"Hour of the day that predictive sending has chosen as the best time to email the contact. Null when not computed.","example":null},"sms_consent":{"type":["string","null"],"description":"\"1\" when the contact has agreed to receive SMS marketing, \"0\" when they have declined. Null when consent was never recorded, which counts as no consent.","example":null},"sms_consent_updated_at":{"type":["string","null"],"description":"When the SMS consent status last changed, as YYYY-MM-DD HH:MM:SS. Null when never recorded.","example":null},"whatsapp_id":{"type":["string","null"],"description":"The contact's WhatsApp user id from Meta. Null when the contact has no WhatsApp identity.","example":null},"whatsapp_username":{"type":["string","null"],"description":"The contact's WhatsApp username. Null when the contact has no WhatsApp identity.","example":null},"links":{"$ref":"#/components/schemas/ContactLinks","description":"URLs of the reads for the contact's related records."},"id":{"type":"string","description":"Id of the contact.","example":"1"},"organization":{"type":["string","null"],"description":"Id of the account the contact belongs to through the legacy account link. The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts.","example":null}}},"ContactAutomationError":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer"},"title":{"description":"The HTTP status text.","type":"string"},"detail":{"description":"What went wrong.","type":"string"}}}}}},"ContactAutomationGoal":{"description":"A goal the contact reached in a run. It also carries seriesid, subscriberid and subscriberseriesid (the automation, contact and run ids), and goal, automation, contact and contactAutomation, which repeat goalid, seriesid, subscriberid and subscriberseriesid. Each of those four is null when the id it repeats is 0.","type":"object","properties":{"goalid":{"description":"Id of the goal.","type":"string"},"timespan":{"description":"Seconds from entering the automation to reaching the goal.","type":"string"},"tstamp":{"description":"When the contact reached the goal.","type":["string","null"]},"links":{"description":"URLs of the entry's related reads.","type":"object"},"id":{"description":"Id of the entry.","type":"string"}}},"ContactAutomationHelperId":{"type":["integer","string"]},"ContactAutomationHelperNotFound":{"type":"object","properties":{"message":{"type":"string"}}},"ContactAutomationLog":{"description":"A history entry for one step of a run. It also carries seriesid, subscriberid and contactseriesid (the automation, contact and run ids), and automation, block, contact and contactAutomation, which repeat seriesid, blockid, subscriberid and contactseriesid. Any of those four is null when the id it repeats is 0.","type":"object","properties":{"blockid":{"description":"Id of the step (automation block).","type":"string"},"tstamp":{"description":"When the contact reached the step. On a wait or goal step that was skipped, when it was skipped.","type":["string","null"]},"res":{"description":"Result of the step. Its meaning depends on the kind of step. 0 can mean it did not succeed, and is also set when a wait or goal step was skipped by hand.","type":"string"},"links":{"description":"URLs of the entry's related reads.","type":"object"},"id":{"description":"Id of the entry.","type":"string"}}},"ContactAutomationLogEntry":{"type":"object","description":"A history entry for one step of a run.","properties":{"seriesid":{"type":"string","description":"Id of the automation. Same value as automation.","example":"2"},"blockid":{"type":"string","description":"Id of the step (automation block). Same value as block.","example":"5"},"subscriberid":{"type":"string","description":"Id of the contact. Same value as contact.","example":"110"},"contactseriesid":{"type":"string","description":"Id of the run (contactAutomation). Same value as contactAutomation.","example":"7"},"tstamp":{"type":["string","null"],"description":"When the contact reached the step, as an ISO 8601 date with offset. On a wait or action step, the time is set again when the contact moves on from it. On a wait or goal step that was skipped, when it was skipped. null when no time was recorded.","example":"2026-10-14T09:12:44-05:00"},"res":{"type":"string","description":"Result of the step. Its meaning depends on the kind of step. 0 can mean it did not succeed, and is also set when a wait or goal step was skipped by hand.","example":"1"},"links":{"type":"object","description":"URLs of the entry's related reads.","properties":{"automation":{"type":"string","description":"URL to the automation."},"block":{"type":"string","description":"URL to the step (automation block)."},"contact":{"type":"string","description":"URL to the contact."},"contactAutomation":{"type":"string","description":"URL to the run (contactAutomation)."}}},"id":{"type":"string","description":"Id of the entry.","example":"31"},"automation":{"type":["string","null"],"description":"Id of the automation. Same value as seriesid. null when seriesid is 0.","example":"2"},"block":{"type":["string","null"],"description":"Id of the step (automation block). Same value as blockid. null when blockid is 0.","example":"5"},"contact":{"type":["string","null"],"description":"Id of the contact. Same value as subscriberid. null when subscriberid is 0.","example":"110"},"contactAutomation":{"type":["string","null"],"description":"Id of the run (contactAutomation). Same value as contactseriesid. null when contactseriesid is 0.","example":"7"}}},"ContactAutomationNotFound":{"type":"object","properties":{"message":{"description":"Says which id was not found.","type":"string","example":"No Result found for SubscriberSeries with id 3"}}},"ContactAutomationStat":{"type":"object","description":"The contact's history in the automation, across every time the contact entered it.","properties":{"id":{"type":"string","description":"Contact id, a hyphen, then automation id, rebuilt from the stored ids. Leading zeros in the requested id are dropped, so 01-06 comes back as 1-6."},"automation":{"type":"string","description":"Id of the automation."},"contact":{"type":"string","description":"Id of the contact."},"isCompleted":{"type":"boolean","description":"true when every step the contact has taken in the automation belongs to an entry that has ended. false while any entry with steps is still in progress."},"percentCompleted":{"type":"number","description":"100 when isCompleted is true. Otherwise the steps taken in entries that have ended, divided by the number of blocks in the automation, times 100, rounded to a whole number. Steps from an entry still in progress do not count. Steps from every ended entry add up, so the value can pass 100 when the contact has finished the automation more than once."},"lastCompletedDate":{"type":"string","description":"When the contact's most recent ended entry ended, in ISO 8601. An empty string when no entry has ended."},"lastEnteredDate":{"type":"string","description":"When the contact last entered the automation, in ISO 8601. An empty string when no entry date is stored."}}},"ContactAutomationStatAutomation":{"type":"object","description":"The automation's stored fields. The full record is documented at GET /automations/{id}.","properties":{"id":{"type":"string","description":"Id of the automation."},"name":{"type":"string","description":"Name of the automation."},"status":{"type":"string","description":"0 = Draft, 1 = Active, 2 = Inactive, 3 = Paused."},"cdate":{"type":["string","null"],"description":"When the automation was created, in ISO 8601."},"mdate":{"type":["string","null"],"description":"When the automation was last changed, in ISO 8601."},"links":{"type":"object","description":"URLs of the automation's related records."}}},"ContactAutomationStatContact":{"type":"object","description":"The contact's stored fields. The full record is documented at GET /contacts/{id}. No related records come with it.","properties":{"id":{"type":"string","description":"Id of the contact."},"email":{"type":["string","null"],"description":"Email address of the contact."},"firstName":{"type":"string","description":"First name. Empty when not set."},"lastName":{"type":"string","description":"Last name. Empty when not set."},"cdate":{"type":["string","null"],"description":"When the contact was created, in ISO 8601."},"udate":{"type":["string","null"],"description":"When the contact was last updated, in ISO 8601."},"deleted":{"type":"string","description":"1 when the contact is deleted, else 0."},"links":{"type":"object","description":"URLs of the contact's related records."}}},"ContactAutomationStatErrors":{"type":"object","description":"An error body with one entry.","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as a number."},"title":{"type":"string","description":"Short name of the status."},"detail":{"type":"string","description":"What went wrong. Left out when there is nothing to add to the title."}}}}},"required":["errors"]},"ContactAutomationStatMessage":{"type":"object","description":"An error body with one message.","properties":{"message":{"type":"string","description":"What was not found."}},"required":["message"]},"ContactAutomationStepResource":{"description":"One recorded step for a contact automation run","properties":{"blockId":{"description":"Automation block id for this step","type":"integer","example":42},"blockType":{"description":"Internal block type key","type":["string","null"],"example":"wait"},"processedAt":{"description":"When the step was processed","type":"string","example":"2026-01-08 09:30:00"},"outcome":{"description":"Step outcome","type":["string","null"],"example":"skipped"},"outcomeMessage":{"description":"Outcome detail message when recorded","type":"string","example":"wait_manual_end"},"skipped":{"oneOf":[{"$ref":"#/components/schemas/ContactAutomationStepSkippedResource","description":"Present when this step was skipped for this contact"},{"type":"null"}],"description":"Present when this step was skipped for this contact"}},"type":"object"},"ContactAutomationStepSkippedResource":{"description":"Skip reason saved for this contact on this step","properties":{"reason":{"description":"Skip reason key recorded when the contact was skipped","type":["string","null"],"example":"subscription_error"},"extra":{"description":"Additional context for the skip reason","type":["object","null"],"example":{"message":"Contact was already subscribed"}}},"type":"object"},"ContactAutomationStepsEnrollmentResource":{"description":"The contact automation enrollment these steps belong to","properties":{"id":{"description":"Contact automation enrollment id","type":"integer","example":6},"automation":{"description":"Automation id","type":"integer","example":2},"contact":{"description":"Contact id","type":"integer","example":15}},"type":"object"},"ContactAutomationStepsResponseResource":{"description":"Recorded automation steps for one contact enrollment","properties":{"contactAutomation":{"$ref":"#/components/schemas/ContactAutomationStepsEnrollmentResource","description":"The contact automation enrollment these steps belong to"},"steps":{"description":"Steps recorded for this enrollment, earliest first. Empty when nothing was logged yet.","type":"array","items":{"$ref":"#/components/schemas/ContactAutomationStepResource"}}},"type":"object"},"ContactBulkDeleteResult":{"description":"Outcome of a bulk contact delete, reported per contact id.","required":["succeeded","message","deleted","failed"],"properties":{"succeeded":{"description":"1 when the call answered 200, otherwise 0.","type":"integer"},"message":{"description":"What happened, in the language of the account; only \"None of the requested lists are accessible.\" is always English.","type":"string"},"deleted":{"description":"Ids of the contacts the request processed: removed from the targeted lists, and deleted from the account when that left them on no list.","type":"array","items":{"type":"integer"}},"failed":{"description":"Contacts that were not deleted, each with the reason.","type":"array","items":{"required":["id","reason"],"properties":{"id":{"description":"Id of the contact that was not deleted.","type":"integer"},"reason":{"description":"Why it was not deleted, in the language of the account.","type":"string"}},"type":"object"}},"pastlimit":{"description":"Present only when the delete allowance stopped the run. Always 1.","type":"integer"}},"type":"object"},"ContactConversion":{"type":"object","description":"One time a contact reached a conversion.","properties":{"contact":{"type":["string","null"],"description":"Id of the contact. Null when it is 0.","example":"12"},"conversion":{"type":["string","null"],"description":"Id of the conversion. Null when it is 0.","example":"3"},"conversionTrigger":{"type":"string","description":"Id of the trigger that fired. Same value as conversiontrigger, but 0 stays \"0\".","example":"5"},"converted_by_type":{"type":["string","null"],"description":"Type of the record that made the entry. Usually EcomOrder for an order; otherwise null.","example":"EcomOrder"},"converted_by_id":{"type":["string","null"],"description":"Id of the record that made the entry, or null.","example":"88"},"triggerType":{"type":"string","description":"Kind of trigger that fired, usually one of segment, manual, url, event, automation, goal, ecommerce. An empty string on entries written through the API without a type.","example":"event"},"modifier":{"type":"string","description":"Not used. Usually an empty string.","example":""},"value":{"type":["number","string"],"description":"Amount booked, in the currency's main unit, for example 15.5 for 15.50. An empty string when no amount was stored.","example":15.5},"currency":{"type":"string","description":"Three-letter code of the currency, or an empty string when none is set.","example":"usd"},"dynamic":{"type":"string","description":"Usually \"0\". \"1\" for entries added in bulk from past orders.","example":"0"},"cdate":{"type":["string","null"],"description":"When the contact converted, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the entry's related records, one for each of conversion, conversiontrigger, contact, activities, convertedBy, attributions. Each URL is the entry's URL followed by the name.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the entry.","example":"41"},"conversiontrigger":{"type":["string","null"],"description":"Id of the trigger that fired. Null when it is 0.","example":"5"},"convertedBy":{"type":["object","null"],"description":"Type and id of the record that made the entry, or null when there is none.","properties":{"type":{"type":"string","description":"Type of the record.","example":"ecom-order"},"id":{"type":"string","description":"Id of the record.","example":"88"}}}}},"ContactConversionActivity":{"type":"object","description":"A contact activity entry for the conversion, with reference_type SubscriberConversion. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the activity.","example":"301"},"tstamp":{"type":["string","null"],"description":"When the contact converted, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"jsonData":{"type":["string","null"],"description":"JSON text. Its touchpoints key counts the tracked touchpoints before the conversion.","example":"{\"touchpoints\":2}"}},"additionalProperties":true},"ContactConversionAttribution":{"type":"object","description":"A share of the entry's amount credited to one touchpoint. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the attribution.","example":"9"},"revenue_generator_type":{"type":"string","description":"Type of the record credited, for example Campaign.","example":"Campaign"},"revenue_generator_id":{"type":"string","description":"Id of the record credited.","example":"7"},"amount":{"type":"string","description":"Amount credited, in the currency's smallest unit, for example cents.","example":"1500"}},"additionalProperties":true},"ContactConversionContact":{"type":"object","description":"The stored contact record. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the contact.","example":"12"},"email":{"type":["string","null"],"description":"Email address of the contact. Null when the contact has no email address.","example":"sam@example.com"},"firstName":{"type":"string","description":"First name of the contact.","example":"Sam"},"lastName":{"type":"string","description":"Last name of the contact.","example":"Example"}},"additionalProperties":true},"ContactConversionConversion":{"type":"object","description":"A tracked event or action with an optional value, with its stored settings. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the conversion.","example":"3"},"name":{"type":"string","description":"Name of the conversion.","example":"Purchase"},"value":{"type":"number","description":"Value of one conversion, in the currency's main unit, for example 15.5 for 15.50.","example":15.5}},"additionalProperties":true},"ContactConversionFields":{"type":"object","description":"Fields of an entry. Each one is optional.","properties":{"contact":{"type":["integer","string"],"description":"Id of the contact."},"conversion":{"type":["integer","string"],"description":"Id of the conversion."},"conversionTrigger":{"type":["integer","string"],"description":"Id of the trigger."},"triggerType":{"type":"string","description":"Kind of trigger, such as event or ecommerce."},"value":{"type":["number","string"],"description":"Amount in the currency's main unit, for example 15.5 for 15.50. A number, or a string that holds a number. It is stored times 100."},"currency":{"type":"string","description":"Three-letter code of the currency."},"converted_by_type":{"type":"string","description":"Type of the record that made the entry. It must name a record type, such as EcomOrder."},"converted_by_id":{"type":["integer","string"],"description":"Id of the record that made the entry."},"dynamic":{"type":["integer","boolean"],"description":"1 marks entries added in bulk from past orders. Defaults to 0."}}},"ContactConversionOrder":{"type":"object","description":"The stored e-commerce order. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the order.","example":"88"},"totalPrice":{"type":"string","description":"Order total, in the currency's smallest unit.","example":"1550"}},"additionalProperties":true},"ContactConversionPoint":{"type":"object","description":"One touchpoint recorded for a contact before a conversion.","properties":{"contact":{"type":["string","null"],"description":"Id of the contact. Null when it is 0.","example":"6199"},"type":{"type":"string","description":"Kind of touchpoint, which also says what relid points to. LinkData is an email open or link click, SmsLog a delivered SMS and OmniChannelLinkData an SMS link click. Others are campaign, automation, form, email, sitemesg, sms, deepdata (a completed ecommerce order), url (a site visit), source (a site visit with UTM values) and event (a tracked event).","example":"LinkData"},"relid":{"type":"string","description":"Id of the activity record the point came from. \"0\" for url, source and event points.","example":"8812"},"pointdata":{"type":["object","array"],"description":"Details of the touchpoint. LinkData, SmsLog and OmniChannelLinkData points carry event.type (EMAIL_OPEN, EMAIL_LINK_CLICK, SMS_DELIVERED or SMS_LINK_CLICKED) and revenue_generator, the record credited with the revenue. Site visits carry the url and any UTM values; tracked events carry event and eventdata. Other points have an empty array."},"tstamp":{"type":["string","null"],"description":"When the activity happened, as an ISO 8601 date with offset. Null when not recorded.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the point's contact and attributions, under contact and attributions.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the point.","example":"15"}}},"ContactConversionPointAttribution":{"type":"object","description":"One share of a conversion's revenue, credited through this point. The ids in aggregate_revenue_id, subscriber_conversion_id and subscriber_conversion_point_id also come back as aggregate_revenue, subscriber_conversion and subscriber_conversion_point, as null when the id is 0.","properties":{"created_utc_timestamp":{"type":"string","description":"When the attribution was created, as an ISO 8601 date with offset.","example":"2026-09-01T14:05:00-05:00"},"updated_utc_timestamp":{"type":"string","description":"When the attribution was last changed, as an ISO 8601 date with offset.","example":"2026-09-01T14:05:00-05:00"},"aggregate_revenue_id":{"type":"string","description":"Id of the revenue total this attribution counts toward.","example":"4"},"subscriber_conversion_id":{"type":"string","description":"Id of the contact conversion that is credited, such as an ecommerce order.","example":"33"},"subscriber_conversion_point_id":{"type":"string","description":"Id of the point.","example":"15"},"revenue_generator_type":{"type":"string","description":"Kind of record credited with the revenue, such as Campaign.","example":"Campaign"},"revenue_generator_id":{"type":"string","description":"Id of the record credited with the revenue.","example":"27"},"amount":{"type":"string","description":"Amount credited, in cents.","example":"4999"},"currency":{"type":"string","description":"Three-letter currency code.","example":"USD"},"links":{"type":"object","description":"URLs under /attributions/{id}. This API does not serve them.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the attribution.","example":"21"},"revenue_generator":{"type":["object","null"],"description":"An object with type (the API type of the credited record, such as campaign) and id. Null when there is none.","additionalProperties":{"type":"string"}}}},"ContactConversionPointContact":{"type":"object","description":"The contact record. Numbers and flags come back as strings. The other stored columns of the contact also come back, such as phone and the cdate and udate dates, with links to its related records.","properties":{"email":{"type":["string","null"],"description":"The contact's email address.","example":"sam@example.com"},"firstName":{"type":"string","description":"The contact's first name. Empty when not set.","example":"Sam"},"lastName":{"type":"string","description":"The contact's last name. Empty when not set.","example":"Example"},"id":{"type":"string","description":"Id of the contact.","example":"6199"}},"additionalProperties":true},"ContactConversionPointErrors":{"type":"object","properties":{"errors":{"type":"array","description":"One entry, with status \"403\" as a string and detail \"Upgrade your account to enable Attribution\".","items":{"type":"object","additionalProperties":{"type":"string"}}}}},"ContactConversionPointFields":{"type":"object","description":"Fields of a point. Each one is optional.","properties":{"contact":{"type":["integer","string"],"description":"Id of the contact.","example":"6199"},"type":{"type":"string","description":"Kind of touchpoint, such as LinkData.","example":"LinkData"},"relid":{"type":["integer","string"],"description":"Id of the activity record the point came from.","example":"8812"},"pointdata":{"type":["object","array"],"description":"Details of the touchpoint, saved as JSON."}}},"ContactConversionPointSaved":{"type":"object","description":"The point after the write. Values sent come back as sent, so a number sent as a number comes back as a number.","properties":{"contact":{"type":["string","integer","null"],"description":"Id of the contact. Null when it is 0.","example":"6199"},"type":{"type":"string","description":"Kind of touchpoint.","example":"LinkData"},"relid":{"type":["string","integer"],"description":"Id of the activity record the point came from.","example":"8812"},"pointdata":{"type":["object","array"],"description":"Details of the touchpoint."},"tstamp":{"type":["string","null"],"description":"When the activity happened, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the point's contact and attributions, under contact and attributions.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the point.","example":"15"}}},"ContactConversionSaved":{"type":"object","description":"An entry as returned by a write. After an update it has the same fields as ContactConversion, plus udate. After a create it has the fields described for POST /contactConversions. Fields sent in the body come back as sent, except value, and ids of 0 in contact and conversion, which come back as null.","properties":{"id":{"type":"string","description":"Id of the entry.","example":"41"},"cdate":{"type":["string","null"],"description":"When the entry was made, as an ISO 8601 date with offset. Null when the entry has no date.","example":"2026-09-01T14:03:12-05:00"},"udate":{"type":"string","description":"Time of this request, as an ISO 8601 date with offset. It is not stored, and reads do not return it.","example":"2026-09-01T14:03:12-05:00"},"value":{"type":["number","string"],"description":"Amount, in the currency's main unit. An empty string when no amount is stored.","example":15.5}},"additionalProperties":true},"ContactConversionSource":{"type":"object","description":"One tracked page visit and its UTM values. campaign, referrer, id, url and tstamp are always present. source, medium, content, term and item are present only when the visit has them. When the visit has no non-empty UTM value and has a referrer, the UTM values are read from the referrer URL instead.","required":["campaign","referrer","id","url","tstamp"],"properties":{"campaign":{"type":"string","description":"The visit's utm_campaign value. Empty string when there is none.","example":"fall_sale"},"source":{"type":"string","description":"utm_source from the visit URL.","example":"newsletter"},"medium":{"type":"string","description":"utm_medium from the visit URL.","example":"email"},"content":{"type":"string","description":"utm_content from the visit URL.","example":"header_link"},"term":{"type":"string","description":"utm_term from the visit URL.","example":"pricing"},"item":{"type":"string","description":"utm_item from the visit URL.","example":"plan_plus"},"referrer":{"type":"string","description":"URL of the page that sent the contact to this page. Empty string when there is none.","example":"https://www.example.com/blog"},"id":{"type":"string","description":"Generated id: an md5 hash of the visit's time, URL and event name. It is not stored, and it changes if any of those change.","example":"5d41402abc4b2a76b9719d911017c592"},"url":{"type":"string","description":"URL of the visited page.","example":"https://www.example.com/pricing?utm_source=newsletter&utm_medium=email&utm_campaign=fall_sale"},"tstamp":{"type":["string","null"],"format":"date-time","description":"When the visit happened, as an ISO 8601 date with offset. Null when the visit has no time.","example":"2026-10-05T09:15:00-05:00"}}},"ContactConversionTrigger":{"type":"object","description":"A rule that fires a conversion for a contact, with its stored settings. Other stored fields also come back.","properties":{"id":{"type":"string","description":"Id of the trigger.","example":"5"},"triggerType":{"type":"string","description":"Kind of trigger.","example":"event"},"value":{"type":"string","description":"What the trigger matches, such as an event name or a URL.","example":"purchase"}},"additionalProperties":true},"ContactDatum":{"type":"object","properties":{"contact":{"type":"string","example":"4","description":"ID of the contact this record belongs to. A contact has at most one record. A normal contact delete keeps the record, so this can be the ID of a contact that no longer exists; merging contacts removes the merged-away contact's record."},"tstamp":{"type":["string","null"],"example":"2021-06-09T14:35:10-05:00","description":"When this record was first created. ISO 8601 with a UTC offset, or null."},"geoTstamp":{"type":["string","null"],"description":"When the location fields were last updated. ISO 8601 with a UTC offset. Null if no location has been stored."},"geoIp4":{"type":["string","null"],"example":"0","description":"The IP address the location was worked out from, stored as a single number rather than dotted form. 0 or null when there is none."},"geoCountry2":{"type":["string","null"],"example":"","description":"Two-letter ISO country code from the location lookup. Empty or null when unknown."},"geo_country":{"type":"string","example":"","description":"Country name from the location lookup. Empty when unknown. This field keeps its snake_case name; there is no geoCountry."},"geoState":{"type":"string","example":"","description":"State, province or region name from the location lookup. Empty when unknown."},"geoCity":{"type":"string","example":"","description":"City name from the location lookup. Empty when unknown."},"geoZip":{"type":"string","example":"","description":"Postal code from the location lookup. Empty when unknown."},"geoArea":{"type":["string","null"],"example":"0","description":"Telephone area code. 0 or null; the location lookup no longer supplies one."},"geoLat":{"type":"string","example":"0.000000","description":"Latitude from the location lookup, to six decimal places. 0.000000 when unknown."},"geoLon":{"type":"string","example":"0.000000","description":"Longitude from the location lookup, to six decimal places. 0.000000 when unknown."},"geoTz":{"type":"string","example":"","description":"Time zone name for the location, such as America/Chicago. Used to run automation waits in the contact's local time. Empty when unknown."},"geoTzOffset":{"type":"string","example":"0.00","description":"Difference in hours between geoTz and the time zone the database server runs in. Normally 0.00 when geoTz is empty."},"ga_campaign_source":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_name":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_medium":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_term":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_content":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_customsegment":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_first_visit":{"type":["string","null"],"description":"Legacy field. Nothing writes it today; expect null."},"ga_times_visited":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"fb_id":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"fb_name":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"tw_id":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"created_timestamp":{"type":"string","example":"0000-00-00 00:00:00","description":"When the database row was created, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS (not ISO 8601). May be 0000-00-00 00:00:00 on older rows."},"updated_timestamp":{"type":"string","example":"0000-00-00 00:00:00","description":"When the database row was last changed, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS (not ISO 8601). May be 0000-00-00 00:00:00 on older rows."},"created_by":{"type":["string","null"],"example":"0","description":"Id of the account user who created the row, when one was recorded. Usually 0 or null."},"updated_by":{"type":["string","null"],"example":"0","description":"Id of the account user who last changed the row, when one was recorded. Usually 0 or null."},"links":{"type":"array","description":"Always an empty list. This record has no related resources of its own."},"id":{"type":"string","example":"12","description":"ID of this data record. Not the contact ID; use contact for that."}},"description":"One contact data record: extra information the application keeps about a contact, mostly where the contact appears to be located."},"ContactDeal":{"type":"object","description":"One contact-to-deal link: the row that puts a contact on a deal, with an optional role. Numbers arrive as strings.","properties":{"deal":{"type":"string","example":"4228","description":"Id of the deal the link points at. The full deal record is sideloaded in deals; GET /deals/{id} returns it on its own."},"contact":{"type":"string","example":"5","description":"Id of the contact on the link. On GET /contacts/{id}/contactDeals this is always the contact in the path."},"role":{"type":["string","null"],"example":"1","description":"Id of the deal role the contact holds on this deal, from GET /dealRoles. Null when no role is set."},"cdate":{"type":["string","null"],"example":"2021-10-22T13:16:27-05:00","description":"When the contact was linked to the deal, in ISO 8601 with a UTC offset. Null when no date was stored."},"created_timestamp":{"type":"string","example":"2021-10-22 13:16:27","description":"When the row was created, as YYYY-MM-DD HH:MM:SS with no timezone offset."},"updated_timestamp":{"type":"string","example":"2021-10-22 13:16:27","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS with no timezone offset."},"created_by":{"type":["string","null"],"example":"1","description":"Id of the account user who created the link. Null when it was not recorded."},"updated_by":{"type":["string","null"],"example":"1","description":"Id of the account user who last changed the link. Null when it was not recorded."},"links":{"type":"object","description":"URLs of the records the link points at, under /contactDeals/{id}.","properties":{"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/4248/deal","description":"URL of the deal."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/4248/contact","description":"URL of the contact."},"role":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/4248/role","description":"URL of the deal role."}}},"id":{"type":"string","example":"4248","description":"Id of the link. Use it with GET, PUT and DELETE /contactDeals/{id}."}}},"ContactEmail":{"type":"object","description":"One one-to-one email that a user sent to a contact. The subject and body are not here; they are on the linked message.","properties":{"messageid":{"type":"string","description":"ID of the message that holds the email's subject, body and sender.","example":"37"},"seriesid":{"type":"string","description":"ID of the automation the contact is added to when they respond to the email. \"0\" unless the sender chose to wait for a response.","example":"0"},"messageheader":{"type":["string","null"],"description":"The Message-ID header of the sent email, used to match replies to it. Null or an empty string when none was recorded, for example before the email is sent.","example":"<0123abcd@example.com>"},"userid":{"type":"string","description":"ID of the user who sent the email.","example":"1"},"d_id":{"type":"string","description":"ID of the deal the email was filed against. \"0\" when it is not filed against a deal.","example":"0"},"subscriberid":{"type":"string","description":"ID of the contact the email was sent to.","example":"12"},"account":{"type":["string","null"],"description":"ID of the CRM account the email was filed against. Null when it is not filed against an account.","example":"2"},"ip":{"type":"string","description":"IPv4 address of the user who sent the email, as an unsigned integer in text form. It is not the contact's address. \"0\" when no IPv4 address was recorded.","example":"3221225985"},"sdate":{"type":["string","null"],"description":"When the email was sent. ISO 8601 with a UTC offset, or null.","example":"2024-03-05T10:15:00-06:00"},"source":{"type":["string","null"],"description":"A label for where the email came from. An empty string for email sent from a contact or deal page in ActiveCampaign. \"ac\" on the sample emails added with the sample deal. Email logged by the read-tracking endpoint carries whatever source the client sent: null when it left source out, or an empty string when it sent null.","example":""},"links":{"type":"object","description":"URLs of the records related to this email.","properties":{"user":{"type":"string","description":"URL of the user who sent the email.","example":"https://:account.api-us1.com/api/3/contactEmails/7/user"},"deal":{"type":"string","description":"URL of the deal the email was filed against.","example":"https://:account.api-us1.com/api/3/contactEmails/7/deal"},"contact":{"type":"string","description":"URL of the contact the email was sent to.","example":"https://:account.api-us1.com/api/3/contactEmails/7/contact"},"message":{"type":"string","description":"URL of the message with the subject and body.","example":"https://:account.api-us1.com/api/3/contactEmails/7/message"},"activity":{"type":"string","description":"URL of the activity stream entry for the email.","example":"https://:account.api-us1.com/api/3/contactEmails/7/activity"},"account":{"type":"string","description":"URL of the CRM account the email was filed against.","example":"https://:account.api-us1.com/api/3/contactEmails/7/account"}}},"id":{"type":"string","description":"ID of this email record.","example":"7"},"user":{"type":["string","null"],"description":"ID of the user who sent the email, the same as userid. Null when userid is \"0\".","example":"1"},"deal":{"type":["string","null"],"description":"ID of the deal, the same as d_id. Null when d_id is \"0\"."},"contact":{"type":["string","null"],"description":"ID of the contact, the same as subscriberid. Null when subscriberid is \"0\".","example":"12"},"message":{"type":["string","null"],"description":"ID of the message, the same as messageid. Null when messageid is \"0\".","example":"37"}}},"ContactEnrichmentError":{"description":"Why a contact enrichment request was declined.","required":["title","code"],"properties":{"title":{"description":"A message for the user.","type":"string","example":"Contact not found."},"code":{"description":"What was declined: `declined_flag` (enrichment is not turned on for the account), `permission_denied` (the user may not edit contacts), `contact_not_found` (no contact has the id) or `declined_quota` (the monthly AI allowance is used up).","type":"string","enum":["declined_flag","permission_denied","contact_not_found","declined_quota"],"example":"contact_not_found"}},"type":"object"},"ContactExportRequest":{"type":"object","properties":{"export":{"type":"object","description":"The filters and column options. Numbers can also be sent as strings, and the include flags take strings such as \"false\" and \"0\" too.","properties":{"listid":{"type":"integer","description":"Only contacts on this list. -1 means contacts on any list and -2 contacts on no list. 0 or no value does not filter. For a user outside the admin group, a listid other than -2 to 0 must be one of the user's lists."},"tagid":{"type":"integer","description":"Only contacts with this tag."},"status":{"type":"integer","minimum":-1,"maximum":3,"description":"Only contacts with this list status: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced. -1, the default, means any status. A value that is not a number counts as 0."},"seriesid":{"type":"integer","description":"Only contacts in this automation."},"finishedAutomation":{"type":"integer","description":"With `seriesid`: 1 for contacts that finished the automation, 0 for contacts still in it."},"formid":{"type":"integer","description":"Only contacts that came in through this form."},"segmentid":{"type":["integer","string"],"description":"Only contacts in this segment, by id or UUID."},"segment_run_id":{"type":"string","description":"A segment run to reuse. Needs `segmentid`."},"waitid":{"type":["integer","string","null"],"description":"Only contacts waiting in this automation block. An empty string or null does not filter."},"query":{"type":"string","description":"Only contacts matching this search text, as in GET /contacts."},"includeFields":{"type":"boolean","description":"Add a column for each custom field. Defaults to true."},"includeAccounts":{"type":"boolean","description":"Add the contact's account, when the account uses Accounts. Defaults to true."},"includeLists":{"type":"boolean","description":"Add list columns. Defaults to true."},"includeTags":{"type":"boolean","description":"Add the contact's tags. Defaults to true."},"includeScores":{"type":"boolean","description":"Add the contact's scores. Defaults to true."},"exportName":{"type":"string","description":"Name of the export. It must not contain HTML tags. When absent or null, the export is named after the time the job starts. An empty string gives an export with an empty name."}}}}},"ContactFieldValue":{"type":"object","properties":{"contact":{"type":"string","description":"ID of the contact.","example":"5"},"field":{"type":"string","description":"ID of the custom field definition.","example":"1"},"value":{"type":"string","description":"The stored value, as a string. Date-time field values are converted to ISO 8601 in the requesting user's time zone, and the preferred language field returns the language name instead of its code.","example":"United States"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2021-05-12T14:19:38-05:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2021-05-12T14:54:57-05:00"},"created_by":{"type":["string","null"],"description":"ID of the account user who created the value; 0 or null when it was not set by a user.","example":"0"},"updated_by":{"type":["string","null"],"description":"ID of the account user who last changed the value; 0 or null when the last change was not made by a user.","example":"0"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/3/fieldValues/1/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/3/fieldValues/1/field"}}},"id":{"type":"string","description":"ID of the field value record.","example":"1"},"owner":{"type":"string","description":"ID of the contact the value belongs to, the same as contact.","example":"5"}}},"ContactGoal":{"type":"object","description":"One goal completion: a record that a contact reached a goal in an automation.","properties":{"goalid":{"type":"string","description":"ID of the goal the contact reached. Same value as goal.","example":"3"},"seriesid":{"type":"string","description":"ID of the automation that holds the goal. Same value as automation.","example":"12"},"subscriberid":{"type":"string","description":"ID of the contact who reached the goal. Same value as contact. When two contacts are merged, the record usually moves to the surviving contact; some records are deleted instead.","example":"6199"},"subscriberseriesid":{"type":"string","description":"ID of the contact's run through the automation, as returned by /contactAutomations. A contact who enters the automation more than once has a separate run for each entry. Same value as contactAutomation.","example":"880"},"timespan":{"type":"string","description":"Number of seconds from when the contact entered the automation to when they reached the goal.","example":"86400"},"tstamp":{"type":["string","null"],"description":"When the completion was recorded, as ISO 8601 with a UTC offset. A background job records it, so it can be a little later than the moment the goal was reached. It is set again when a contact merge moves the record to another contact. Null for a zero date.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the records related to this goal completion.","properties":{"goal":{"type":"string","description":"URL of the goal."},"automation":{"type":"string","description":"URL of the automation."},"contact":{"type":"string","description":"URL of the contact."},"contactAutomation":{"type":"string","description":"URL of the contact's run through the automation."},"contactGoalLists":{"type":"string","description":"URL of the lists the contact was on when they reached the goal."},"contactGoalTags":{"type":"string","description":"URL of the tags the contact had when they reached the goal."}}},"id":{"type":"string","description":"ID of the goal completion.","example":"41"},"goal":{"type":["string","null"],"description":"ID of the goal. Same value as goalid, but null when goalid is \"0\".","example":"3"},"automation":{"type":["string","null"],"description":"ID of the automation. Same value as seriesid, but null when seriesid is \"0\".","example":"12"},"contact":{"type":["string","null"],"description":"ID of the contact. Same value as subscriberid, but null when subscriberid is \"0\".","example":"6199"},"contactAutomation":{"type":["string","null"],"description":"ID of the contact's run through the automation. Same value as subscriberseriesid, but null when subscriberseriesid is \"0\".","example":"880"}}},"ContactGoalAutomation":{"type":"object","description":"The automation, in the same shape as automation in GET /automations/{id}. The main fields are listed here. Every other field of the automation also comes back.","properties":{"name":{"type":"string","description":"Name of the automation.","example":"Welcome series"},"cdate":{"type":["string","null"],"description":"When the automation was created, as ISO 8601 with a UTC offset. Null when not set.","example":"2026-08-14T09:12:44-05:00"},"mdate":{"type":["string","null"],"description":"When the automation was last changed, as ISO 8601 with a UTC offset. Null when not set.","example":"2026-08-15T10:02:11-05:00"},"status":{"type":"string","description":"0 draft, 1 active, 2 inactive, 3 paused.","example":"1"},"links":{"type":"object","description":"URLs of the automation's related reads.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"ID of the automation.","example":"12"}}},"ContactGoalContact":{"type":"object","description":"The contact, in the same shape as contact in GET /contacts/{id}. The main fields are listed here. Every other field of the contact also comes back. Only the contact comes back; none of the arrays that GET /contacts/{id} adds beside it.","properties":{"email":{"type":["string","null"],"description":"Email address of the contact. Null when the contact has no email address.","example":"sam@example.com"},"firstName":{"type":"string","description":"First name of the contact. Empty when not set.","example":"Sam"},"lastName":{"type":"string","description":"Last name of the contact. Empty when not set.","example":"Example"},"links":{"type":"object","description":"URLs of the contact's related reads.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"ID of the contact.","example":"6199"}}},"ContactGoalContactAutomation":{"type":"object","description":"The run, in the same shape as contactAutomation in GET /contactAutomations/{id}. The main fields are listed here. Every other field of the run also comes back. Only the run comes back; subscriberSeriesEnds does not.","properties":{"contact":{"type":["string","null"],"description":"ID of the contact on this run. Null when it is \"0\".","example":"6199"},"seriesid":{"type":"string","description":"ID of the automation. Same value as automation.","example":"12"},"status":{"type":"string","description":"1 while the contact is moving through the automation, 2 once the run has ended.","example":"1"},"adddate":{"type":["string","null"],"description":"When the contact entered the automation, as ISO 8601 with a UTC offset. Null when not set.","example":"2026-08-31T14:03:12-05:00"},"remdate":{"type":["string","null"],"description":"When the run ended, as ISO 8601 with a UTC offset. Null while the run is in progress."},"lastblock":{"type":"string","description":"ID of the last step (automation block) the contact reached.","example":"57"},"completed":{"type":"integer","description":"1 when the run has ended (status 2), otherwise 0.","example":0},"completeValue":{"type":"number","description":"Percent of the automation done. 100 once the run has ended.","example":60},"links":{"type":"object","description":"URLs of the run's related reads.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"ID of the run.","example":"880"},"automation":{"type":["string","null"],"description":"ID of the automation. Same value as seriesid, but null when seriesid is \"0\".","example":"12"}}},"ContactGoalGoal":{"type":"object","description":"A goal in an automation.","properties":{"blockid":{"type":"string","description":"ID of the automation step (block) that holds the goal. Same value as automationBlock.","example":"57"},"seriesid":{"type":"string","description":"ID of the automation that holds the goal. Same value as automation.","example":"12"},"name":{"type":"string","description":"Name of the goal.","example":"Made a purchase"},"cdate":{"type":["string","null"],"description":"When the goal was created, as ISO 8601 with a UTC offset. Null when not set.","example":"2026-08-20T10:15:00-05:00"},"dirty_stats":{"type":"string","description":"1 when the goal's statistics need recalculating, otherwise 0.","example":"0"},"links":{"type":"object","description":"URLs of the goal's related reads: automation, automationBlock and contactGoals.","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"ID of the goal.","example":"3"},"automation":{"type":["string","null"],"description":"ID of the automation. Same value as seriesid, but null when seriesid is \"0\".","example":"12"},"automationBlock":{"type":["string","null"],"description":"ID of the automation step. Same value as blockid, but null when blockid is \"0\".","example":"57"}}},"ContactGoalList":{"type":"object","description":"One list the contact was on when it reached a goal.","properties":{"listid":{"type":"string","description":"Id of the list. Same value as list.","example":"3"},"subscribergoalid":{"type":["string","null"],"description":"Id of the reached goal. Same value as contactGoal.","example":"41"},"links":{"type":"object","description":"URLs of the entry's related records.","properties":{"list":{"type":"string","description":"URL of the list record."},"contactGoal":{"type":"string","description":"URL of the reached goal."}}},"id":{"type":"string","description":"Id of the entry.","example":"12"},"list":{"type":["string","null"],"description":"Id of the list. Same value as listid, but null when listid is 0.","example":"3"},"contactGoal":{"type":["string","null"],"description":"Id of the reached goal. Same value as subscribergoalid, but null when it is 0. Absent when subscribergoalid is null.","example":"41"}}},"ContactGoalListContactGoal":{"type":"object","description":"One goal reached by a contact in one automation run.","properties":{"goalid":{"type":"string","description":"Id of the goal. Same value as goal.","example":"7"},"seriesid":{"type":"string","description":"Id of the automation. Same value as automation.","example":"2"},"subscriberid":{"type":"string","description":"Id of the contact. Same value as contact.","example":"6199"},"subscriberseriesid":{"type":"string","description":"Id of the automation run. Same value as contactAutomation.","example":"83"},"timespan":{"type":"string","description":"Seconds from the contact entering the automation to reaching the goal.","example":"3600"},"tstamp":{"type":["string","null"],"description":"When the goal was reached, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the related goal, automation, contact, contactAutomation (the automation run), contactGoalLists (the lists the contact was on) and contactGoalTags (the tags the contact had).","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the reached goal.","example":"41"},"goal":{"type":["string","null"],"description":"Id of the goal. Same value as goalid, but null when it is 0.","example":"7"},"automation":{"type":["string","null"],"description":"Id of the automation. Same value as seriesid, but null when it is 0.","example":"2"},"contact":{"type":["string","null"],"description":"Id of the contact. Same value as subscriberid, but null when it is 0.","example":"6199"},"contactAutomation":{"type":["string","null"],"description":"Id of the automation run. Same value as subscriberseriesid, but null when it is 0.","example":"83"}}},"ContactGoalListList":{"type":"object","description":"The stored list record. Every other stored column of the list also comes back, as a string or null: for example the sender address, the tracking settings and the notification addresses.","properties":{"id":{"type":"string","description":"Id of the list.","example":"3"},"stringid":{"type":"string","description":"Unique URL-safe form of the list name.","example":"example-newsletter"},"userid":{"type":"string","description":"Id of the account user who owns the list.","example":"1"},"name":{"type":"string","description":"Name of the list.","example":"Example Newsletter"},"cdate":{"type":["string","null"],"description":"When the list was created, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"udate":{"type":["string","null"],"description":"When the list was last changed, as YYYY-MM-DD HH:MM:SS.","example":"2026-09-02 09:30:00"},"channel":{"type":"string","description":"Channel of the list.","enum":["email","sms"],"example":"email"},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS.","example":"2026-09-01 14:03:12"},"updated_timestamp":{"type":"string","description":"When the row was last changed, as YYYY-MM-DD HH:MM:SS.","example":"2026-09-02 09:30:00"},"links":{"type":"array","description":"Always an empty array."}},"additionalProperties":{"type":["string","null"]}},"ContactGoalTag":{"type":"object","description":"One tag the contact had when it reached a goal.","properties":{"tagid":{"type":"string","description":"Id of the tag. Same value as tag.","example":"5"},"subscribergoalid":{"type":["string","null"],"description":"Id of the reached goal. Same value as contactGoal.","example":"41"},"links":{"type":"object","description":"URLs of the entry's related records.","properties":{"tag":{"type":"string","description":"URL of the tag."},"contactGoal":{"type":"string","description":"URL of the reached goal."}}},"id":{"type":"string","description":"Id of the entry.","example":"12"},"tag":{"type":["string","null"],"description":"Id of the tag. Same value as tagid, but null when it is 0.","example":"5"},"contactGoal":{"type":["string","null"],"description":"Id of the reached goal. Same value as subscribergoalid, but null when it is 0. Absent when subscribergoalid is null.","example":"41"}}},"ContactGoalTagContactGoal":{"type":"object","description":"One goal reached by a contact in one automation run.","properties":{"goalid":{"type":"string","description":"Id of the goal. Same value as goal.","example":"7"},"seriesid":{"type":"string","description":"Id of the automation. Same value as automation.","example":"2"},"subscriberid":{"type":"string","description":"Id of the contact. Same value as contact.","example":"6199"},"subscriberseriesid":{"type":"string","description":"Id of the automation run. Same value as contactAutomation.","example":"83"},"timespan":{"type":"string","description":"Seconds from the contact entering the automation to reaching the goal.","example":"3600"},"tstamp":{"type":["string","null"],"description":"When the goal was reached, as an ISO 8601 date with offset. Null when the stored date is zero.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"URLs of the related goal, automation, contact, contactAutomation (the automation run), contactGoalLists (the lists the contact was on) and contactGoalTags (the tags the contact had).","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the reached goal.","example":"41"},"goal":{"type":["string","null"],"description":"Id of the goal. Same value as goalid, but null when it is 0.","example":"7"},"automation":{"type":["string","null"],"description":"Id of the automation. Same value as seriesid, but null when it is 0.","example":"2"},"contact":{"type":["string","null"],"description":"Id of the contact. Same value as subscriberid, but null when it is 0.","example":"6199"},"contactAutomation":{"type":["string","null"],"description":"Id of the automation run. Same value as subscriberseriesid, but null when it is 0.","example":"83"}}},"ContactGoalTagTag":{"type":"object","description":"The tag, as it is now.","properties":{"tagType":{"type":"string","description":"What the tag is applied to: contact or template.","example":"contact"},"tag":{"type":"string","description":"Name of the tag.","example":"Example Customer"},"description":{"type":"string","description":"Description of the tag. An empty string when none was set.","example":""},"subscriber_count":{"type":"string","description":"How many contacts have the tag now, whatever their status. Kept up to date by the database, not counted on read.","example":"1"},"cdate":{"type":["string","null"],"description":"When the tag was created, as an ISO 8601 date with offset. Null when not recorded.","example":"2026-08-20T10:00:00-05:00"},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS.","example":"2026-08-20 10:00:00"},"updated_timestamp":{"type":"string","description":"When the row was last changed, as YYYY-MM-DD HH:MM:SS.","example":"2026-08-20 10:00:00"},"created_by":{"type":["string","null"],"description":"Id of the account user who created the tag, or null.","example":"1"},"updated_by":{"type":["string","null"],"description":"Id of the account user who last changed the tag, or null.","example":"1"},"deleted":{"type":"string","description":"1 when the tag was soft-deleted, else 0. A soft-deleted tag is still returned here.","example":"0"},"links":{"type":"object","description":"URLs of the tag's related contactGoalTags (the contact goal tag entries for this tag) and templateTags (its links to email templates).","additionalProperties":{"type":"string"}},"id":{"type":"string","description":"Id of the tag.","example":"5"}}},"ContactImport":{"type":"object","description":"One row of a contact import's per-row log. Integer values come back as strings.","properties":{"id":{"type":"string","description":"ID of this log row.","example":"19"},"processid":{"type":"string","description":"ID of the import's background process. For imports started from the app, it matches the processid of the import in GET /import/history. 0 for rows written by an integration's automatic sync, which has no process.","example":"3401"},"autosync":{"type":["string","null"],"description":"For rows written by an integration's automatic sync, the ID of that sync run's log entry. null for every other import.","example":null},"email":{"type":["string","null"],"description":"Email address of the row that was imported. null or empty when the row had no email address, for example a phone-only contact.","example":"sam@example.com"},"res":{"type":"string","description":"Outcome of the row: 1 imported, 2 imported but a list subscription was skipped, 0 not imported. Rows from older sync imports use only 0 and 1; a partly imported row there has res 1 with code 104 or 116.","example":"1"},"code":{"type":"string","description":"Reason code for the outcome. 0 usually means no problem, but rows from an integration's automatic sync always have code 0, even when res is 0. Other values include 2 (general failure), 4 (previously bounced), 16 (previously unsubscribed), 25 (existing contact not updated and no new lists), 30 (on the exclusion list), 60 (no email address), 65 (invalid phone), 70 (contact limit reached), 80 (invalid custom field value), and 104, 116, 124 and 130 for an import that succeeded but skipped a list because the contact previously bounced, previously unsubscribed, named a list that does not exist, or is on the exclusion list. The list is not complete: a failure can also carry the code of the error that stopped the row.","example":"0"},"msg":{"type":"string","description":"Result message as shown in the app, in the language of the user who ran the import. For imported rows it starts with \"Imported under ID: <contact id>\". It can be empty.","example":"Imported under ID: 6199."},"tstamp":{"type":["string","null"],"description":"When the row was processed, as an ISO 8601 date and time. null if it was never set.","example":"2026-09-01T14:03:12-05:00"},"links":{"type":"object","description":"Related-resource links for this row.","properties":{"autosync":{"type":"string","description":"URL of this row's autosync relationship. It is present on every row, even when there was no sync, and it does not lead to the sync run in autosync, so do not rely on it.","example":"https://example.api-us1.com/api/3/contactImports/19/autosync"}}}}},"ContactLinks":{"title":"ContactLinks","type":"object","description":"URLs of the reads for the contact's related records.","properties":{"bounceLogs":{"type":"string","description":"URL of the read that lists the contact's bounce logs.","example":"https://:account.api-us1.com/api/3/contacts/1/bounceLogs"},"contactAutomations":{"type":"string","description":"URL of the read that lists the automations the contact has entered. The URL includes limit=2500 and orders[lastdate]=DESC.","example":"https://:account.api-us1.com/api/3/contacts/1/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC"},"contactData":{"type":"string","description":"URL of the read for the contact's engagement data.","example":"https://:account.api-us1.com/api/3/contacts/1/contactData"},"contactGoals":{"type":"string","description":"URL of the read that lists the automation goals the contact has met.","example":"https://:account.api-us1.com/api/3/contacts/1/contactGoals"},"contactLists":{"type":"string","description":"URL of the read that lists the contact's list memberships.","example":"https://:account.api-us1.com/api/3/contacts/1/contactLists"},"contactLogs":{"type":"string","description":"URL of the read that lists the contact's logs.","example":"https://:account.api-us1.com/api/3/contacts/1/contactLogs"},"contactTags":{"type":"string","description":"URL of the read that lists the tags on the contact.","example":"https://:account.api-us1.com/api/3/contacts/1/contactTags"},"contactDeals":{"type":"string","description":"URL of the read that lists the links between the contact and deals.","example":"https://:account.api-us1.com/api/3/contacts/1/contactDeals"},"deals":{"type":"string","description":"URL of the read that lists the contact's deals.","example":"https://:account.api-us1.com/api/3/contacts/1/deals"},"fieldValues":{"type":"string","description":"URL of the read that lists the contact's custom field values.","example":"https://:account.api-us1.com/api/3/contacts/1/fieldValues"},"geoIps":{"type":"string","description":"URL of the read that lists the IP addresses recorded for the contact.","example":"https://:account.api-us1.com/api/3/contacts/1/geoIps"},"notes":{"type":"string","description":"URL of the read that lists the contact's notes.","example":"https://:account.api-us1.com/api/3/contacts/1/notes"},"organization":{"type":"string","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts.","example":"https://:account.api-us1.com/api/3/contacts/1/organization"},"plusAppend":{"type":"string","description":"URL of the read for the contact's appended social profile data.","example":"https://:account.api-us1.com/api/3/contacts/1/plusAppend"},"trackingLogs":{"type":"string","description":"URL of the read that lists the contact's tracking logs.","example":"https://:account.api-us1.com/api/3/contacts/1/trackingLogs"},"scoreValues":{"type":"string","description":"URL of the read that lists the contact's score values.","example":"https://:account.api-us1.com/api/3/contacts/1/scoreValues"},"accountContacts":{"type":"string","description":"URL of the read that lists the contact's account links. Present only when the account has the Accounts feature.","example":"https://:account.api-us1.com/api/3/contacts/1/accountContacts"},"automationEntryCounts":{"type":"string","description":"URL of the read that counts the contact's entries into each automation.","example":"https://:account.api-us1.com/api/3/contacts/1/automationEntryCounts"}}},"ContactLog":{"type":"object","properties":{"userid":{"type":["string","null"],"description":"Id of the account user who performed the merge. Same value as user.","example":"1"},"subscriberid":{"type":"string","description":"Id of the surviving contact. Same value as contact.","example":"6199"},"name":{"type":["string","null"],"description":"Surviving contact's full name at the time of the merge.","example":"Sam Example"},"email":{"type":["string","null"],"description":"Surviving contact's email address at the time of the merge.","example":"sam@example.com"},"action":{"type":"string","description":"What was logged. merge is the only action written today.","example":"merge"},"params":{"type":["string","null"],"description":"JSON text with the source and destination contacts and the field and automation differences resolved by the merge.","example":"{\"source\":{\"id\":\"6200\",\"name\":\"Sam Example\",\"email\":\"sam.example@example.com\"},\"destination\":{\"id\":\"6199\",\"name\":\"Sam Example\",\"email\":\"sam@example.com\"},\"fields\":[],\"automations\":[],\"resolutionField\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"},\"resolutionAutomation\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"}}"},"tstamp":{"type":["string","null"],"description":"When the entry was logged, as an ISO 8601 date with offset.","example":"2026-09-01T14:03:12-05:00"},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago).","example":"2026-09-01 14:03:12"},"updated_timestamp":{"type":"string","description":"When the row was last changed, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago).","example":"2026-09-01 14:03:12"},"created_by":{"type":["string","null"],"description":"Not set by the merge; null."},"updated_by":{"type":["string","null"],"description":"Not set by the merge; null."},"links":{"type":"object","description":"URLs of the entry's related resources.","properties":{"contact":{"type":"string","description":"URL to the contact."},"user":{"type":"string","description":"URL to the account user."}}},"id":{"type":"string","description":"Id of the log entry.","example":"12"},"contact":{"type":"string","description":"Id of the contact. Same value as subscriberid.","example":"6199"},"user":{"type":["string","null"],"description":"Id of the account user who performed the merge. Same value as userid. Absent (not null) when userid is null.","example":"1"}},"description":"One contact log entry."},"ContactMessage":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"object","additionalProperties":{"type":"string","nullable":true}}},"emails":{"type":"array","items":{"type":"object","additionalProperties":{"type":"string","nullable":true}}},"ims":{"type":"array","items":{"type":"object","additionalProperties":{"type":"string","nullable":true}}},"urls":{"type":"array","items":{"type":"string","maxLength":255}},"name":{"type":"object","additionalProperties":{"type":"string","nullable":true}},"phones":{"type":"array","items":{"type":"object","additionalProperties":{"type":"string","nullable":true}}},"org":{"type":"object","additionalProperties":{"type":"string","nullable":true}}}},"ContactModelFieldMatch":{"description":"One custom field whose title contains every word in the query. Contact field values are not included.","properties":{"id":{"description":"Field id.","type":"integer","example":1},"title":{"description":"Field title.","type":"string","example":"gift card value"},"type":{"description":"Field type.","type":"string","example":"text"},"perstag":{"description":"Personalization tag. Search does not match on this.","type":"string","example":"GIFTCARDVALUE"},"options":{"description":"Option labels for a dropdown, checkbox, radio, or listbox. Omitted when the field has none.","type":"array","items":{"type":"string"},"example":["Red","Blue"]}},"type":"object"},"ContactModelNameMatch":{"description":"One list or tag whose name contains every word in the query.","properties":{"id":{"description":"List or tag id.","type":"integer","example":43},"name":{"description":"List or tag name.","type":"string","example":"INTEREST - Drums"},"count":{"description":"Stored contact count for a list, or subscriber count for a tag.","type":"integer","example":0}},"type":"object"},"ContactModelSearchResponse":{"description":"Lists, tags, and fields on this account whose names match the query. At most 10 of each.","required":["lists","tags","fields"],"properties":{"lists":{"description":"Matching lists, largest stored contact count first.","type":"array","items":{"$ref":"#/components/schemas/ContactModelNameMatch"}},"tags":{"description":"Matching tags, largest subscriber count first.","type":"array","items":{"$ref":"#/components/schemas/ContactModelNameMatch"}},"fields":{"description":"Matching fields by title. Never includes contact field values.","type":"array","items":{"$ref":"#/components/schemas/ContactModelFieldMatch"}}},"type":"object"},"ContactNote":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"notes":{"type":"string"},"contact":{"type":"string","format":"uuid","readOnly":true},"created_on":{"type":"string","format":"date-time","readOnly":true,"title":"Created on"},"created_by":{"$ref":"#/components/schemas/SimpleUser"}},"required":["contact","created_on","id","notes"]},"ContactPerformanceGrowthPoint":{"description":"Contact counts for one period of a growth trend. When the range ends today or later, the last period carries the current counts as numbers.","required":["event_hour","total_contacts","active_contacts","inactive_contacts"],"properties":{"list_id":{"description":"ID of the list. Sent only by the list trend.","type":["integer","string"],"example":5},"tag_id":{"description":"ID of the tag. Sent only by the tag trend.","type":["integer","string"],"example":12},"event_hour":{"description":"Start of the period, as Y-m-d H:i:s.","type":"string","example":"2026-10-01 00:00:00"},"total_contacts":{"description":"Contacts in the period.","type":["integer","string"],"example":1500},"active_contacts":{"description":"Active contacts in the period.","type":["integer","string"],"example":1260},"inactive_contacts":{"description":"Inactive contacts in the period.","type":["integer","string"],"example":240}},"type":"object"},"ContactPerformanceGrowthSummary":{"description":"Contact counts at the start and end of a date range, and how much each changed. A range that ends today (the server's date) or later ends with the current counts. A range that ends earlier is the reporting data service's row as it sends it. Counts come back as numbers or as strings of digits.","required":["first_total_contacts","first_active_contacts","first_inactive_contacts","total_contacts","active_contacts","inactive_contacts","total_contact_growth_rate","active_contact_growth_rate","inactive_contact_growth_rate"],"properties":{"account_id":{"description":"ID of the account. Sent only when the range ends before today.","type":["integer","string"],"example":1},"list_id":{"description":"ID of the list. Sent only by the list report, when the range ends before today.","type":["integer","string"],"example":5},"tag_id":{"description":"ID of the tag. Sent only by the tag report, when the range ends before today.","type":["integer","string"],"example":12},"first_total_contacts":{"description":"Contacts at the start of the range, from the reporting data service. When startDate and endDate are the same day and it is today or later, the current count. null when the range ends today or later and the service has no row for it.","type":["integer","string","null"],"example":1200},"first_active_contacts":{"description":"Active contacts at the start of the range, counted like active_contacts.","type":["integer","string","null"],"example":1000},"first_inactive_contacts":{"description":"Inactive contacts at the start of the range, counted like inactive_contacts.","type":["integer","string","null"],"example":200},"total_contacts":{"description":"Contacts at the end of the range.","type":["integer","string"],"example":"1500"},"active_contacts":{"description":"Active contacts at the end of the range. null from the tag report when the range ends today or later and no contact has the tag.","type":["integer","string","null"],"example":"1260"},"inactive_contacts":{"description":"Inactive contacts at the end of the range. When the range ends today or later, total_contacts minus active_contacts; otherwise the reporting data service's value.","type":["integer","string"],"example":240},"total_contact_growth_rate":{"description":"Change from first_total_contacts to total_contacts, as a percentage of first_total_contacts rounded to two decimals. 0 when either count is 0. When the range ends before today, the reporting data service's value.","type":["number","string"],"example":25},"active_contact_growth_rate":{"description":"Change from first_active_contacts to active_contacts, worked out like total_contact_growth_rate.","type":["number","string"],"example":26},"inactive_contact_growth_rate":{"description":"Change from first_inactive_contacts to inactive_contacts, worked out like total_contact_growth_rate.","type":["number","string"],"example":20}},"type":"object"},"ContactPerformanceTopList":{"description":"One of the account's largest lists, with its contact counts and growth. Counts, IDs and the growth rate come back as numbers or as numeric strings.","required":["account_id","list_id","name","total_contacts","active_contacts","inactive_contacts","total_contact_growth_rate"],"properties":{"account_id":{"description":"ID of the account.","type":["integer","string"],"example":1},"list_id":{"description":"ID of the list.","type":["integer","string"],"example":"3"},"name":{"description":"Name of the list.","type":"string","example":"Newsletter"},"total_contacts":{"description":"Contacts on the list, whatever their status on it, not counting deleted contacts.","type":["integer","string"],"example":"1500"},"active_contacts":{"description":"Contacts subscribed to the list (active status).","type":["integer","string"],"example":"1260"},"inactive_contacts":{"description":"total_contacts minus active_contacts.","type":["integer","string"],"example":"240"},"total_contact_growth_rate":{"description":"Change in total_contacts over the range, as a percentage of the count at the start. In a row the reporting data service sends as it is, the service's own value. In a row of current counts, rounded to two decimals, and 0 when either count is 0 or the service has no row for the list.","type":["number","string"],"example":25},"first_total_contacts":{"description":"Contacts on the list at the start of the range. Sent only when the row is the reporting data service's own.","type":["integer","string"],"example":1200}},"type":"object"},"ContactPerformanceTopTag":{"description":"One of the account's most used tags, with its contact counts and growth. Counts, IDs and the growth rate come back as numbers or as numeric strings.","required":["account_id","tag_id","tag_name","total_contacts","active_contacts","inactive_contacts","total_contact_growth_rate"],"properties":{"account_id":{"description":"ID of the account.","type":["integer","string"],"example":1},"tag_id":{"description":"ID of the tag.","type":["integer","string"],"example":"7"},"tag_name":{"description":"Name of the tag.","type":"string","example":"customer"},"total_contacts":{"description":"Contacts who carry the tag.","type":["integer","string"],"example":"800"},"active_contacts":{"description":"Contacts who carry the tag and are subscribed to at least one list.","type":["integer","string"],"example":"700"},"inactive_contacts":{"description":"total_contacts minus active_contacts.","type":["integer","string"],"example":"100"},"total_contact_growth_rate":{"description":"Change in total_contacts over the range, as a percentage of the count at the start. In a row the reporting data service sends as it is, the service's own value. In a row of current counts, rounded to two decimals, and 0 when either count is 0 or the service has no row for the tag.","type":["number","string"],"example":14.29},"first_total_contacts":{"description":"Contacts who carried the tag at the start of the range. Sent only when the row is the reporting data service's own.","type":["integer","string"],"example":700}},"type":"object"},"ContactReadSimple":{"type":"object","properties":{"first_name":{"type":"string","nullable":true,"maxLength":100},"last_name":{"type":"string","nullable":true,"maxLength":100},"email":{"type":"string","format":"email","nullable":true,"maxLength":254},"meta":{},"canonical_phone":{"type":"string","nullable":true,"maxLength":30},"is_deleted":{"type":"boolean"},"phone":{"type":"string"},"id":{"type":"string"},"created_on":{"type":"string","format":"date-time","title":"Created on"},"last_updated_on":{"type":"string","format":"date-time","readOnly":true,"title":"Last updated on"},"source":{"type":"string","maxLength":255},"external_url":{"type":"string","format":"uri","nullable":true,"maxLength":200}},"required":["id","last_updated_on","phone","source"]},"ContactRestoreError":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code."},"title":{"type":"string","description":"The HTTP status name."},"detail":{"type":"string","description":"Why the request was refused."}}}}}},"ContactRestoreQueued":{"type":"object","properties":{"restoreRequest":{"type":"object","properties":{"message":{"type":"string","example":"Deleted contacts have been queued for restore. Please use Contact Restore Request ID to request progress information: 12","description":"A human-readable confirmation that ends with the restore request id. The text may contain a line break and spaces; do not rely on its exact wording."},"restoreRequestId":{"type":"integer","example":12,"description":"The id of the restore request that was created."}},"description":"Passed through from the contact restore service's reply."}}},"ContactRestoreRequest":{"type":"object","properties":{"id":{"type":"integer","example":12,"description":"The restore request id. Use it with GET /contactArchives/restoreRequest/{id}."},"type":{"type":"string","example":"contact","description":"What the request restores. Always contact."},"parameters":{"type":"string","example":"{\"ids\":\"5606,5607\"}","description":"The selection the request was made with, as a JSON-encoded string: the ids, or the start, end and search of a restore-all."},"contacts_matching":{"type":"integer","example":2,"description":"How many archived contacts the request matched when it was made."},"contacts_to_be_skipped":{"type":"integer","example":0,"description":"How many of the matched contacts are being skipped rather than restored."},"contacts_restored":{"type":"integer","example":1,"description":"How many contacts have been restored so far."},"contacts_failed":{"type":"integer","example":0,"description":"How many contacts could not be restored."},"created_at":{"type":["string","null"],"example":"2026-10-12 15:04:05","description":"When the request was made, YYYY-MM-DD HH:MM:SS."},"updated_at":{"type":["string","null"],"example":"2026-10-12 15:04:30","description":"When the request last made progress, YYYY-MM-DD HH:MM:SS."},"finished_at":{"type":["string","null"],"example":null,"description":"When the request finished, YYYY-MM-DD HH:MM:SS. null while it is still running."}}},"ContactRestoreServerError":{"type":"object","properties":{"message":{"type":"string","example":"Something went wrong on our end. Please try again later","description":"A generic message; the cause is not returned."}}},"ContactScoreValue":{"title":"ContactScoreValue","type":"object","description":"One point total: the points a contact holds for one score. Numbers arrive as strings.","properties":{"score":{"type":"string","example":"2","description":"Id of the score definition. See GET /scores."},"contact":{"type":"string","example":"1","description":"Id of the contact."},"deal":{"type":["string","null"],"description":"Id of the deal for a deal score. Null for contact scores."},"cdate":{"type":["string","null"],"example":"2018-03-08T14:01:16-06:00","description":"When the point total was first recorded."},"mdate":{"type":["string","null"],"example":"2018-10-22T20:15:28-05:00","description":"When the point total last changed."},"scoreValue":{"type":"string","example":"0","description":"The points the contact currently holds for this score."},"links":{"type":"object","properties":{"score":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/score","description":"URL to the score definition."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/contact","description":"URL to the contact."},"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/deal","description":"URL to the deal. Only meaningful for deal scores."}},"description":"URLs of the row's related resources."},"id":{"type":"string","example":"1","description":"Id of the score value row."}}},"ContactScriptHttpErrors":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status."},"title":{"type":"string","description":"Short name of the error."},"detail":{"type":"string","description":"What is wrong."}}}}}},"ContactScriptKernelErrors":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string","description":"What is wrong."}}}}}},"ContactScriptNotFound":{"type":"object","properties":{"message":{"type":"string","description":"Which contact was not found."}}},"ContactStandardFieldDefaults":{"type":["object","array"],"description":"Stored defaults keyed by field name. An empty array when none are stored.","additionalProperties":{"type":"string","description":"Stored default value."},"maxItems":0,"example":{"firstname":"Sam","lastname":"Example"}},"ContactTag":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"name":{"type":"string","maxLength":100}},"required":["id","name"]},"ContactUpdateRecord":{"type":"object","description":"A record of a contact updating their details through a campaign's update link.","properties":{"subscriberid":{"type":"string","description":"Id of the contact who updated their details. Same value as contact. \"0\" when no contact was stored.","example":"110"},"campaignid":{"type":"string","description":"Id of the campaign whose update link the contact used. Same value as campaign. \"0\" when no campaign was stored.","example":"12"},"messageid":{"type":"string","description":"Id of the campaign message the contact used. Same value as message. \"0\" when no message was stored.","example":"15"},"tstamp":{"type":["string","null"],"description":"When the contact sent the update, as an ISO 8601 date with offset. null when no time was stored.","example":"2026-10-14T09:12:44-05:00"},"ip":{"type":"string","description":"IPv4 address the contact sent the update from, stored as one unsigned 32-bit number and returned as a string of digits. For example, 203.0.113.10 is \"3405803786\". \"0\" when no address was stored.","example":"3405803786"},"links":{"type":"object","description":"URLs of the record's related reads.","properties":{"contact":{"type":"string","description":"URL to the contact."},"campaign":{"type":"string","description":"URL to the campaign."},"message":{"type":"string","description":"URL to the message."}}},"id":{"type":"string","description":"Id of the record.","example":"31"},"contact":{"type":["string","null"],"description":"Id of the contact. Same value as subscriberid. null when subscriberid is 0.","example":"110"},"campaign":{"type":["string","null"],"description":"Id of the campaign. Same value as campaignid. null when campaignid is 0.","example":"12"},"message":{"type":["string","null"],"description":"Id of the message. Same value as messageid. null when messageid is 0.","example":"15"}}},"ContactWrite":{"type":"object","description":"The contact fields that create and update both accept. On update, only the fields you send change.","properties":{"email":{"type":["string","null"],"description":"The contact's email address. Line breaks are removed, and so are spaces at either end. It must be valid and no other contact may have it, or the request fails with 422. Required on create, unless allowNullEmail applies. On update, leave it out to keep the current address.","example":"johndoe@example.com"},"firstName":{"type":"string","description":"The contact's first name."},"lastName":{"type":"string","description":"The contact's last name."},"phone":{"type":"string","description":"The contact's phone number. Must be a string; a number fails with 422.","example":"7223224241"},"allowNullEmail":{"type":"boolean","description":"Set to true to save the contact without an email address. This only works when the account has phone-only contacts turned on. The phone must then be unique, and is required unless the contact has a channel identity. When phone-only contacts are off, an email is still required. Leave email out or send null; an empty string still fails."},"fieldValues":{"type":"array","description":"Custom field values to save with the contact. Each item sets one field. Fields you leave out are not changed. The saved values are returned in the top-level fieldValues array of the response.","items":{"type":"object","properties":{"field":{"type":["integer","string"],"description":"Id of the custom field.","example":"1"},"value":{"type":["string","number","boolean","array","null"],"items":{"type":"string"},"description":"The new value. Lists are only supported for checkbox and listbox fields. For those fields, a string with the options separated by || also works.","example":"The Value for First Field"}},"additionalProperties":false}},"fields":{"type":"array","description":"Deprecated: use fieldValues. The old name for fieldValues, with the same items. Ignored when fieldValues is sent.","items":{"type":"object","description":"A field and value, as in fieldValues.","properties":{"field":{"type":["integer","string"],"description":"Id of the custom field."},"value":{"type":["string","number","boolean","array","null"],"items":{"type":"string"}}},"additionalProperties":false}},"account":{"type":"object","description":"Links the contact to an account. Send either id or name, not both. Needs the Accounts feature and the edit contacts permission, or the request fails with 403. When sent, organization and account_name are ignored.","properties":{"id":{"type":["integer","string"],"description":"Id of an existing account. An id that does not exist fails with 422.","example":12},"name":{"type":"string","description":"Name of the account. Spaces at either end and letter case do not matter. If no account has this name, the request fails with 422 unless createIfMissing is true.","example":"Example Inc"},"createIfMissing":{"type":"boolean","description":"Only with name. Set to true to create the account when no account has the name. Creating needs the add accounts permission, or the request fails with 403. Defaults to false. The account is created before the contact is checked, so it stays even if the request then fails."}},"additionalProperties":false},"organization":{"type":["integer","string"],"description":"Deprecated: use account. Id of the account to link the contact to. Ignored when account is sent."},"account_name":{"type":"string","description":"Name of the account to link the contact to. The contact links to the account with this name, which is created if none has it. Used only when neither account nor organization is sent, and only when the account has the Accounts feature; otherwise ignored. The account is created before the contact is checked, so it stays even if the request then fails."},"orgid":{"type":["integer","string"],"description":"Deprecated: use account. Id of the account to link the contact to. If sent together with account or organization, orgid wins."},"tags":{"type":"array","description":"Names of tags to add to the contact. A name that no tag has yet creates that tag. Tags the contact already has stay, and so do tags you leave out; this field never removes a tag. In each name, commas and line breaks become spaces, and HTML, emoji and spaces at either end are removed. A name that is then empty or longer than 250 characters fails with 422. New tags are created before the contact is checked, so they stay even if the request then fails.","items":{"type":"string"},"example":["vip","newsletter"]},"lists":{"type":"array","description":"Lists to subscribe the contact to. Each list you name becomes an active subscription, also when the contact was unconfirmed or unsubscribed on it. The exception is a double opt-in form in contact.form; see form. Lists you leave out are not changed. A non-empty list needs the edit contacts permission, on create too, or the request fails with 403. All lists are checked before the contact is saved, and the contact is not saved if one fails. A list that does not exist, or an item with a key not listed here, fails with 422. So does resubscribing a contact who unsubscribed from the list, unless the user has the permission to resubscribe contacts. An email list needs a contact with an email address and an SMS list needs one with a phone number, or the request fails with 400. The mail options below do nothing while a subscription is unconfirmed.","items":{"type":"object","required":["list"],"properties":{"list":{"type":["integer","string"],"description":"Id of the list.","example":1},"sdate":{"type":"string","description":"When the subscription started, as YYYY-MM-DD HH:MM:SS or YYYY-MM-DD (start of that day). It is set even when the contact is already on the list. Leave it out to keep the current date; a new subscription, or one that becomes active again, then starts now. Any other format fails with 422.","example":"2026-01-15 09:30:00"},"sendInstantAutoresponder":{"type":"boolean","description":"Set to true to send the list's subscribe autoresponders even when the contact was already on the list or had unsubscribed. Cannot be true together with suppressInstantAutoresponder. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."},"suppressInstantAutoresponder":{"type":"boolean","description":"Set to true to not send the list's subscribe autoresponders. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."},"sendLastCampaign":{"type":"boolean","description":"Set to true to send the contact the last campaign sent to the list, even when the list is not set up to do that. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."}},"additionalProperties":false}},"form":{"type":["integer","string"],"description":"Id of a form. The write then acts like a submission of that form. The contact is also subscribed to the form's lists, with the same permission and checks as lists. If the form uses double opt-in, every list subscription this request creates stays unconfirmed, including lists named in contact.lists. The confirmation email is sent when one of the form's own lists gets a new subscription, and the form's actions and its submit automations run once the contact confirms. Otherwise they run now. An id that is not a form fails with 422.","example":3},"ip4":{"type":["string","null"],"description":"The IPv4 address the contact signed up from. It is saved on the contact, where ip in the response shows it as a number, and on the list subscriptions this request creates. An address that is not IPv4, such as an IPv6 address, fails with 422. An empty string or null records nothing.","example":"203.0.113.10"},"whatsapp_id":{"type":"string","description":"The contact's WhatsApp user id from Meta. Used only when the account has a WhatsApp inbox; otherwise it is dropped, and so is whatsapp_username when sent with it. It also needs phone-only contacts turned on, or the request fails with 422. With a whatsapp_id the email address is optional. If another contact already has this id, the request fails with 409.","example":"15551234567"},"whatsapp_username":{"type":"string","description":"The contact's WhatsApp username. Without a WhatsApp inbox it is dropped when sent with whatsapp_id, and saved when sent alone."},"channelIdentities":{"type":"array","items":{"type":"object","required":["source","channelAccountId","externalId"],"properties":{"source":{"type":"string","enum":["instagram","messenger"]},"channelAccountId":{"type":"string","minLength":1,"maxLength":64},"externalId":{"type":"string","minLength":1,"maxLength":255}},"additionalProperties":false}},"open_tracking_optout":{"type":["integer","string"],"enum":[0,1,"0","1"]}}},"ContactWriteConflict":{"type":"object","description":"The body of a contact write refused because of a conflict.","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status.","example":409},"title":{"type":"string","description":"The name of the HTTP status, in the user's language.","example":"Conflict"},"detail":{"type":"string","description":"Why the request was refused.","example":"A contact with this whatsapp_id already exists"}}}}}},"ContactWriteForbidden":{"type":"object","description":"The body of a refused contact write, for 400 and 403.","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status.","example":"403"},"detail":{"type":"string","description":"Why the request was refused.","example":"Forbidden, the user doesn't have permission to add contacts."}}}}}},"ContactWriteValidationError":{"type":"object","description":"The body of a failed contact validation, such as a duplicate email. Other 422s, such as a malformed account link or a fieldValues that is not a list, use a different body: errors items with status (the number 422), title, detail and sometimes source.pointer, but no code or error.","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"title":{"type":"string","description":"What went wrong.","example":"Email address already exists in the system."},"detail":{"type":"string","description":"More about the problem. Empty for the email errors.","example":""},"code":{"type":"string","description":"A short error code. For example: duplicate for an email another contact has, field_missing for a missing email, email_invalid for an invalid one, field_invalid for a phone that is not a string.","example":"duplicate"},"error":{"type":"string","description":"Extra error text. Empty for the email errors.","example":""},"source":{"type":"object","description":"Where in the request the problem is.","properties":{"pointer":{"type":"string","description":"The field that failed.","example":"/data/attributes/email"}}}}}}}},"ContentCompletion":{"description":"One generated text.","required":["text","id"],"properties":{"text":{"description":"The generated text; null when the model returned none for this slot.","type":["string","null"],"example":"Spring is here, and so are our new garden tools. Shop the collection today."},"id":{"description":"Position of the result, from 0.","type":"integer","example":0}},"type":"object"},"ContentCompletionResponse":{"description":"Generated texts, or the reason none were.","required":["results","suggestions"],"properties":{"error":{"description":"Present only when the model call failed: its error message. results is then empty.","type":["string","null"],"example":"The model request timed out"},"results":{"description":"resultCount generated texts; empty when error is set.","type":"array","items":{"$ref":"#/components/schemas/ContentCompletion"}},"suggestions":{"description":"Always empty; kept for the shape clients expect.","type":"array","items":{"type":"string"},"example":[]}},"type":"object"},"ContentComposeRequest":{"description":"What to write, how many versions, and in whose voice.","required":["prompt","resultCount"],"properties":{"prompt":{"description":"What to write, in plain words.","type":"string","example":"A short email intro announcing our spring sale on garden tools"},"resultCount":{"description":"How many versions to generate, 1 to 8.","type":"integer","example":3},"requestSource":{"description":"Where the request comes from, for usage reporting (for example the editor block that asked).","type":"string","example":"campaign-editor"},"brandkitUuid":{"description":"UUID of a brand kit whose voice to write in, or primary for the account's primary brand kit. An unknown UUID answers 422.","type":["string","null"],"example":"primary"},"tone":{"description":"Voice to write in, one of the template content tones.","type":["string","null"],"example":"friendly"}},"type":"object"},"ContentEditRequest":{"description":"Text to rewrite and how.","properties":{"resultCount":{"description":"How many rewritten versions to generate, 1 to 8.","type":"integer","example":2},"editInstructions":{"description":"What to change, in plain words.","type":"string","example":"Make it shorter and more upbeat"},"originalContent":{"description":"The texts to rewrite; at least one.","type":"array","items":{"type":"string"},"example":["Spring is here. Our garden tools are on sale this week."]}},"type":"object"},"ContentManagerFoldersResponse":{"description":"The Content Manager folders the AI features store images in. Each ID is null when the folder does not exist yet.","required":["brandLogosFolderId","imageGenerationFolderId","stockImagesFolderId","websiteImagesFolderId"],"properties":{"brandLogosFolderId":{"description":"Folder holding brand kit logos.","type":["integer","null"],"example":12},"imageGenerationFolderId":{"description":"Folder holding AI-generated images.","type":["integer","null"],"example":13},"stockImagesFolderId":{"description":"Folder holding imported stock photos.","type":["integer","null"],"example":14},"websiteImagesFolderId":{"description":"Folder holding images imported from the account's website.","type":["integer","null"],"example":15}},"type":"object"},"ContentRemappingErrorResponse":{"description":"Why the request was refused, in one sentence.","required":["error"],"properties":{"error":{"description":"The reason, as a sentence meant for the caller.","type":"string","example":"Content remapping job not found: a1b2c3d4-e5f6-4789-abcd-ef0123456789"}},"type":"object"},"ContentRemappingJobStatus":{"description":"Where a content remapping job stands: in progress, finished, or failed with the reason.","required":["requestId","campaignId","status","step"],"properties":{"requestId":{"description":"UUID of the remapping job, as given in the path.","type":"string","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"campaignId":{"description":"Id of the campaign the job rewrites.","type":"integer","example":123},"status":{"description":"in_progress until the worker finishes; then success when the campaign was rewritten, or failed when it was not.","type":"string","enum":["in_progress","success","failed"],"example":"success"},"step":{"description":"The stage the worker last reported: null before it starts, then remapping_content, processing_images, compiling and saving, and completed once the job succeeded. A failed job keeps the stage it failed in.","type":["string","null"],"enum":["remapping_content","processing_images","compiling","saving","completed",null],"example":"completed"},"error":{"description":"Only on a failed job: why it failed, for example that the campaign was being modified by another request or was no longer editable. May be null when the failure recorded no message.","type":["string","null"],"example":"Campaign is being modified by another request"},"degradations":{"description":"Only when the job finished with something it could not do. brand_logo_not_applied means the brand kit logo could not be placed into the new design, so the campaign shipped without it.","type":"array","items":{"type":"string","enum":["brand_logo_not_applied"]},"example":["brand_logo_not_applied"]}},"type":"object"},"ContentRemappingJobSummary":{"description":"A content remapping job: its id, the campaign it rewrites, and where it stands.","required":["requestId","campaignId","status"],"properties":{"requestId":{"description":"UUID of the remapping job. Poll GET /ai/campaigns/content-remapping/{requestId} with it.","type":"string","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"campaignId":{"description":"Id of the campaign whose content is being remapped.","type":"integer","example":123},"status":{"description":"in_progress when the job was just created and queued; success when the worker endpoint reports a finished job.","type":"string","enum":["in_progress","success"],"example":"in_progress"}},"type":"object"},"ContentRemappingLayoutRequest":{"description":"Which campaign to remap and the built-in layout to pour its content into. The brand kit is optional: left out, the account's primary brand kit styles the layout.","required":["campaignId","layout"],"properties":{"campaignId":{"description":"Id of the campaign whose content is remapped. It must exist, be accessible to the API user, not be sent or sending, and have been built in the current designer with blocks the XML flow supports.","type":"integer","example":123},"layout":{"description":"Name of the built-in layout to pour the content into: the file name under CampaignGenerationBlocks/Layouts without its .xml extension, for example welcome, promote, announcement, monthly, whatsnew, flashsale, producthighlight or fashioneditorial.","type":"string","example":"welcome"},"mode":{"description":"Colour mode the layout is rendered in. Defaults to light.","type":"string","enum":["light","dark"],"example":"light"},"brandkitUuid":{"description":"UUID of the brand kit whose colours, fonts and logo style the layout. Left out, the account's primary brand kit is used and no brand context is sent to the model.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"sessionId":{"description":"Client session id stored on the job and passed to the model calls for tracing.","type":["string","null"],"example":"sess_01HZY3K9Q"},"campaignRecord":{"description":"Not sent by the caller: the server resolves the campaign named by campaignId into it while validating.","type":"object","readOnly":true},"brandkitRecord":{"description":"Not sent by the caller: the server resolves the brand kit record named by brandkitUuid into it while validating.","type":"object","readOnly":true}},"type":"object"},"ContentRemappingStockTemplateRequest":{"description":"Which campaign to remap and the ActiveCampaign stock template to pour its content into. The brand kit is optional: left out, the account's primary brand kit supplies the logo.","required":["campaignId","hash"],"properties":{"campaignId":{"description":"Id of the campaign whose content is remapped. It must exist, be accessible to the API user, not be sent or sending, and have been built in the current designer with blocks the XML flow supports.","type":"integer","example":123},"hash":{"description":"Name hash of the stock template to pour the content into, as listed by the template gallery. Only current-designer (V3) stock templates are accepted.","type":"string","example":"abc123hash456789012345678901234567890ab"},"sessionId":{"description":"Client session id stored on the job and passed to the model calls for tracing.","type":["string","null"],"example":"sess_01HZY3K9Q"},"brandkitUuid":{"description":"UUID of the brand kit whose logo is placed into the template. Left out, the account's primary brand kit is used.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"campaignRecord":{"description":"Not sent by the caller: the server resolves the campaign named by campaignId into it while validating.","type":"object","readOnly":true},"brandkitRecord":{"description":"Not sent by the caller: the server resolves the brand kit record named by brandkitUuid into it while validating.","type":"object","readOnly":true},"templateContent":{"description":"Not sent by the caller: the server loads the stock template named by hash (its HTML and CSS) into it while validating.","type":"object","readOnly":true}},"type":"object"},"ContentRemappingTemplateRequest":{"description":"Which campaign to remap and the account's own saved template to pour its content into. The brand kit is optional: left out, the account's primary brand kit supplies the logo.","required":["campaignId","templateId"],"properties":{"campaignId":{"description":"Id of the campaign whose content is remapped. It must exist, be accessible to the API user, not be sent or sending, and have been built in the current designer with blocks the XML flow supports.","type":"integer","example":123},"templateId":{"description":"Id of the saved template to pour the content into. It must exist, be accessible to the API user, and carry designer HTML and CSS the XML flow can read back.","type":"integer","example":10},"sessionId":{"description":"Client session id stored on the job and passed to the model calls for tracing.","type":["string","null"],"example":"sess_01HZY3K9Q"},"brandkitUuid":{"description":"UUID of the brand kit whose logo is placed into the template. Left out, the account's primary brand kit is used.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"campaignRecord":{"description":"Not sent by the caller: the server resolves the campaign named by campaignId into it while validating.","type":"object","readOnly":true},"templateRecord":{"description":"Not sent by the caller: the server resolves the template named by templateId into it while validating.","type":"object","readOnly":true},"brandkitRecord":{"description":"Not sent by the caller: the server resolves the brand kit record named by brandkitUuid into it while validating.","type":"object","readOnly":true}},"type":"object"},"ContentSummarizationCreateRequest":{"description":"What to summarize and in what form it comes.","required":["type","format","data"],"properties":{"type":{"description":"Kind of source.","type":"string","enum":["file","website","video"],"example":"website"},"format":{"description":"Format of the source: link for a website or video address, mp4 or pdf for an uploaded file.","type":"string","enum":["link","mp4","pdf"],"example":"link"},"data":{"description":"The source: the address for link, the uploaded file's location for mp4 and pdf.","type":"string","example":"https://www.example.com/catalogue"},"name":{"description":"Name for the record; omitted, one is derived from the content.","type":["string","null"],"example":"Acme spring catalogue"}},"type":"object"},"ContentSummarizationGenerateResponse":{"description":"Outcome of the summarization job.","required":["status"],"properties":{"status":{"description":"success when the summary was written and stored, error when the model call failed; the record carries the same status.","type":"string","enum":["success","error"],"example":"success"}},"type":"object"},"ContentSummarizationGenerateWorkerRequest":{"description":"The job POST /ai/summarization queues: the record to fill and the parsed content to summarize. Sent only by Hosted's own background dispatcher.","required":["summarization_id","data"],"properties":{"summarization_id":{"description":"ID of the summarization record; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"data":{"description":"The parsed text of the source.","type":"string","example":"Acme sells garden tools..."}},"type":"object"},"ContentSummarizationResponse":{"description":"A finished content summarization.","required":["type","format","dataLocation","name","status","summary"],"properties":{"type":{"description":"Kind of source that was summarized.","type":"string","enum":["file","website","video"],"example":"website"},"format":{"description":"Format of the source.","type":"string","enum":["link","mp4","pdf"],"example":"link"},"dataLocation":{"description":"Where the source was read from: the address sent for a website or video, the stored location for a file.","type":"string","example":"https://www.example.com/catalogue"},"name":{"description":"Name of the source.","type":"string","example":"Acme spring catalogue"},"status":{"description":"Always success on this route: other statuses answer 409 or 500.","type":"string","enum":["success"],"example":"success"},"summary":{"description":"The summary the model wrote, as a JSON string following the summarization schema.","type":["string","null"],"example":"{\"businessName\":\"Acme\",\"products\":[\"Garden tools\"]}"}},"type":"object"},"ContentSummarizationSummary":{"description":"A content summarization record in brief.","required":["id","name","status"],"properties":{"id":{"description":"ID of the summarization; pass it to GET /ai/summarization/{summarizationId}.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"name":{"description":"Name of the source: the name sent on create, or one derived from the content (a page title, a file name).","type":"string","example":"Acme spring catalogue"},"status":{"description":"in_progress until the background job finishes, then success or error.","type":"string","enum":["in_progress","success","error"],"example":"in_progress"}},"type":"object"},"ConversationEdit":{"type":"object","properties":{"id":{"type":"string","description":"The UUID of the Conversation."},"contact":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/ConversationStatusEnum"},"assigned":{"type":"array","items":{"$ref":"#/components/schemas/UserBasicEdit"},"description":"The Users assigned to the Conversation."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ConversationTag"},"description":"The Tags assigned to the Conversation."},"created_on":{"type":"string","format":"date-time","readOnly":true,"title":"Created on"},"source":{"allOf":[{"$ref":"#/components/schemas/ConversationSourceEnum"}],"readOnly":true},"assigned_team":{"type":"integer","description":"The ID of the Team assigned to the Conversation."},"channel":{"type":"integer","nullable":true}},"required":["assigned","contact","created_on","id","source"]},"ConversationReadSimple":{"type":"object","properties":{"id":{"type":"string","description":"The UUID of the Conversation."},"contact":{"type":"string","format":"uuid"},"status":{"allOf":[{"$ref":"#/components/schemas/ConversationStatusEnum"}],"readOnly":true},"first_message":{"allOf":[{"$ref":"#/components/schemas/WhatsAppMessageSimple"}],"description":"The first Message of the Conversation."},"assigned":{"type":"array","items":{"$ref":"#/components/schemas/UserSimple"},"description":"The Users assigned to the Conversation."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ConversationTag"},"description":"The Tags assigned to the Conversation."},"created_on":{"type":"string","format":"date-time","readOnly":true,"title":"Created on"},"source":{"allOf":[{"$ref":"#/components/schemas/ConversationSourceEnum"}],"readOnly":true},"assigned_team":{"type":"integer","description":"The ID of the Team assigned to the Conversation."},"channel":{"type":"integer","nullable":true}},"required":["assigned","contact","created_on","first_message","id","source","status"]},"ConversationSourceEnum":{"enum":["INBOX","AUTO_RESPONSE","API","BROADCAST","FLOW","UNKNOWN"],"type":"string","description":"* `INBOX` - Inbox\n* `AUTO_RESPONSE` - Auto Response\n* `API` - Api\n* `BROADCAST` - Broadcast\n* `FLOW` - Flow\n* `UNKNOWN` - Unknown"},"ConversationStatusEnum":{"enum":["CREATED","FLOW","NEW","IN_PROGRESS","RESOLVED","CLOSED"],"type":"string","description":"* `CREATED` - Created\n* `FLOW` - Flow\n* `NEW` - New\n* `IN_PROGRESS` - In Progress\n* `RESOLVED` - Resolved\n* `CLOSED` - Closed"},"ConversationTag":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"name":{"type":"string","maxLength":100}},"required":["id","name"]},"Conversion":{"title":"Conversion","type":"object","description":"A tracked event or action with an optional dollar value, used to measure campaign/automation effectiveness. ORM class Conversion, table em_conversion.","properties":{"id":{"type":"integer"},"name":{"type":"string"},"value":{"type":"number","description":"Dollar value. Stored as cents in the DB; this is the dollar amount."},"currency":{"type":"string"},"limit":{"type":"integer"},"enforcelimit":{"type":"integer","enum":[0,1]},"value_option":{"type":"integer","description":"Exact enum not fully confirmed."},"field_data":{"type":"string","nullable":true},"cdate":{"type":"string","format":"date-time"},"udate":{"type":"string","format":"date-time"},"total":{"type":"integer","description":"Only present when with_counts=1 on the list endpoint."},"total_last_30days":{"type":"integer","description":"Only present when with_counts=1 on the list endpoint."},"last":{"type":"string","format":"date-time","nullable":true,"description":"Only present when with_counts=1 on the list endpoint."},"is_required_by_goal":{"type":"boolean","description":"Only present when is_required_by_goal=1 on the list endpoint."},"folder_ids":{"type":"array","items":{"type":"integer"},"description":"Only present when is_required_by_goal=1 on the list endpoint."}},"required":["id","name"]},"ConversionData":{"title":"ConversionData","type":"object","description":"Conversion statistics and graph data, as returned by GET /conversions/data and GET /conversions/{id}/data. Grounded against InitiativeConversionDataDTO::jsonSerialize().","properties":{"conversionId":{"type":"integer"},"conversionName":{"type":"string"},"conversionValue":{"type":"integer"},"valueOption":{"type":"integer"},"totalCount":{"type":"integer"},"totalValue":{"type":"integer"},"currency":{"type":"string"},"graphData":{"type":"array","items":{"type":"object","properties":{"conversionid":{"type":"integer"},"cdate":{"type":"string","format":"date-time"},"totalCount":{"type":"integer","nullable":true},"totalValue":{"type":"integer","nullable":true}}}},"backfillData":{"type":"object","description":"Only present when include_backfill=1 and initiativeId is set.","properties":{"totalCount":{"type":"integer"},"totalValue":{"type":"integer"}}},"graphOverlayData":{"type":"array","description":"Only present when include_graph_overlay=1 and initiativeId is set. Item shape not fully confirmed (InitiativeAssetEvent).","items":{"type":"object"}},"totalCountInDateRange":{"type":"integer","description":"Only present when include_total_and_avg=1."},"averagePerDayInDateRange":{"type":"number","description":"Only present when include_total_and_avg=1."},"percentToTarget":{"type":"number","description":"Only present when the conversion has an active business-goal target."},"conversionState":{"type":"string","description":"Only present when use_overview_config=1."},"conversionTargetStatus":{"type":"integer","description":"Only present when the conversion has an active business-goal target."},"conversionTargetStatusLabel":{"type":"string","description":"Only present when the conversion has an active business-goal target."},"goalType":{"type":"integer","enum":[1,2]},"goalValue":{"type":"integer"},"goalCurrency":{"type":"string"}},"required":["conversionId","conversionName","conversionValue","valueOption","totalCount","totalValue","currency","graphData"]},"ConversionLabelEntry":{"title":"ConversionLabelEntry","description":"The association row between a conversion and a label/folder, optionally carrying a business-goal target. ORM class ConversionFolder, table em_conversion_folder.","required":["id","conversion","label"],"properties":{"id":{"description":"ID of the conversion label association.","type":"integer"},"conversion":{"description":"Conversion ID. API field name for the conversionid column.","type":"integer"},"label":{"description":"Folder ID. API field name for the folderid column.","type":"integer"},"goalType":{"description":"Type of the business-goal target: 1 = total conversion event count, 2 = total conversion revenue. Null when the conversion has no target.","type":["integer","null"],"enum":[1,2]},"goalValue":{"description":"Value of the business-goal target. Null when the conversion has no target.","type":["integer","null"]},"goalCurrency":{"description":"Currency of the business-goal target. Null when the conversion has no target.","type":["string","null"]},"conversionTargetStatus":{"description":"Progress of the target: 0 = not started, 1 = on track, 2 = needs attention, 3 = at risk.","type":"integer","enum":[0,1,2,3]},"created_timestamp":{"description":"When the association was created.","type":"string","format":"date-time"},"updated_timestamp":{"description":"When the association was last updated.","type":"string","format":"date-time"},"conversionId":{"description":"ID of the conversion. Only present when include_conversions=1.","type":"integer"},"conversionName":{"description":"Name of the conversion. Only present when include_conversions=1.","type":"string"},"conversionValue":{"description":"Value of the conversion. Only present when include_conversions=1.","type":["number","null"]},"conversionCurrency":{"description":"Currency of the conversion. Only present when include_conversions=1.","type":"string"}},"type":"object"},"ConversionMetric":{"title":"ConversionMetric","type":"object","description":"Grounded against ConversionAgentService::getConversionMetrics().","properties":{"conversionId":{"type":"integer"},"conversionName":{"type":"string"},"eventCount":{"type":"integer"},"uniqueContacts":{"type":"integer"},"conversionValueOption":{"type":"string","enum":["count","revenue"]},"totalValue":{"type":"number","description":"Only present when conversionValueOption is 'revenue'."},"currency":{"type":"string","description":"Only present when conversionValueOption is 'revenue'."}},"required":["conversionId","conversionName","eventCount","uniqueContacts","conversionValueOption"]},"ConversionMetricEntry":{"title":"ConversionMetricEntry","description":"Grounded against ConversionAgentService::getConversionMetrics().","required":["conversionId","conversionName","eventCount","uniqueContacts","conversionValueOption"],"properties":{"conversionId":{"description":"ID of the conversion.","type":"integer"},"conversionName":{"description":"Name of the conversion.","type":"string"},"eventCount":{"description":"Number of times the conversion happened in the period.","type":"integer"},"uniqueContacts":{"description":"Number of distinct contacts that converted in the period.","type":"integer"},"conversionValueOption":{"description":"Whether the conversion counts events or sums revenue.","type":"string","enum":["count","revenue"]},"totalValue":{"description":"Only present when conversionValueOption is 'revenue'.","type":"number"},"currency":{"description":"Only present when conversionValueOption is 'revenue'.","type":"string"}},"type":"object"},"ConversionTrigger":{"description":"A rule that fires a conversion for a contact when something happens: a segment is entered, a URL is visited, an event is tracked, a goal or automation block is reached, an ecommerce order completes, or a user triggers it manually. Each trigger belongs to one conversion.","required":["id","conversion","triggerType"],"properties":{"id":{"description":"Unique id of the conversion trigger.","type":"integer","example":12},"conversion":{"description":"Id of the conversion this trigger fires. The ID is stored in the conversionid column and returned here as `conversion`.","type":"integer","example":3},"triggerType":{"description":"What fires the conversion. `segment`: a contact enters the segment in `segment_id`. `url`: a contact visits a page matched by `modifier` and `value`. `event`: a tracked event named `value`. `goal` and `automation`: a contact reaches the automation block named in `modifier`. `ecommerce`: an ecommerce order completes. `manual`: fired by a user or an API call. Stored in the type column.","type":"string","enum":["segment","manual","url","event","automation","goal","ecommerce"],"example":"url"},"modifier":{"description":"For `url` triggers, how `value` is compared with the visited URL: `matches` (the visited URL matches `value`, ignoring case) or `contains` (the URL contains `value`). For `goal` and `automation` triggers it holds the id of the automation block, which the response repeats as `automationBlock`.","type":"string","example":"contains"},"value":{"description":"What to look for, depending on `triggerType`: the URL or URL fragment for `url` triggers, the event name for `event` triggers. Not used by the other types.","type":"string","example":"/thank-you"},"dynamic":{"description":"1 when the conversion's value is the value passed with the event that fired it instead of the fixed value on the conversion; 0 otherwise. Applies to `event`, `manual` and `ecommerce` triggers.","type":"integer","enum":[0,1],"example":0},"retroactive":{"description":"1 when creating the trigger also starts a background process that fires the conversion for contacts whose past tracking activity matches it; 0 otherwise. The flag has no effect on `segment`, `manual`, `goal` and `automation` triggers.","type":"integer","enum":[0,1],"example":0},"segment_id":{"description":"Id of the segment that fires the conversion when `triggerType` is `segment`; null for the other types. Deleting the trigger also deletes this segment; a failure to delete it is only logged.","type":["string","null"],"example":null},"meta":{"description":"Free-form JSON that varies by trigger. The pre-packaged custom object trigger stores `type` (`pre-packaged-co`) and `data` with the singular and plural `labels` of the object, its fields and its relationships. Null when the trigger has none.","type":["object","null"],"example":null},"automationBlock":{"description":"Only present when `triggerType` is `goal` or `automation`: the automation block id, repeated from `modifier`.","type":"string"},"cdate":{"description":"Date and time the trigger was created.","type":"string","format":"date-time","example":"2026-10-01T09:15:00-05:00"},"udate":{"description":"Date and time the trigger was last updated.","type":"string","format":"date-time","example":"2026-10-01T09:15:00-05:00"}},"type":"object"},"ConversionTriggerBulkWrite":{"title":"ConversionTriggerBulkWrite","type":"object","description":"Writable fields for one item of a bulk create or update. api/3/conversionTrigger/bulk.php passes each item straight to ConversionTrigger::fill(), so items use the persisted column names `conversionid` and `type`, not the `conversion` and `triggerType` API aliases accepted by /conversionTriggers.","properties":{"conversionid":{"type":"integer"},"type":{"type":"string","enum":["segment","manual","url","event","automation","goal","ecommerce"]},"modifier":{"type":"string"},"value":{"type":"string"},"dynamic":{"oneOf":[{"type":"integer","enum":[0,1]},{"type":"boolean"}]},"retroactive":{"type":"integer","enum":[0,1]},"segment_id":{"type":"string","nullable":true},"meta":{"type":"object","nullable":true},"conversion":{"type":"integer","description":"Alternative to conversionid: ID of the conversion the trigger belongs to."},"triggerType":{"type":"string","enum":["segment","manual","url","event","automation","goal","ecommerce"],"description":"Alternative to type: the trigger type."}}},"ConversionTriggerRequest":{"description":"A conversionTrigger object wrapping the trigger fields","required":["conversionTrigger"],"properties":{"conversionTrigger":{"$ref":"#/components/schemas/ConversionTriggerWrite","description":"The fields of the conversion trigger."}},"type":"object"},"ConversionTriggerResponse":{"description":"A single conversion trigger, under conversionTrigger","properties":{"conversionTrigger":{"$ref":"#/components/schemas/ConversionTrigger","description":"The conversion trigger."}},"type":"object"},"ConversionTriggerWrite":{"description":"Fields of a conversion trigger that can be set when creating or updating one. Fields left out of an update keep their current values.","properties":{"conversion":{"description":"Id of the conversion this trigger fires.","type":"integer","example":3},"triggerType":{"description":"What fires the conversion; see `ConversionTrigger.triggerType` for the meaning of each value.","type":"string","enum":["segment","manual","url","event","automation","goal","ecommerce"],"example":"url"},"modifier":{"description":"For `url` triggers, how `value` is compared with the visited URL: `matches` (the visited URL matches `value`, ignoring case) or `contains` (the URL contains `value`). For `goal` and `automation` triggers it holds the id of the automation block, which the response repeats as `automationBlock`.","type":"string","example":"contains"},"value":{"description":"What to look for, depending on `triggerType`: the URL or URL fragment for `url` triggers, the event name for `event` triggers. Not used by the other types.","type":"string","example":"/thank-you"},"dynamic":{"description":"1 (or true) to take the conversion's value from the event that fires it; 0 to use the conversion's fixed value.","example":0,"oneOf":[{"type":"integer","enum":[0,1]},{"type":"boolean"}]},"retroactive":{"description":"1 when creating the trigger also starts a background process that fires the conversion for contacts whose past tracking activity matches it; 0 otherwise. The flag has no effect on `segment`, `manual`, `goal` and `automation` triggers.","type":"integer","enum":[0,1],"example":0},"segment_id":{"description":"Id of the segment to watch when `triggerType` is `segment`. Null for the other types.","type":["string","null"],"example":null},"meta":{"description":"Free-form JSON that varies by trigger. The pre-packaged custom object trigger stores `type` (`pre-packaged-co`) and `data` with the singular and plural `labels` of the object, its fields and its relationships. Null when the trigger has none.","type":["object","null"],"example":null}},"type":"object"},"ConversionTriggersListResponse":{"description":"A page of conversion triggers, with the total in meta.total","properties":{"conversionTriggers":{"description":"The conversion triggers in this page of results.","type":"array","items":{"$ref":"#/components/schemas/ConversionTrigger"}},"meta":{"description":"Paging information.","properties":{"total":{"description":"Number of conversion triggers that matched, ignoring limit and offset.","type":"integer","example":1}},"type":"object"}},"type":"object"},"ConversionsPerformanceSummary":{"description":"The stored performance summary of one conversion linked to a business goal, and where its generation stands.","required":["goalId","conversionId","status","summary"],"properties":{"goalId":{"description":"ID of the business goal the summary is for.","type":"integer","example":2228},"conversionId":{"description":"ID of the conversion the summary is for.","type":"integer","example":23},"status":{"description":"in_progress until generation records a result (it stays in_progress if generation stops without recording one), success once summary holds the text, error when generation recorded a failure or could not be started.","type":"string","enum":["in_progress","success","error"],"example":"success"},"summary":{"description":"The summary: one paragraph written by an AI model, which can contain HTML <strong> tags, or a fixed, translated message when the conversion is not linked to the goal, or when the conversion cannot be found. Null while status is in_progress or error.","type":["string","null"],"example":"There are no updates at this time. Add a conversion and goal to generate a summary!"}},"type":"object"},"ConversionsPerformanceSummaryCreateResponse":{"description":"The performance summary record for the goal and conversion: the one just created, or the stored one when it is finished and not yet expired. Poll this same operation until status is success or error.","required":["id","status","summary"],"properties":{"id":{"description":"The record's identifier, ai-conversions-performance-summary-<goalId>-<conversionId>. Empty only in the rare redlocked case described under status.","type":"string","example":"ai-conversions-performance-summary-2228-23"},"status":{"description":"in_progress: a record was created and the generation request queued; the summary is not ready. success or error: the stored record is finished and younger than expirationHours, so it is returned instead of starting a new generation. redlocked: another request took the per-goal-and-conversion lock between the controller's own lock check and the service's; id and summary are empty strings. Call again later.","type":"string","enum":["in_progress","success","error","redlocked"],"example":"in_progress"},"summary":{"description":"The generated summary text when status is success, including the fixed \"no data\" texts used when the conversion has no events in the interval. Null while in progress or after an error; an empty string when redlocked.","type":["string","null"],"example":null}},"type":"object"},"ConversionsPerformanceSummaryGenerateRequest":{"description":"Which stored conversion performance summary to generate, and how. Sent only by Hosted's own background dispatcher, never by a client. Send each field with the JSON type shown.","required":["summaryId","intervalDays","tone"],"properties":{"summaryId":{"description":"ID of the stored summary record to generate, as returned in id by POST /ai/conversions/performance/summary.","type":"string","example":"ai-conversions-performance-summary-2228-23"},"tone":{"description":"Tone of voice of the generated summary.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"intervalDays":{"description":"How many days of performance the summary analyses. Between 1 and 30.","type":"integer","maximum":30,"minimum":1,"example":7}},"type":"object"},"ConversionsPerformanceSummaryRedlockedResponse":{"description":"Another request holds the lock for this goal and conversion, so nothing was created or read. The lock is taken when a generation request is queued and released when generation finishes, or after 90 seconds. Call again later.","required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"},"status":{"description":"Always redlocked.","type":"string","enum":["redlocked"],"example":"redlocked"}},"type":"object"},"CreateCampaignFromStockTemplateRequest":{"description":"Which stock template to start the campaign from and what the model should change in it.","required":["hash","userPrompt"],"properties":{"hash":{"description":"Hash of the stock template, the id of GET /templates/stock. Only Email Designer (Stripo) stock templates are accepted; an unknown hash or an older template is refused with 422.","type":"string","example":"a3f9c2e1b7d4"},"userPrompt":{"description":"What the model should change in the template's content, 5 to 5000 characters.","type":"string","example":"Turn this into a spring sale announcement for our garden furniture range, 20% off until Sunday."},"images":{"description":"Up to 7 images for the model to place in the campaign. Each names the image by URL and says where it goes: main for the hero image, random to let the model choose, or a short free-text placement hint. Omitted, the template's own images stay.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"Address of the image, http or https, up to 2048 characters.","type":"string","format":"uri","example":"https://cdn.example.com/spring-sale-hero.jpg"},"position":{"description":"Where the image goes: main, random, or a placement hint of up to 500 characters.","type":"string","example":"main"},"altText":{"description":"Alternative text for the image, up to 1000 characters.","type":"string","example":"Spring sale banner"}},"type":"object"},"maxItems":7},"templateContent":{"description":"Not sent by the caller: the server resolves it from hash during validation, as the decoded stock template content.","type":"object","readOnly":true}},"type":"object"},"CreateCampaignFromTemplateRequest":{"description":"Which of the account's templates to start the campaign from and what the model should change in it.","required":["templateId","userPrompt"],"properties":{"templateId":{"description":"Id of the template to start from. It must be an Email Designer template the user may use, with no images embedded as data URIs, and convertible by the editing pipeline; otherwise 422.","type":"integer","example":1234},"userPrompt":{"description":"What the model should change in the template's content, 5 to 5000 characters.","type":"string","example":"Turn this into a spring sale announcement for our garden furniture range, 20% off until Sunday."},"sessionId":{"description":"Id of the conversation the request belongs to; passed through to the model calls for tracing. Optional.","type":["string","null"],"example":"sess_01HZX4K9Q2M7"},"source":{"description":"Where the campaign is created from, recorded on the campaign: web for the app, ai for the campaign generation agent.","type":"string","enum":["web","ai"],"example":"ai"},"brandkitUuid":{"description":"UUID of the brand kit whose logo the job applies to the campaign. Omitted, the account's primary brand kit is used.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"templateRecord":{"description":"Not sent by the caller: the server resolves it from templateId during validation.","type":"object","readOnly":true},"brandkitRecord":{"description":"Not sent by the caller: the server resolves it from brandkitUuid during validation.","type":"object","readOnly":true},"images":{"description":"Up to 7 images for the model to place in the campaign. Each names the image by URL and says where it goes: main for the hero image, random to let the model choose, or a short free-text placement hint. Omitted, the template's own images stay.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"Address of the image, http or https, up to 2048 characters.","type":"string","format":"uri","example":"https://cdn.example.com/spring-sale-hero.jpg"},"position":{"description":"Where the image goes: main, random, or a placement hint of up to 500 characters.","type":"string","example":"main"},"altText":{"description":"Alternative text for the image, up to 1000 characters.","type":"string","example":"Spring sale banner"}},"type":"object"},"maxItems":7}},"type":"object"},"CreateConversionSummaryRequest":{"description":"Which goal and conversion to summarize, and how. Every field is a JSON number or string of the type shown; a value of another JSON type answers 422 with Unexpected type.","required":["goalId","conversionId"],"properties":{"intervalDays":{"description":"How many days back the analysis covers, 1 to 30. The current interval is compared with the interval of the same length before it. Also passed to the queued generation request.","type":["integer","null"],"maximum":30,"minimum":1,"example":7},"expirationHours":{"description":"How many hours a finished summary stays valid, 1 to 168. A stored summary finished more recently than this is returned as is; an older one is replaced by a new generation.","type":["integer","null"],"maximum":168,"minimum":1,"example":24},"tone":{"description":"Tone of voice for the generated text. Only used when a new generation is queued.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"goalId":{"description":"ID of the business goal (initiative). Must exist on the account.","type":["integer","null"],"example":2228},"conversionId":{"description":"ID of the conversion whose performance is summarized. Must exist on the account.","type":["integer","null"],"example":23}},"type":"object"},"CreateInitiativeRequest":{"description":"A new business goal and the conversion to link to it, optionally with a target.","required":["label","color","description","conversionId"],"properties":{"label":{"description":"Name of the business goal. Must not be blank and must not match the name of an existing goal or folder (a label in the API).","type":"string","example":"Grow the newsletter list"},"color":{"description":"Color of the goal's folder, as a hex code without the leading #.","type":"string","example":"edf0f7"},"description":{"description":"What the goal is for. Required, but may be an empty string.","type":"string","example":"Reach 10,000 subscribers by the end of the year."},"conversionId":{"description":"Id of an existing conversion to link to the new goal. Required: a request without it, or with an id that matches no conversion, is a 422.","type":["integer","null"],"example":7},"targetEndDate":{"description":"Date the goal should be reached by, such as 2026-12-31. Applied only when useTargetEndDate is 1. Must not be blank when given.","type":["string","null"],"example":"2026-12-31"},"useTargetEndDate":{"description":"1 to give the goal a target end date, 0 or omitted for none. Sent as a number, not a boolean.","type":["integer","null"],"enum":[0,1],"example":1},"goalType":{"description":"What the conversion target measures: 1 for the total number of conversions, 2 for total revenue. Used only with conversionId.","type":["integer","null"],"enum":[1,2],"example":1},"goalValue":{"description":"The target the conversion should reach, for the goalType. Used only with conversionId.","type":["integer","null"],"example":100}},"type":"object"},"CreateRecommendationRequest":{"description":"What to recommend an asset for. Send initiativeId or templateHash, not both: when both are sent, selection starts for the goal, but templateHash is still validated and its stored recommendation can be the one answered.","required":["assetType"],"properties":{"initiativeId":{"description":"ID of a business goal that is not archived. A numeric string is accepted too.","type":"integer","example":123},"templateHash":{"description":"Hash of a goal recipe template, to get a recommendation for the template instead of a business goal.","type":["string","null"],"example":"3KP9Mla"},"assetType":{"description":"Kind of asset to recommend.","type":"string","enum":["automation","campaign"],"example":"automation"}},"type":"object"},"CreateRequest":{"description":"Which sent campaign to follow up on and what the followup email should say.","required":["campaignId","prompt"],"properties":{"campaignId":{"description":"Id of the sent campaign to follow up on, as a string. Must name a campaign of the account; it also names the new automation.","type":"string","example":"4821"},"prompt":{"description":"What the followup email should say, in the sender's words.","type":"string","example":"Thank readers who clicked the autumn sale link and offer them free shipping this week"},"tone":{"description":"Voice of the generated email: encouraging, persuasive, thoughtful, personal, witty, funny, empathetic, informative, professional, friendly, casual, enthusiastic or bold. Any other value falls back to encouraging.","type":"string","example":"friendly"},"outputLang":{"description":"Language the email is written in. Omitted, the calling user's language is used.","type":["string","null"],"example":"en"},"brandkitUuid":{"description":"UUID of the brand kit to style the email with; omitted, none is applied. Passed to the generation step as given, where an unknown UUID is refused, so here it fails the dispatch with 500.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"CreateSummaryRequest":{"description":"Options for generating the initiatives performance summary. Every field is optional.","properties":{"interval_days":{"description":"How many days of initiative performance the summary analyses. Between 1 and 30.","type":["integer","null"],"maximum":30,"minimum":1,"example":7},"expiration_hours":{"description":"How many hours an existing summary stays current. A summary younger than this is returned as it is instead of generating a new one. Between 1 and 168.","type":["integer","null"],"maximum":168,"minimum":1,"example":24},"tone":{"description":"Tone of voice of the generated summary.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"}},"type":"object"},"CreateSyncJobRequest":{"description":"A new database sync. The same fields as an update, except that `password` is required: a new sync has no stored password to fall back on. It may be an empty string.","required":["password","name","listId","fields","host","database","username"],"allOf":[{"$ref":"#/components/schemas/SaveSyncJobRequest"}]},"CreditsResponse":{"type":"object","properties":{"smsCredits":{"type":"object","properties":{"period":{"type":"string","example":"month"},"nextRefillDate":{"type":"string","example":"2026-02-26 15:06:25"},"includedThisPeriod":{"type":"integer","example":1000},"usedThisPeriod":{"type":"integer","example":71},"extra":{"type":"integer","example":9040},"available":{"type":"integer","example":9969}}}}},"CurrencyResource":{"description":"A currency the app can show amounts in. Every currency in GET /currencies has `id`, `label`, `symbol`, `position` and `sticky`, and `decimals` when it differs from the default; GET /currencies/{id} with a code that is not in the list returns only `id`.","required":["id"],"properties":{"id":{"description":"Lowercase three-letter ISO 4217 code. It is also the `id` GET /currencies/{id} takes.","type":"string","example":"usd"},"label":{"description":"Name of the currency, translated into the user's language","type":"string","example":"US Dollar"},"symbol":{"description":"Symbol shown with an amount in this currency","type":"string","example":"$"},"position":{"description":"Where the symbol goes: `f` before the amount, `b` after it. An empty string is shown before the amount, like `f`.","type":"string","enum":["f","b",""],"example":"f"},"sticky":{"description":"True for the currencies that currency pickers list first: the US dollar and the euro","type":"boolean","example":true},"decimals":{"description":"Number of decimal places an amount in this currency is shown with. Left out when it is the default, 2; only the Chilean peso (`clp`, 0) carries it.","type":"integer","example":0}},"type":"object"},"CustomerAccountActivity":{"type":"object","description":"One activity from the account's feed in the activity feed service, with the records it refers to filled in. Properties other than the four record references are passed through from that service as it stores them.","properties":{"feed":{"type":"string","description":"URN of the feed the activity belongs to","example":"urn:ac-hosted:customer-account:12345/19"},"eventKey":{"type":"string","description":"Key of the activity in the feed; pass it as `after` to read the activities that follow it","example":"1423580695-OHXnUakk"},"action":{"type":"string","description":"What happened","example":"updated"},"category":{"type":"string","description":"Category of the activity, the value the `category` filter matches","example":"task"},"published":{"type":"string","description":"When the activity happened, ISO 8601 in UTC","example":"2015-02-10T15:04:55Z"},"accountId":{"type":"string","description":"ID of the ActiveCampaign account (tenant) the feed belongs to","example":"12345"},"actor":{"$ref":"#/components/schemas/CustomerAccountActivityEntity"},"object":{"$ref":"#/components/schemas/CustomerAccountActivityEntity"},"origin":{"$ref":"#/components/schemas/CustomerAccountActivityEntity"},"target":{"$ref":"#/components/schemas/CustomerAccountActivityEntity"},"summary":{"type":"string","description":"Readable summary of the activity","example":"Task was completed for contact 23"},"context":{"type":["object","array"],"description":"Additional context the feed stores with the activity; an empty array when there is none"}}},"CustomerAccountActivityEntity":{"type":"object","description":"A record an activity refers to, as the activity feed service stores it (`urn`, `id`, `type`) merged with the record's current details that Hosted resolves for its type: for example `firstName`, `lastName` and `username` for a user; `firstName`, `lastName` and `email` for a contact; `title` and `typeTitle` for a task. Which detail properties appear depends on `type`.","properties":{"urn":{"type":"string","description":"URN of the record in the activity feed","example":"urn:ac-hosted:user:12345/2"},"id":{"type":"string","description":"ID of the record","example":"2"},"type":{"type":"string","description":"Kind of record. Hosted resolves details for contact, customer-account, deal, deal-email, link, subscriber-email, task and user.","example":"user"}}},"DeadLetterQueueDeleteResponse":{"description":"The outcome of the call, whether it succeeded or not: refusals and SQS failures also answer 200, with success false and the reason in errors.","required":["success","messages_processed","messages_deleted","messages","errors","dry_run","dead_letter_queue_url"],"properties":{"success":{"description":"True when errors is empty. False when the queue was refused, the dead letter queue could not be found, SQS failed, or at least one message could not be deleted.","type":"boolean","example":true},"messages_processed":{"description":"Messages received from the dead letter queue and looked at, deleted or not. 0 when the call stopped before reading the queue.","type":"integer","example":2},"messages_deleted":{"description":"Messages deleted. Always 0 on a dry run.","type":"integer","example":2},"messages":{"description":"On a dry run, the messages that a real run would delete. Empty on a real run.","type":"array","items":{"$ref":"#/components/schemas/DeadLetterQueueMessage"}},"errors":{"description":"What went wrong, one sentence each: \"Failed to delete messages: <cause>\" (or \"Failed to retrieve messages: <cause>\" on a dry run) when the call stopped early, for example because the queue is not one of the allowed ones or has no redrive policy; \"Messsage failed with id <MessageId>: <cause>\" per message SQS refused to delete.","type":"array","items":{"type":"string"},"example":[]},"dry_run":{"description":"The isDryRun the call ran with.","type":"boolean","example":false},"dead_letter_queue_url":{"description":"URL of the dead letter queue read from the source queue's redrive policy. Empty when the call stopped before resolving it.","type":"string","example":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives-dlq"}},"type":"object"},"DeadLetterQueueError":{"description":"One error in a DeadLetterQueueErrorResponse.","required":["status","title","detail"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":500},"title":{"description":"The translated name of the HTTP status, so its exact text depends on the account's language.","type":"string","example":"Internal Server Error"},"detail":{"description":"A fixed prefix followed by the cause.","type":"string","example":"Failed to delete messages: Connection reset by peer"}},"type":"object"},"DeadLetterQueueErrorResponse":{"description":"Error body when the call failed outside the service, which handles its own SQS errors. Rare: the service reports its failures in the 200 body instead.","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"$ref":"#/components/schemas/DeadLetterQueueError"}}},"type":"object"},"DeadLetterQueueMessage":{"description":"One message as SQS returned it from the dead letter queue, passed through unchanged. SQS can add further fields (MD5OfBody, Attributes, MD5OfMessageAttributes).","required":["MessageId","ReceiptHandle","Body"],"properties":{"MessageId":{"description":"SQS message id; the value to send as messageId to act on this message alone.","type":"string","example":"e5f6a7b8-1234-4c3d-9e8f-0a1b2c3d4e5f"},"ReceiptHandle":{"description":"Receipt handle of this receive. It belongs to the dry run that returned it and cannot be used to delete the message through this API.","type":"string","example":"AQEB7xk2..."},"Body":{"description":"The message body as the producer sent it, usually a JSON document.","type":"string","example":"{\"accountId\":1234,\"goalId\":2228,\"conversionId\":23}"},"MessageAttributes":{"description":"SQS message attributes, keyed by name, each with DataType and StringValue (or BinaryValue). Left out when the message has none.","type":"object","example":{"endpoint":{"DataType":"String","StringValue":"api/3/ai/initiatives/recipes/prepopulate"}},"additionalProperties":{"type":"object"}}},"type":"object","additionalProperties":true},"DeadLetterQueueRedriveResponse":{"description":"The outcome of the call, whether it succeeded or not: SQS failures and a queue without a redrive policy also answer 200, with success false and the reason in errors.","required":["success","messages_processed","messages_redriven","errors","dry_run"],"properties":{"success":{"description":"True when errors is empty. False when the dead letter queue could not be found, SQS failed, or at least one message could not be sent back.","type":"boolean","example":true},"messages_processed":{"description":"Messages received from the dead letter queue and looked at, redriven or not. 0 when the call stopped before reading the queue.","type":"integer","example":2},"messages_redriven":{"description":"Messages sent back to the source queue and removed from the dead letter queue. On a dry run, the messages that a real run would redrive: nothing is sent or removed.","type":"integer","example":2},"errors":{"description":"What went wrong, one sentence each: \"Failed to redrive dead letter queue: <cause>\" when the call stopped early, for example because the queue has no redrive policy or SQS failed; \"Failed to redrive message <MessageId>: <cause>\" per message that could not be sent back or removed.","type":"array","items":{"type":"string"},"example":[]},"dry_run":{"description":"The isDryRun the call ran with.","type":"boolean","example":false}},"type":"object"},"DeadLetterQueueValidationError":{"description":"One field of the request body that failed validation.","required":["status","title","detail","source"],"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed: \"This value should not be blank.\" or \"This value is not a valid URL.\" for sourceQueueUrl, \"maxReceiveCount must be between 1 and 100.\", or \"Unexpected type\" when a field has the wrong JSON type.","type":"string","example":"This value should not be blank."},"source":{"description":"The field that failed.","required":["pointer"],"properties":{"pointer":{"description":"The field, as /data/attributes/<field name>.","type":"string","example":"/data/attributes/sourceQueueUrl"}},"type":"object"}},"type":"object"},"DeadLetterQueueValidationErrorResponse":{"description":"Error body for a request body that fails validation.","required":["errors"],"properties":{"errors":{"description":"One error per failed check. A field can appear more than once if it fails several checks, for example a maxReceiveCount sent with the wrong type and a blank sourceQueueUrl are each reported. A blank sourceQueueUrl fails only the not-blank check; the URL check skips empty values.","type":"array","items":{"$ref":"#/components/schemas/DeadLetterQueueValidationError"}}},"type":"object"},"DealConnection":{"description":"A mailbox a user connected through Nylas so its emails sync to deals and contacts and deal emails can be sent from it. Read from the database, numeric columns are numeric strings.","properties":{"id":{"description":"ID of the connection","type":["string","integer"],"example":"3"},"userid":{"description":"ID of the user the mailbox belongs to","type":["string","integer"],"example":"1"},"email":{"description":"Address of the connected mailbox","type":"string","example":"jane@example.com"},"accountid":{"description":"Nylas API v2 account ID of the mailbox; empty for a mailbox connected through Nylas API v3","type":"string","example":""},"provider":{"description":"Sync service the mailbox is connected through: nylas for every connection made today, contextio or null on old rows","type":["string","null"],"example":"nylas"},"type":{"description":"Email provider of the mailbox as Nylas names it, for example google, microsoft, imap, icloud or yahoo (gmail on older connections)","type":["string","null"],"example":"google"},"version":{"description":"Not written by current code; empty on connections made through Nylas API v3","type":"string","example":""},"status":{"description":"Sync state, for example running while Nylas syncs the mailbox and invalid once its Nylas grant was deleted or expired","type":"string","example":"running"},"privacy":{"description":"Copied onto every email synced from the mailbox: 1 shows those emails only to the mailbox owner, 0 to every user","type":["string","integer"],"example":"0"},"cdate":{"description":"When the mailbox was connected, ISO 8601 with offset; null when unknown","type":["string","null"],"example":"2026-05-04T10:12:30-05:00"},"sentiment_enabled":{"description":"1 when the sentiment of emails synced from the mailbox is shown, 0 when it is hidden","type":["string","integer"],"example":"1"},"preferred_email":{"description":"1 on the mailbox the user sends deal emails from, 0 on the user's other mailboxes; null until a preferred mailbox was chosen","type":["string","integer","null"],"example":"1"},"has_send_scope":{"description":"1 when the Nylas connection may send email, 0 when it may only read","type":["string","integer"],"example":"1"},"sync_option":{"description":"Which emails are synced: 0 every email, 1 only emails with the primary contacts of open deals","type":["string","integer"],"example":"0"},"last_synced":{"description":"When emails were last synced from the mailbox, Y-m-d H:i:s as stored (not converted to ISO 8601); null before the first sync","type":["string","null"],"example":"2026-10-14 08:00:00"},"api_version":{"description":"Nylas API version the mailbox is connected through: 2 or 3","type":"string","example":"3"},"grant_id":{"description":"Nylas API v3 grant of the mailbox; null for a mailbox still on Nylas API v2","type":["string","null"],"example":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41"},"links":{"description":"Always empty: a connection has no related resources","type":"array","items":{"type":"string"},"example":[]}},"type":"object"},"DealCustomFieldMetaBulkError":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":["integer","string"],"description":"HTTP status. A string when the user lacks pg_deal_fields, a number otherwise."},"title":{"type":"string","description":"Name of the status. Not sent when the user lacks pg_deal_fields."},"detail":{"type":"string","description":"Forbidden, when the user lacks pg_deal_fields."}}}}}},"DealCustomFieldMetaBulkServiceError":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"The service's message."},"detail":{"type":"string","description":"Always an empty string."},"code":{"type":"integer","description":"Always 422."},"source":{"type":"object","properties":{"pointer":{"type":"string","description":"The service's pointer, with /data/attributes in front."}}}}}}}},"DealCustomFieldMetaBulkUpdateItem":{"type":"object","description":"One field to update. Its keys are sent to the service in snake_case, and nested values are sent as they are. Keys whose value is null are dropped.","required":["id"],"properties":{"id":{"type":["integer","string"],"description":"Id of the field to update."},"fieldLabel":{"type":"string","description":"Name of the field."},"fieldOptions":{"type":["array","object"],"description":"Options for the field, for dropdown, multiselect, radio and checkbox fields."},"fieldDefault":{"type":"string","description":"Default value of the field."},"isFormVisible":{"type":["integer","boolean"],"description":"Whether the field shows on forms."},"isRequired":{"type":["integer","boolean"],"description":"Whether the field is required."},"displayOrder":{"type":"integer","description":"Order of the field on the Manage Fields page and on deals."},"personalization":{"type":"string","description":"Personalization tag of the field. Hosted sends it as given."}}},"DealStageErrorResponse":{"type":"object","description":"Why the request was refused","properties":{"errors":{"type":"array","description":"One entry","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"The reason, as a translated message","example":"You do not have permission to delete stages"}}}}}},"DealStageJobQueued":{"type":"object","description":"Confirms that the background job was queued","properties":{"meta":{"type":"object","description":"Request status","properties":{"success":{"type":"boolean","description":"Always true","example":true}}}}},"DealStageOrderRequest":{"type":"object","description":"The stages in their new order","required":["ids"],"properties":{"ids":{"type":"array","description":"Stage IDs in the new order. The first gets `order` 1, the second 2, and so on.","items":{"type":["integer","string"]},"example":["3","1","2"]}}},"DealStageOrderResult":{"type":"object","description":"The reordered stages","properties":{"dealStages":{"type":"array","description":"The stages from `ids`, in that order","items":{"$ref":"#/components/schemas/DealStageOrderedStage"}}}},"DealStageOrderedStage":{"type":"object","description":"A deal stage as stored, after its new order was saved. Unlike GET /dealStages/{id}, card region and deal order values come back as stored, without converting older stored values.","properties":{"id":{"type":"string","description":"ID of the stage","example":"3"},"group":{"type":["string","null"],"description":"ID of the pipeline the stage belongs to","example":"1"},"title":{"type":"string","description":"Name of the stage","example":"Qualified"},"color":{"type":"string","description":"Column color, as six hex digits without #","example":"3f3f3f"},"order":{"type":"integer","description":"The stage's new position in its pipeline, counting from 1","example":1},"width":{"type":"string","description":"Column width in pixels","example":"280"},"dealOrder":{"type":"string","description":"How deals are sorted in the column: a sort field and direction","example":"next-action DESC"},"cardRegion1":{"type":"string","description":"What the first region of a deal card shows","example":"title"},"cardRegion2":{"type":"string","description":"What the second region of a deal card shows","example":"next-action"},"cardRegion3":{"type":"string","description":"Whether a deal card shows the avatar: show-avatar or hide-avatar","example":"show-avatar"},"cardRegion4":{"type":"string","description":"What the fourth region of a deal card shows","example":"contact-fullname-acctname"},"cardRegion5":{"type":"string","description":"What the fifth region of a deal card shows. A region set to win_probability reads hide when the account does not have win probability.","example":"value"},"cdate":{"type":["string","null"],"description":"When the stage was created, in ISO 8601","example":"2026-01-20T09:27:32-06:00"},"udate":{"type":["string","null"],"description":"When the stage was last updated, in ISO 8601","example":"2026-03-02T11:41:01-06:00"},"links":{"type":"object","description":"URLs of the stage's related reads","properties":{"group":{"type":"string","description":"URL that returns the stage's pipeline","example":"https://:account.api-us1.com/api/3/dealStages/3/group"}}}}},"DealTasktypesBulkUpsertEntry":{"type":"object","description":"One task type to keep, change or create","properties":{"id":{"type":["integer","string"],"description":"ID of an existing task type to keep and update. Leave it out to create a task type.","example":"1"},"title":{"type":"string","description":"Title of the task type. Required when `id` is left out, and unique within the request. Empty keeps the current title.","example":"Call"},"display_order":{"type":["integer","string"],"description":"Position of the task type in the list. Left out keeps the current position.","example":1},"status":{"type":["integer","string"],"description":"0 for active, 1 for disabled. Left out keeps the current status.","enum":[0,1,"0","1"],"example":0},"taskTypeIdToMigrateTasks":{"type":["integer","string"],"description":"Only with `status` 1: ID of an active task type to move this task type's open tasks to. Completed tasks stay.","example":"1"},"outcomes":{"type":"array","description":"The task type's outcomes, 1 to 100 of them. Required while the task outcomes setting is on; ignored while it is off.","items":{"type":"object","required":["id"],"properties":{"id":{"type":["integer","string"],"description":"ID of an enabled outcome","example":1},"display_order":{"type":["integer","string"],"description":"Position of the outcome within the task type. Left out reads as 0.","example":1}}}}}},"DealTasktypesBulkUpsertErrors":{"type":"object","description":"Why the request was refused","properties":{"errors":{"type":"array","description":"One entry per problem found","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 422","example":422},"title":{"type":"string","description":"What is wrong, in English","example":"At least one dealTasktype is required."}}}}}},"DealTasktypesBulkUpsertRequest":{"type":"object","description":"The complete list of task types the account should have","required":["dealTasktypes"],"properties":{"dealTasktypes":{"type":"array","minItems":1,"description":"Every task type to keep or create. Existing task types left out are deleted.","items":{"$ref":"#/components/schemas/DealTasktypesBulkUpsertEntry"}}}},"DealTasktypesBulkUpsertResult":{"type":"object","description":"The first page of the account's task types after the save","properties":{"dealTasktypes":{"type":"array","description":"Up to 20 task types, ordered by `display_order` and then `title`","items":{"$ref":"#/components/schemas/DealTasktypesListedTaskType"}},"meta":{"type":"object","description":"List metadata","properties":{"total":{"type":"integer","description":"Number of task types the account has","example":3}}}}},"DealTasktypesErrorResponse":{"type":"object","description":"Why the request was refused","properties":{"errors":{"type":"array","description":"One entry","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"The reason","example":"Forbidden"}}}}}},"DealTasktypesListedTaskType":{"description":"A task type with its outcomes","allOf":[{"$ref":"#/components/schemas/DealTasktypesTaskType"},{"type":"object","properties":{"outcomes":{"type":"array","description":"The task type's enabled outcomes, ordered by `display_order`. Returned whether or not the task outcomes setting is on.","items":{"$ref":"#/components/schemas/DealTasktypesOutcomeLink"}}}}]},"DealTasktypesOutcomeLink":{"type":"object","description":"An enabled outcome linked to a task type","properties":{"id":{"type":"string","description":"ID of the outcome","example":"1"},"display_order":{"type":"string","description":"Position of the outcome within the task type","example":"1"}}},"DealTasktypesPatchFields":{"type":"object","description":"The task type fields to change. Fields left out keep their current value.","properties":{"title":{"type":"string","description":"Title of the task type. Must not be used by another task type.","example":"Meet in person"},"status":{"type":["integer","string"],"description":"0 for active, 1 for disabled","enum":[0,1,"0","1"],"example":1},"defduration":{"type":["integer","string"],"description":"Whole number stored on the task type and returned as given","example":0}}},"DealTasktypesTaskType":{"type":"object","description":"A task type as stored","properties":{"id":{"type":"string","description":"ID of the task type","example":"7"},"title":{"type":"string","description":"Title of the task type. The four task types every account starts with are returned translated into the user's language.","example":"Meet in person"},"status":{"type":["string","integer"],"description":"0 for active, 1 for disabled. A value just written is echoed as sent.","example":"1"},"defduration":{"type":["string","integer"],"description":"Whole number stored on the task type","example":"0"},"display_order":{"type":["string","integer"],"description":"Position of the task type in the list","example":"1"},"cdate":{"type":["string","null"],"description":"When the task type was created, in ISO 8601; null for the four task types every account starts with","example":"2026-03-02T14:28:53-06:00"},"udate":{"type":["string","null"],"description":"When the task type was last saved, in ISO 8601; null when it never was","example":"2026-03-02T14:32:20-06:00"},"created_utc_timestamp":{"type":"string","description":"When the row was created, in ISO 8601","example":"2026-03-02T20:28:53-06:00"},"updated_utc_timestamp":{"type":"string","description":"When the row was last changed, in ISO 8601","example":"2026-03-02T20:32:20-06:00"},"created_by":{"type":["string","null"],"description":"ID of the user who created the task type","example":"1"},"updated_by":{"type":["string","null"],"description":"ID of the user who last changed the task type","example":"1"},"links":{"type":"object","description":"URLs of the task type's related reads","properties":{"dealTasks":{"type":"string","description":"URL that returns the task type's tasks","example":"https://:account.api-us1.com/api/3/dealTasktypes/7/dealTasks"},"tasktypeOutcomeRels":{"type":"string","description":"URL that returns the task type's outcome links","example":"https://:account.api-us1.com/api/3/dealTasktypes/7/tasktypeOutcomeRels"}}}}},"DealTasktypesValidationErrors":{"type":"object","description":"The fields that failed validation","properties":{"errors":{"type":"array","description":"One entry per failed check","items":{"type":"object","properties":{"title":{"type":"string","description":"What is wrong, as a translated message","example":"The task type already exists in the system."},"detail":{"type":"string","description":"More detail; empty for these checks","example":""},"code":{"type":"string","description":"Kind of failure: field_missing or duplicate","example":"duplicate"},"error":{"type":"string","description":"Machine-readable form of the failure","example":"dealTasktype_already_exists_in_the_system"},"source":{"type":"object","description":"Where the failure is","properties":{"pointer":{"type":"string","description":"The failing field","example":"/data/attributes/title"}}}}}}}},"DeleteDispatchRequest":{"description":"Queue payload for a delete that has to wait for a running generation. CampaignGenerationService::deleteRequestOrDispatch builds it.","required":["request_id"],"properties":{"request_id":{"description":"UUID of the generation request to delete.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"DeleteMessagesRequest":{"description":"Which dead letter queue to clean and how much of it. Send each field with the JSON type shown, or leave it out; a field sent as JSON null makes the call fail with a generic 500.","required":["sourceQueueUrl"],"properties":{"sourceQueueUrl":{"description":"URL of the source SQS queue whose dead letter queue is cleaned; the dead letter queue is read from its redrive policy. Must be one of the three Generative Marketing queues Hosted is configured with (initiatives, performance summaries, recommendations); any other URL is refused with success false. Must be a syntactically valid URL to pass validation.","type":["string","null"],"example":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives"},"maxReceiveCount":{"description":"Most messages to take from the dead letter queue, 1 to 100. Defaults to 10. Messages are received in batches of up to 10 with a one-second wait each, so fewer can come back than asked for.","type":["integer","null"],"maximum":100,"minimum":1,"example":10},"messageId":{"description":"Only act on the message with this SQS MessageId. The call keeps receiving batches from the dead letter queue until it finds this message or the queue returns no more messages; maxReceiveCount does not limit that scan. Every other message it received is left in place but stays invisible for the queue's visibility timeout.","type":["string","null"],"example":"e5f6a7b8-1234-4c3d-9e8f-0a1b2c3d4e5f"},"isDryRun":{"description":"When true, return the matching messages instead of deleting them, so the call can be previewed. Defaults to false.","type":["boolean","null"],"example":true}},"type":"object"},"DesignIrDocument":{"description":"The design IR stored for a campaign or one of its split messages, with the revision that identifies this exact document.","required":["ir","revision"],"properties":{"ir":{"description":"The design IR exactly as it was stored: an opaque JSON document owned by the generation engine. Hosted never inspects its shape, so it is a JSON object or array.","example":{"root":{"type":"container","blocks":[{"type":"text","text":"Hello"}]}},"oneOf":[{"type":"object"},{"type":"array","items":{}}]},"revision":{"description":"Content hash of the stored document; it changes on every real edit. Send it back as expectedRevision on the next PUT to make that write conditional.","type":"string","example":"0f1d2c3b4a5e4f609b7c8d9e0f1a2b3c"}},"type":"object"},"DesignIrUnverifiedWrite":{"description":"The write committed but could not be read back, so the caller must record the design IR as unverified rather than as stored.","required":["verified","reason"],"properties":{"verified":{"description":"Always false: a verified write answers 204 with no body instead.","type":"boolean","example":false},"reason":{"description":"Why the write is unverified. read_back_absent: the read-back query ran and matched no row. read_back_failed: the read-back query itself failed.","type":"string","enum":["read_back_absent","read_back_failed"],"example":"read_back_absent"}},"type":"object"},"DeterministicTemplateImportCompletedResponse":{"description":"The import finished and the template is saved.","required":["status","result","createdAt","completedAt"],"properties":{"status":{"description":"Always completed.","type":"string","enum":["completed"],"example":"completed"},"result":{"oneOf":[{"$ref":"#/components/schemas/DeterministicTemplateImportResult","description":"The imported template; null for a record written without it."},{"type":"null"}],"description":"The imported template; null for a record written without it."},"createdAt":{"description":"When the request was created, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:02:11"},"completedAt":{"description":"When the import finished, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:02:19"}},"type":"object"},"DeterministicTemplateImportFailedResponse":{"description":"The job failed. The status code says how: 504 when a model call timed out, 413 when content was too large for it, 500 otherwise.","required":["status","error","errorCode","createdAt","failedAt"],"properties":{"status":{"description":"Always failed.","type":"string","enum":["failed"],"example":"failed"},"error":{"description":"Always this fixed sentence; the underlying error is logged, never answered.","type":"string","enum":["Processing failed."],"example":"Processing failed."},"errorCode":{"description":"Why a model call failed, when that is known: timeout (answered 504) or content_too_large (answered 413). The conversion itself uses no model; these come from regenerating empty images. null for any other failure, answered 500.","type":["string","null"],"enum":["timeout","content_too_large",null],"example":null},"createdAt":{"description":"When the request was created, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:02:11"},"failedAt":{"description":"When the job failed, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:02:19"}},"type":"object"},"DeterministicTemplateImportProcessRequest":{"description":"The job POST /ai/template/import-deterministic/create queues: which stored import request to run.","required":["requestId","rawHtml","templateName"],"properties":{"requestId":{"description":"ID of the request record the create call stored; must name a stored request of this import kind.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"rawHtml":{"description":"The HTML as sent to the create call. Carried in the job for tracing; the worker reads the copy stored on the request record.","type":"string","example":"<html><body><table width=\"600\">...</table></body></html>"},"templateName":{"description":"The template name as sent to the create call. Carried in the job; the worker reads the stored copy.","type":"string","example":"Spring newsletter"}},"type":"object"},"DeterministicTemplateImportResult":{"description":"The imported template.","required":["stripoCompatibleHtml","templateName","conversionMethod","templateId"],"properties":{"stripoCompatibleHtml":{"description":"The Stripo-compatible HTML built from the parsed structure, with empty images regenerated for the primary brand kit; also the html of the saved template's content.","type":"string","example":"<table class=\"es-content\">...</table>"},"templateName":{"description":"Name of the saved template, as sent when the request was created.","type":"string","example":"Spring newsletter"},"conversionMethod":{"description":"Always deterministic: no model wrote the markup.","type":"string","enum":["deterministic"],"example":"deterministic"},"templateId":{"description":"ID of the template saved to the account (editor version 3, source deterministic_template_import, hidden when the request asked for it).","type":"integer","example":4821}},"type":"object"},"Disclosure":{"description":"One gap between what a sub-agent was asked for and what it delivered.\n\n``text`` is written for the reader and is meant to be relayed verbatim; the\nnumeric and field members carry the same fact in machine-readable form.","properties":{"kind":{"$ref":"#/components/schemas/DisclosureKind"},"text":{"title":"Text","type":"string"},"shown":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Shown"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Total"},"field":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Field"}},"required":["kind","text"],"title":"Disclosure","type":"object"},"DisclosureKind":{"description":"Why a delivered result differs from the request it answered.","enum":["truncated","capped_source","substituted","defaulted","not_persisted","not_applied","unconfirmed"],"title":"DisclosureKind","type":"string"},"DiscoverFieldsRequest":{"description":"The source connection, and the table or custom query whose columns to list. Either `table` or `query` must be given; with both, `table` wins.","required":["host","database","username"],"type":"object","allOf":[{"$ref":"#/components/schemas/SourceConnectionRequest"},{"properties":{"table":{"description":"Table whose columns to list. It must be one of the tables POST /syncs/connection lists. Leave it empty to read the columns of `query` instead.","type":"string","example":"customers"},"query":{"description":"Custom SELECT query whose columns to list, used when `table` is empty. It is run with its LIMIT replaced by `LIMIT 0, 1`, and must return at least one row.","type":"string","example":"SELECT email, first_name FROM customers WHERE active = 1"}},"type":"object"}]},"DynamicDataBlockProcessingResponse":{"description":"Acknowledgement of one step of an AI content automation block: whether the step ran, completed the block, or skipped it. The step always restarts the automation itself, so the answer carries no result data.","required":["message"],"properties":{"message":{"description":"What the step did. \"Dynamic data block processing\" when process handed the generation to the Bedrock pipeline; \"Dynamic data block processed\" when finish wrote the content to the field or generate dispatched the finish step; \"Dynamic data block processed but skipped\" when the step failed and the block was skipped, with the reason recorded in the automation history.","type":"string","enum":["Dynamic data block processing","Dynamic data block processed","Dynamic data block processed but skipped"],"example":"Dynamic data block processed"}},"type":"object"},"DynamicDataGenerateRequest":{"description":"Callback payload of the temporary in-Hosted generation step of an AI content automation block: the personalized prompt the AWS dynamic data processing system hands back for Hosted to run against the model.","required":["subscriberSeriesId","blockId","personalizedContent","processStartTime"],"properties":{"subscriberSeriesId":{"description":"Id of the contact's entry in the automation (the contact automation record) waiting at the block.","type":"integer","example":91337},"blockId":{"description":"Id of the automation block to generate content for. Must name an existing block of type aidynamicdata.","type":"integer","example":4821},"personalizedContent":{"description":"The block's prompt with the contact's values filled into every personalization tag, at most 3000 characters.","type":"string","example":"Write a one-line greeting for Ada who works at Acme"},"personalizedTool":{"description":"Input of the block's tool (for example the text for sentiment_analyzer) with the contact's values filled in, keyed by input name; every value is a string. Empty when the block uses no tool.","type":"object","example":{"text":"The onboarding call was great, thank you!"},"additionalProperties":{"type":"string"}},"processStartTime":{"description":"Unix time with microseconds at which the block started processing the contact, carried through to report the processing time of the whole run.","type":"number","format":"double","example":1760000000.123456},"block":{"description":"Ignored on input: the server loads the block named by blockId into it.","type":"object","readOnly":true},"contactSeries":{"description":"Ignored on input: the server loads the contact automation record named by subscriberSeriesId into it.","type":"object","readOnly":true}},"type":"object"},"DynamicDataPreview":{"description":"One generated preview: the contact the prompt was personalized for and the text the model wrote.","required":["contact","generatedContent"],"properties":{"contact":{"$ref":"#/components/schemas/DynamicDataPreviewContact","description":"The contact picked from the preview record for this preview."},"generatedContent":{"description":"The text the model generated from the prompt with the contact's values filled in, as it would be written to a text field.","type":"string","example":"Hi Ada, thanks for choosing Acme."}},"type":"object"},"DynamicDataPreviewContact":{"description":"The contact a preview was generated for, with the values that were filled into the prompt.","required":["contactId","personalizedTags","used"],"properties":{"contactId":{"description":"Id of the contact whose values were filled into the prompt.","type":"integer","example":1042},"personalizedTags":{"description":"Each personalization tag found in the prompt, with the value this contact has for it. Serialized as an empty list when the contact entry holds no tags.","type":"object","example":{"%FIRSTNAME%":"Ada","%COMPANY%":"Acme"},"additionalProperties":{"type":"string"}},"used":{"description":"True once a preview has been generated for this contact; each contact of a record is used once, and the record is replaced when none is left.","type":"boolean","example":true}},"type":"object"},"DynamicDataPreviewErrorResponse":{"description":"Why no preview could be generated for the prompt.","required":["type"],"properties":{"type":{"description":"\"general\" when no contact in the account has a value for every personalization tag in the prompt; \"guardrail_violation\" when the model's guardrail blocked the generation for the picked contact.","type":"string","enum":["general","guardrail_violation"],"example":"general"}},"type":"object"},"DynamicDataPreviewRequestIdResponse":{"description":"The preview record started for a prompt: the id to generate previews under.","required":["requestId"],"properties":{"requestId":{"description":"External identifier of the preview record, the md5 of the personalization tags found in the prompt. Pass it as requestId to POST /ai/dynamic-data/preview/{requestId}; a prompt with the same tags answers the same id while the record is fresh.","type":"string","example":"9e107d9d372bb6826bd81d3542a419d6"}},"type":"object"},"DynamicDataPreviewResponse":{"description":"A generated preview of an AI content block's prompt for one sample contact.","required":["preview"],"properties":{"preview":{"$ref":"#/components/schemas/DynamicDataPreview","description":"The preview: the sample contact and the generated text."}},"type":"object"},"DynamicPreviewContact":{"description":"One contact the prompt can be previewed on, with the prompt's personalization tags filled in from that contact.","required":["contactId","personalizedTags"],"properties":{"contactId":{"description":"ID of the contact.","type":"integer","example":17},"personalizedTags":{"description":"Each personalization tag found in the prompt, keyed as written there, with the value it renders to for this contact (the contact's most recent deal supplies deal tags).","type":"object","example":{"%FIRSTNAME%":"Ada","%DEAL_TITLE%":"Spring renewal"},"additionalProperties":{"type":"string"}}},"type":"object"},"DynamicPreviewContactsResponse":{"description":"Contacts to preview the prompt on, each with its tags rendered.","required":["contacts"],"properties":{"contacts":{"description":"At most maxContacts contacts. Matched contacts when the prompt's tags gave the preview segment conditions, random contacts of the account otherwise; empty when none could be personalized.","type":"array","items":{"$ref":"#/components/schemas/DynamicPreviewContact"}}},"type":"object"},"DynamicPreviewSearchRequest":{"description":"The text to preview and how many personalization tags it may use.","required":["prompt"],"properties":{"prompt":{"description":"The message text to preview, carrying 1 to maxTags personalization tags such as %FIRSTNAME%.","type":"string","example":"Hi %FIRSTNAME%, your %DEAL_TITLE% renewal is coming up"},"maxTags":{"description":"The most personalization tags the prompt may carry; more than this, or none, is a 422.","type":"integer","example":3}},"type":"object"},"DynamicPreviewStartedResponse":{"description":"A preview record exists for the prompt and, when it has conditions, the contact match is running.","required":["recordId"],"properties":{"recordId":{"description":"ID of the preview record; pass it to GET /ai/dynamic/preview/{recordId}. A prompt already previewed answers the existing record's ID as long as its segment still exists.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"EcomDataSyncCustomer":{"description":"One store customer to create or update, with the orders to create or update for them. The customer is looked up on the connection by `email`, then `externalid`, then `phone` (phone only when the account has phone-only contacts). When none matches, the customer is created, and a contact is created for them unless one with that email or phone already exists.","properties":{"externalid":{"description":"The customer's ID in the store. Every customer needs `externalid` or `connectionid`.","type":"string","example":"56789"},"connectionid":{"description":"Accepted in place of `externalid` to pass validation, but not used: the customer is saved on the connection named in `ecomData`.","type":"integer","example":1},"email":{"description":"The customer's email address. Required, unless the account has phone-only contacts; then `email` or `phone` is required.","type":"string","example":"alice@example.com"},"phone":{"description":"The customer's phone number. It is normalised before it is matched and saved.","type":"string","example":"+15555550123"},"first_name":{"description":"First name, given to the contact when this sync creates it","type":"string","example":"Alice"},"last_name":{"description":"Last name, given to the contact when this sync creates it","type":"string","example":"Smith"},"accepts_marketing":{"description":"Whether the customer accepts marketing: a true value is stored as 1, and a false value, or leaving it out, as 0. When true, the contact is also subscribed to the connection's list, or made active on it again; a false value does not unsubscribe them.","type":["boolean","integer"],"example":true},"sms_marketing_state":{"description":"The customer's SMS marketing state, stored as the store reports it","type":"string"},"sms_opt_in_level":{"description":"The customer's SMS opt-in level, stored as the store reports it","type":"string"},"sms_consent_updated_at":{"description":"When the customer's SMS consent last changed, as the store reports it","type":"string"},"customer_tags":{"description":"Tags the store gives the customer, as a list or as one comma-separated string. For a Shopify store they are added to the contact as tags when this sync creates the contact.","example":["vip","wholesale"],"oneOf":[{"type":"array","items":{"type":"string"}},{"type":"string"}]},"total_revenue":{"description":"Total revenue of the customer, in cents. A new customer starts at 0 when it is left out.","type":"integer","example":45678},"total_orders":{"description":"Number of orders of the customer. A new customer starts at 0 when it is left out.","type":"integer","example":3},"total_products":{"description":"Number of products the customer ordered. A new customer starts at 0 when it is left out.","type":"integer","example":5},"avg_revenue_per_order":{"description":"Average revenue per order, in cents. A new customer starts at 0 when it is left out.","type":"integer","example":15226},"orders":{"description":"Orders to create or update for the customer, each wrapped as `{\"ecomOrder\": {...}}`. An order is matched on the connection by its `externalid` or `externalcheckoutid`, and its products are replaced by the ones sent.","type":"array","items":{"required":["ecomOrder"],"properties":{"ecomOrder":{"description":"The order, with the fields of `ecomOrder` in POST /ecomOrders (their API names or the snake_case column names), except `connectionid` and `customerid`, which come from the connection and the customer. It is validated as in POST /ecomOrders: `externalid` (or `externalcheckoutid`), `totalPrice`, `currency`, `externalCreatedDate` and a valid `state` are required.","required":["orderProducts"],"properties":{"externalid":{"description":"The order's ID in the store","type":"string","example":"3000"},"externalcheckoutid":{"description":"The cart's ID in the store, for an abandoned cart","type":"string","example":"7000"},"orderProducts":{"description":"The products of the order, with the fields of `orderProducts` in POST /ecomOrders. Required, even when empty: the total product count is the sum of their `quantity`.","type":"array","items":{"type":"object","additionalProperties":true}},"orderDiscounts":{"description":"The discounts of the order, with the fields of `orderDiscounts` in POST /ecomOrders","type":"array","items":{"type":"object","additionalProperties":true}}},"type":"object","additionalProperties":true}},"type":"object"}}},"type":"object"},"EditAutomationInput":{"additionalProperties":false,"properties":{"prompt":{"description":"The change to make, in the user's own words.","maxLength":20000,"minLength":1,"title":"Prompt","type":"string"},"idempotency_key":{"anyOf":[{"maxLength":200,"minLength":1,"type":"string"},{"type":"null"}],"default":null,"description":"Names one request: the same key returns the same run instead of building twice. Reuse a key only for a run reported lost.","title":"Idempotency Key"},"language":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Language for the automation's emails, only when the user names one outright.","examples":["English","Spanish"],"title":"Language"},"automation_id":{"description":"Id of the automation to change. Find it first when the user names the automation only by name.","examples":[12],"exclusiveMinimum":0,"title":"Automation Id","type":"integer"}},"required":["prompt","automation_id"],"title":"EditAutomationInput","type":"object"},"EditByCampaignIdAccepted":{"description":"The edit was queued. The id to poll it by.","required":["requestId"],"properties":{"requestId":{"description":"Id of the generation record the edit runs under. Poll GET /ai/campaign/generation/poll/{requestId} with it until the record leaves in_progress.","type":"string","example":"0c7a4ad5-7a0e-4a4e-9a2e-8d6f5a1c2b3d"}},"type":"object"},"EditByCampaignIdRequest":{"description":"What to change on the campaign named in the path: a brand kit, a template, summarized external content, a free-text edit prompt, block configurations or images. At least one of those must differ from what the campaign already has, or the request is refused with 422.","properties":{"campaignId":{"description":"Ignored: the campaign is taken from the campaignId path segment, not from the body.","type":"integer","example":123},"brandkitUuid":{"description":"UUID of the brand kit to apply to the campaign. It must name one of the account's stored brand kits. Omitted or null, no brand kit change is made.","type":["string","null"],"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"},"brandkitRecord":{"description":"Not sent by the caller: the server resolves the brand kit record named by brandkitUuid into it while validating.","type":"object","readOnly":true},"summarizationUuid":{"description":"UUID of a finished content summarization whose material the edit draws on. It must name a stored summarization; one still processing or in error is refused with 422.","type":["string","null"],"example":"0b1f6a3c-2d4e-4f50-8a9b-1c2d3e4f5a6b"},"summarizationRecord":{"description":"Not sent by the caller: the server resolves the summarization record named by summarizationUuid into it while validating.","type":"object","readOnly":true},"useSummarizationLink":{"description":"True to link to the summarized content from the campaign. Defaults to false.","type":["boolean","null"],"example":false},"template":{"description":"Name of the template to re-render the campaign with. Omitted or null, the template stays as it is.","type":["string","null"],"example":"promote"},"editPrompt":{"description":"Free-text instruction for the model, 5 to 5000 characters. Personalization tags in it must be valid.","type":["string","null"],"example":"Make the headline shorter and mention the spring sale."},"contentChange":{"description":"Whether the edit may change the body content. Defaults to true.","type":"boolean","example":true},"subjectChange":{"description":"Whether the edit may change the subject line. Defaults to false.","type":"boolean","example":false},"preheaderChange":{"description":"Whether the edit may change the preheader. Defaults to false.","type":"boolean","example":false},"nameChange":{"description":"Whether the edit may change the campaign name. Defaults to false.","type":"boolean","example":false},"labelId":{"description":"Id of the campaign folder (label) to file the campaign under. It must exist.","type":["integer","null"],"example":7},"sessionId":{"description":"Client session id passed along to the queued update for tracing.","type":["string","null"],"example":"sess_01HZY3K9Q"},"blocks":{"description":"Block configurations to apply, each with a type and its config map. Any non-empty list counts as a change.","type":"array","items":{"required":["type","config"],"properties":{"type":{"description":"The block type.","type":"string","example":"text"},"config":{"description":"Settings for the block, keyed by setting name.","type":"object","example":{"value":"Hello"}}},"type":"object"},"example":[{"type":"text","config":{"value":"Hello"}}]},"images":{"description":"Images to place in the campaign, at most 7. Each needs an http or https url of at most 2048 characters and a position of at most 500 characters; altText is optional and at most 1000 characters. Any non-empty list counts as a change.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"Where the image is served from; http or https.","type":"string","example":"https://example.com/hero.jpg"},"position":{"description":"Where in the campaign the image goes, as the model understands it.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image.","type":["string","null"],"example":"Spring collection"}},"type":"object"},"example":[{"url":"https://example.com/hero.jpg","position":"hero","altText":"Spring collection"}]}},"type":"object"},"EditDispatchRequest":{"description":"Queue payload for running an AI edit. CampaignEditsService::dispatchEdits builds it from the body of POST /ai/campaigns/edit/{requestId}/initialize; the server resolves the stored request, brand kit, summarization, campaign, message and markup from the ids.","required":["request_id"],"properties":{"request_id":{"description":"UUID of the edit request. Must name a stored edit request that is past classification and not in error.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"record":{"description":"The stored edit request. Resolved by the server from request_id; not part of the payload.","type":"object","readOnly":true},"emailEditRequest":{"description":"The edit request decoded from the stored record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"brandkit_id":{"description":"UUID of the brand kit to style with, or null for none.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"brandkitRecord":{"description":"The stored brand kit. Resolved by the server from brandkit_id; not part of the payload.","type":"object","readOnly":true},"summarization_id":{"description":"UUID of the finished content summarization to draw the copy from, or null for none.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"summarizationRecord":{"description":"The stored summarization record. Resolved by the server from summarization_id; not part of the payload.","type":"object","readOnly":true},"summarization":{"description":"The summarization decoded from its record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"use_summarization_link":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"edit_prompt":{"description":"Free-text instruction for the model, applied to every text block.","type":["string","null"],"example":"Make it shorter and more upbeat"},"subject":{"description":"New subject line, kept as given. Null lets the model rewrite the current one.","type":["string","null"],"example":"Your October picks are here"},"preheader":{"description":"New preheader text, kept as given. Null lets the model rewrite the current one.","type":["string","null"],"example":"New arrivals, member offers and more"},"images":{"description":"Images to place in the email, at most 7, each with its URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}},"campaign":{"description":"The campaign under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"message":{"description":"The message under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"messageMarkup":{"description":"The editor markup of the message. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"EditRequest":{"description":"What to change in the email. At least one of a new brandkitUuid, a new summarizationUuid, an editPrompt or images must be given, or the request is refused with 400.","properties":{"brandkitUuid":{"description":"UUID of a brand kit of the account to style the email with. Counts as a change only when it differs from the one stored on the request.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of a finished content summarization of the account to draw the copy from. Counts as a change only when it differs from the one stored on the request. Refused with 409 while the summarization is in progress and 500 when it errored.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"summarizationKVStore":{"description":"The stored summarization record. Resolved by the server from summarizationUuid; not part of the payload.","type":"object","readOnly":true},"summarization":{"description":"The summarization decoded from its record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"useSummarizationLink":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"editPrompt":{"description":"Free-text instruction for the model, applied to every text block.","type":["string","null"],"example":"Make it shorter and more upbeat"},"subject":{"description":"New subject line. Omitted, the model may rewrite the current one.","type":["string","null"],"example":"Your October picks are here"},"preheader":{"description":"New preheader text. Omitted, the model may rewrite the current one.","type":["string","null"],"example":"New arrivals, member offers and more"},"images":{"description":"Images to place in the email, at most 7, each with its URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}}},"type":"object"},"EmailAccountsEmailAccount":{"description":"A Subscriptions by Email account as the API returns it: a POP3 mailbox or a piped address whose incoming mail subscribes or unsubscribes the sender to the account's lists. The password and the detected POP3 login method are never returned. Values read from the database are strings; a create or update response returns the numbers it computed as integers.","properties":{"id":{"description":"ID of the email account","type":["string","integer"],"example":"3"},"userid":{"description":"ID of the user who created the email account. Set from the calling user on create; an update does not change it.","type":["string","integer"],"example":"1"},"action":{"description":"What a message received at the address does to its sender: sub subscribes the sender to the lists, unsub unsubscribes them","type":"string","enum":["sub","unsub"],"example":"sub"},"type":{"description":"How mail reaches the account: pop3 is a mailbox read over POP3 with host, port, user and password; pipe is an address whose mail is forwarded to one of the account's parser addresses (GET /emailAccounts/parserAddresses)","type":"string","enum":["pop3","pipe"],"example":"pop3"},"email":{"description":"The address subscribers write to; the parser matches incoming mail to email accounts by its To: address.","type":"string","example":"join@example.com"},"host":{"description":"POP3 server host name; empty for a pipe account","type":"string","example":"pop.example.com"},"port":{"description":"POP3 server port; 110 for a pipe account","type":["string","integer"],"example":"110"},"user":{"description":"POP3 login user name; empty for a pipe account","type":"string","example":"join@example.com"},"emailsPerBatch":{"description":"Number of messages taken from the mailbox in one batch, as stored; 120 for a pipe account","type":["string","integer"],"example":"120"},"filterUse":{"description":"Whether only messages that pass the filter (filterField, filterCond, filterVal) are acted on: 1 yes, 0 every message","type":["string","integer"],"example":"0"},"filterField":{"description":"Which part of the message the filter tests","type":"string","enum":["subject","body"],"example":"subject"},"filterCond":{"description":"How the filter compares filterVal with filterField, ignoring case: contains, notcontains or equals","type":"string","example":"contains"},"filterVal":{"description":"The text the filter compares against; empty when no filter is set","type":"string","example":"subscribe"},"emailAccountList":{"description":"IDs of the account's list associations, the emailAccountLists records linking it to its lists. Only in create and update responses, and in GET /emailAccounts with include=emailAccountList.","type":"array","items":{"type":["string","integer"]},"example":["7","8"]},"links":{"description":"URLs of the related reads","properties":{"emailAccountList":{"description":"URL that returns the account's list associations, GET /emailAccounts/{id}/emailAccountList","type":"string","example":"https://:account.api-us1.com/api/3/emailAccounts/3/emailAccountList"}},"type":"object"}},"type":"object"},"EmailAccountsListAssociation":{"description":"One link between an email account and a list it subscribes or unsubscribes contacts to (an emailAccountLists record)","properties":{"id":{"description":"ID of the association","type":["string","integer"],"example":"7"},"emailAccount":{"description":"ID of the email account","type":["string","integer","null"],"example":"3"},"list":{"description":"ID of the list","type":["string","integer","null"],"example":"1"},"created_timestamp":{"description":"When the association was created, ISO 8601 with offset","type":["string","null"],"example":"2026-10-15T09:12:45-05:00"},"updated_timestamp":{"description":"When the association was last changed, ISO 8601 with offset","type":["string","null"],"example":"2026-10-15T09:12:45-05:00"},"created_by":{"description":"ID of the user who created the association, when recorded","type":["string","integer","null"],"example":null},"updated_by":{"description":"ID of the user who last changed the association, when recorded","type":["string","integer","null"],"example":null},"links":{"description":"URLs of the related reads","properties":{"emailAccount":{"description":"URL that returns the email account","type":"string","example":"https://:account.api-us1.com/api/3/emailAccountLists/7/emailAccount"},"list":{"description":"URL that returns the list","type":"string","example":"https://:account.api-us1.com/api/3/emailAccountLists/7/list"}},"type":"object"}},"type":"object"},"EmailAccountsSavedResponse":{"description":"An email account after a create or update, with its list associations side-loaded","required":["emailAccount","emailAccountLists"],"properties":{"emailAccountLists":{"description":"The account's list associations as saved, read back from the database","type":"array","items":{"$ref":"#/components/schemas/EmailAccountsListAssociation"}},"emailAccount":{"$ref":"#/components/schemas/EmailAccountsEmailAccount","description":"The email account as saved, with emailAccountList holding the IDs of its associations"}},"type":"object"},"EmailAccountsWriteFields":{"description":"The email account to save. On create, a field left out takes the default below; on update it keeps its current value, except lists and pass, which are read from every request. The setting fields are also accepted under their database column names (emails_per_batch, filteruse, filterfield, filtercond, filterval); any other key is ignored.","required":["lists"],"properties":{"lists":{"description":"IDs of the lists the account subscribes or unsubscribes senders to. Required on every create and update and must name at least one list: the account's associations are replaced by these. On update, associations with lists the calling user cannot see are kept.","type":"array","items":{"type":"integer"},"example":[1,2]},"email":{"description":"The address subscribers write to; must be a valid email address. Required on create.","type":"string","example":"join@example.com"},"type":{"description":"pop3 (the default) reads a mailbox over POP3; pipe takes mail forwarded to a parser address and clears host, user and pass. Any other value is saved as pop3.","type":"string","enum":["pop3","pipe"],"example":"pop3"},"action":{"description":"sub (the default) subscribes senders to the lists; unsub unsubscribes them. Any other value is saved as sub.","type":"string","enum":["sub","unsub"],"example":"sub"},"host":{"description":"POP3 server host name. Required, non-blank, for a pop3 account.","type":"string","example":"pop.example.com"},"port":{"description":"POP3 server port; 0 or left out means 110","type":"integer","example":110},"user":{"description":"POP3 login user name. Required, non-blank, for a pop3 account.","type":"string","example":"join@example.com"},"pass":{"description":"POP3 password. Write-only: never returned. For a pop3 account the server logs in with it on every create and update before saving, and stores it encrypted in place of the previous one, so an update must send it again.","type":"string","example":"secret"},"emailsPerBatch":{"description":"Number of messages taken from the mailbox in one batch; saved as an integer (0 when left out on create). A pipe account always gets 120.","type":"integer","example":120},"filterUse":{"description":"Whether only messages that pass the filter are acted on: a non-zero integer (or true) saves 1, anything else 0","type":"integer","enum":[0,1],"example":0},"filterField":{"description":"Which part of the message the filter tests; any value other than body is saved as subject","type":"string","enum":["subject","body"],"example":"subject"},"filterCond":{"description":"How the filter compares; any other value is saved as contains","type":"string","enum":["contains","notcontains","equals"],"example":"contains"},"filterVal":{"description":"The text the filter compares against","type":"string","example":"subscribe"}},"type":"object"},"EmailAccountsWriteRequest":{"description":"Body of a create or update of an email account","required":["emailAccount"],"properties":{"emailAccount":{"$ref":"#/components/schemas/EmailAccountsWriteFields","description":"The email account. Left out, the request has no lists and is refused with 422."}},"type":"object"},"EmailItemProgress":{"properties":{"block_id":{"title":"Block Id","type":"integer"},"state":{"title":"State","type":"string"},"campaign_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Campaign Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"}},"required":["block_id","state"],"title":"EmailItemProgress","type":"object"},"EmailsProgress":{"description":"What a poller sees of a run's emails, folded from its stream.","properties":{"state":{"title":"State","type":"string"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Total"},"done":{"default":0,"title":"Done","type":"integer"},"failed":{"default":0,"title":"Failed","type":"integer"},"items":{"default":[],"items":{"$ref":"#/components/schemas/EmailItemProgress"},"title":"Items","type":"array"}},"required":["state"],"title":"EmailsProgress","type":"object"},"EmberGlobalData":{"description":"Everything the Ember app reads at start-up about the account, the signed-in user, branding and connections, in one document. It is large: on big accounts it can run to megabytes.","required":["acct","admin","branding","connections","global","user","userJson","tplShareHost","regions","cell_name","nrx_tracking_enabled"],"properties":{"acct":{"description":"Account settings, plan, entitlement and usage values: the tracking account ID, suspension state, number of active status messages not yet clicked or closed, site name and serial, date and time formats, geo-IP country code, plus-field availability, deal, customer account, ecommerce and contact personalization tags, the CCPA terms configuration, whether a new export is ready, a billing provisioning token, one has*/is*/can* flag per plan feature, plan tier and term, seat, user, contact (`sub*`) and email sending (`mail*`) limits and counts, language, currency and account age flags. An empty array when gathering it fails; the failure is logged.","oneOf":[{"type":"object","additionalProperties":true},{"type":"array","items":{},"maxItems":0}]},"admin":{"description":"The signed-in user's record merged with the permissions, limits and branding of the user's groups, plus `locale` (the locale of the user's language). `password` and `apikey` are removed.","type":"object","additionalProperties":true},"branding":{"description":"The account's branding, personalized for the app, plus `has_header`, `has_footer`, `content_pre`, `content_body` and `content_post`. Social app credentials are removed from its `site` block, and logo and favicon URLs on the legacy CDN host are rewritten to the current one.","type":"object","additionalProperties":true},"connections":{"description":"The account's integration connections in JSON API form: an object whose `connections` key holds one record per connection. An empty array when the account has none.","oneOf":[{"properties":{"connections":{"description":"One record per connection.","type":"array","items":{"type":"object","additionalProperties":true}}},"type":"object"},{"type":"array","items":{},"maxItems":0}]},"global":{"$ref":"#/components/schemas/EmberGlobalDataGlobal","description":"Session and environment values the app needs before anything else."},"user":{"$ref":"#/components/schemas/EmberGlobalDataUser","description":"The signed-in user."},"userJson":{"description":"The signed-in user in JSON API form: the user under `user`, and one array per related resource already loaded on the user, keyed by its plural name (`userGroups`, `groups`, `configs`). When the automations read-only feature is on, every group carries `pgAutomationRead` (`\"1\"` or `\"0\"`).","type":"object","additionalProperties":true},"tplShareHost":{"description":"Host name of the template sharing service.","type":"string","example":"tplshare.com"},"regions":{"$ref":"#/components/schemas/EmberGlobalDataRegions","description":"The data regions, and which one serves this account."},"cell_name":{"description":"Name of the cell that serves the account. Empty when unknown.","type":"string","example":"product-aws-use1-p-1"},"nrx_tracking_enabled":{"description":"Whether NRX reporting tracking is on for the account: set by the NRX report migration feature flag, or, when that flag is undecided, by the account's NRX tracking state and the React campaign reporting launch flags.","type":"boolean","example":false}},"type":"object"},"EmberGlobalDataGlobal":{"description":"Session and environment values the Ember app needs before anything else.","required":["_hosted_developer","__ws_topic_prefix","ac_arc_login","ac_rs_login","cdn_link","facebookFormIntegrationAppUrl","has_billing","layerAppUuid","mfa_enforced","ac_user_id","ssoEnabled"],"properties":{"_hosted_developer":{"description":"Developer-mode marker: false unless the runtime defines the `_hosted_developer` global, which the application code does not.","type":"boolean","example":false},"__ws_topic_prefix":{"description":"Prefix of the account's private websocket topics.","type":"string","example":"private-abc123-"},"ac_arc_login":{"description":"True when the session is an ARC impersonation login.","type":"boolean","example":false},"ac_rs_login":{"description":"True when the session is a reseller impersonation login.","type":"boolean","example":false},"cdn_link":{"description":"Base URL of the static asset CDN, ending in a slash. Empty when it cannot be built.","type":"string","example":"https://active-cdn.app-us1.com/"},"facebookFormIntegrationAppUrl":{"description":"URL of the Facebook app the Facebook form integration uses, from the `FACEBOOK_APP_URL` environment variable. Empty when it is not set.","type":"string","example":""},"has_billing":{"description":"True when the user is in the account's main admin group and the account is not managed by a reseller, so billing pages apply.","type":"boolean","example":true},"layerAppUuid":{"description":"Value of the `LAYER_APP_UUID` environment variable. Empty when it is not set.","type":"string","example":""},"mfa_enforced":{"description":"True when the account requires multi-factor authentication for every user.","type":"boolean","example":false},"ac_user_id":{"description":"ID of the signed-in user, as a string.","type":"string","example":"1"},"ssoEnabled":{"description":"Stored value of the `authentication.sso.enabled` setting, as a string. Empty when the setting does not exist.","type":"string","example":""}},"type":"object"},"EmberGlobalDataRegion":{"description":"One data region.","required":["currentRegion"],"properties":{"currentRegion":{"description":"True when this region serves the account, judged from the first two letters of the service's AWS region.","type":"boolean","example":true}},"type":"object"},"EmberGlobalDataRegions":{"description":"The data regions. At most one is the current region; none is when the service has no region configured.","required":["us","eu"],"properties":{"us":{"$ref":"#/components/schemas/EmberGlobalDataRegion","description":"The United States region."},"eu":{"$ref":"#/components/schemas/EmberGlobalDataRegion","description":"The European Union region."}},"type":"object"},"EmberGlobalDataUser":{"description":"The signed-in user: the user record limited to a fixed set of fields (`id`, `absid`, `parentid`, `approved`, `username`, `first_name`, `last_name`, `email`, `phone`, `signature`, `last_login`, `lang`, `default_deals`, the `t_offset*` time zone offsets, the `*_per_page` paging preferences, `htmleditor`, `editorsize_w`, `editorsize_h`, `local_zoneid`, `local_dst`, `autoupdate`, `autosave`, `sdate`, `ldate`, `ltime`, `password_updated_utc_timestamp`, the `notify_*` settings, `cdate`, `udate` and `mfa_enabled`; never the password or API key), plus the properties listed here.","required":["main_admin_group","main_admin","email_hash"],"properties":{"main_admin_group":{"description":"True when the user is in the account's main admin group.","type":"boolean","example":true},"main_admin":{"description":"True when the user is the account's primary admin (user ID 1).","type":"boolean","example":true},"email_hash":{"description":"MD5 hash of the user's email address.","type":"string","example":"d41d8cd98f00b204e9800998ecf8427e"}},"type":"object","additionalProperties":true},"EmlExtractedHtmlResponse":{"description":"The HTML part of the uploaded email.","required":["html"],"properties":{"html":{"description":"The email's HTML body, with inline (cid:) images rewritten to hosted URLs so the markup renders outside the mail client.","type":"string","example":"<html><body><table width=\"600\">...</table></body></html>"}},"type":"object"},"EmlExtractionErrorResponse":{"description":"Error body with a single message.","required":["error"],"properties":{"error":{"description":"Why the file was refused or could not be read. One of the fixed messages the operation lists.","type":"string","example":"Invalid file extension. Only .eml files are allowed"}},"type":"object"},"EnableReadTrackingBulkFailure":{"type":"object","description":"The required array is missing or empty.","properties":{"errors":{"type":"string","description":"The error text. It is a single string, not a list."}}},"EnableReadTrackingContactEmail":{"type":"object","description":"A contact email record as created: the fields sent, plus `userid`, `ip`, `sdate` and `id`, with each relationship key repeated under its relationship name (`message`, `contact`, `deal`, `user`; `customer_acct_id` is returned as `account`) and `links` to the related resources.","properties":{"id":{"type":["string","integer"],"description":"ID of the contact email record.","example":17},"messageid":{"type":["string","integer"],"description":"ID of the message that was emailed.","example":"42"},"subscriberid":{"type":["string","integer"],"description":"ID of the contact the message was emailed to.","example":"8"},"userid":{"type":["string","integer"],"description":"ID of the user making the request.","example":"1"},"ip":{"type":"string","description":"IPv4 address of the request, as an unsigned integer.","example":"3232235777"},"sdate":{"type":"string","description":"When the request was handled, ISO 8601.","example":"2026-10-01T10:05:00-05:00"},"links":{"type":"object","description":"URLs of the related resources, keyed by relationship name.","additionalProperties":{"type":"string"}}}},"EnableReadTrackingLink":{"type":"object","description":"A tracked link record as created: the fields sent plus `id`, the click counters, each relationship key repeated under its relationship name (`campaign`, `message`) and `links` to the related resources.","properties":{"id":{"type":["string","integer"],"description":"ID of the link record.","example":31},"messageid":{"type":["string","integer"],"description":"ID of the message the link belongs to.","example":"42"},"campaignid":{"type":["string","integer"],"description":"ID of the campaign the link belongs to; 0 for an email that is not part of a campaign.","example":"0"},"link":{"type":["string","null"],"description":"The tracked URL, or `open` for the open-tracking link.","example":"open"},"name":{"type":["string","null"],"description":"Display name of the link.","example":"Read tracker"},"uniquelinkclicks":{"type":["string","integer"],"description":"Number of distinct contacts who clicked the link.","example":"0"},"linkclicks":{"type":["string","integer"],"description":"Total clicks on the link.","example":"0"},"links":{"type":"object","description":"URLs of the related resources, keyed by relationship name.","additionalProperties":{"type":"string"}}}},"EnableReadTrackingLinkData":{"type":"object","description":"A link data (open or click) record in the standard v3 form: every column of the record, `tstamp` and `updated_timestamp` in ISO 8601, each relationship key repeated under its relationship name (`link`, `contact`, `campaign`, `message`) and `links` to the related resources.","properties":{"id":{"type":["string","integer"],"description":"ID of the link data record.","example":"90"},"linkid":{"type":["string","integer"],"description":"ID of the link the record belongs to.","example":31},"messageid":{"type":["string","integer"],"description":"ID of the message the record belongs to.","example":"42"},"subscriberid":{"type":["string","integer"],"description":"ID of the contact who opened or clicked.","example":"8"},"isread":{"type":["string","integer"],"description":"1 for an open, 0 for a click.","example":"1"},"referer":{"type":["string","null"],"description":"Referrer of the open or click, as plain text.","example":"https://mail.google.com/"},"tstamp":{"type":["string","null"],"description":"When the open or click happened, ISO 8601.","example":"2026-10-01T10:05:00-05:00"},"links":{"type":"object","description":"URLs of the related resources, keyed by relationship name.","additionalProperties":{"type":"string"}}}},"EnableReadTrackingMessage":{"type":"object","description":"A message in the standard v3 form: every column of the message record, dates in ISO 8601, `user` repeating `userid`, and `links` to the related resources.","properties":{"id":{"type":["string","integer"],"description":"ID of the message.","example":"42"},"userid":{"type":["string","integer"],"description":"ID of the user who owns the message.","example":"1"},"user":{"type":["string","integer","null"],"description":"Same as `userid`; null when it is 0.","example":"1"},"name":{"type":"string","description":"Internal name of the message.","example":"Following up"},"subject":{"type":["string","null"],"description":"Subject line.","example":"Following up"},"fromname":{"type":"string","description":"Sender name.","example":"Jane Doe"},"fromemail":{"type":"string","description":"Sender address.","example":"jane@example.com"},"format":{"type":"string","enum":["html","text","mime"],"description":"Body format.","example":"mime"},"html":{"type":["string","null"],"description":"HTML body."},"text":{"type":["string","null"],"description":"Plain-text body."},"cdate":{"type":["string","null"],"description":"When the message was created, ISO 8601.","example":"2026-10-01T10:00:00-05:00"},"mdate":{"type":["string","null"],"description":"When the message was last changed, ISO 8601.","example":"2026-10-01T10:05:00-05:00"},"links":{"type":"object","description":"URLs of the related resources, keyed by relationship name (`user`, `hyperlinks`, `campaignMessage`).","additionalProperties":{"type":"string"}}}},"EnableReadTrackingServerError":{"type":"object","description":"An unexpected failure.","properties":{"message":{"type":"string","description":"Generic error text.","example":"Something went wrong on our end. Please try again later"}}},"EnableReadTrackingWriteFailure":{"type":"object","description":"A write failed. Nothing the request wrote is kept.","properties":{"error":{"type":"string","description":"Fixed error text naming the step that failed.","example":"Error occurred while creating message, try again."}}},"EnrichError":{"description":"Why a web scrape, search or map request failed, and whether trying again can help.","required":["status","detail","category","retryable"],"properties":{"status":{"description":"The HTTP status of the response, as a string. A rejected scrape, search or map target keeps the status the web-scraping provider answered with when it was 400, 401, 403 or 404.","type":"string","example":"429"},"detail":{"description":"What went wrong, in words.","type":"string","example":"Rate limit exceeded"},"category":{"description":"What kind of failure it was, which decides the status and whether to retry: rate_limited (429), transient (502: the provider timed out, answered 5xx, could not be reached or reported success false), credits_exhausted (503), client_error (the provider's own 400, 401, 403 or 404), invalid_url (422: the target is not an allowed public HTTPS address, or its domain is blocked by policy) and decode_error (502: the provider's answer could not be read).","type":"string","enum":["rate_limited","transient","credits_exhausted","client_error","invalid_url","decode_error"],"example":"rate_limited"},"retryable":{"description":"True for rate_limited and transient failures, which can succeed if the same request is sent again.","type":"boolean","example":true},"retry_after":{"description":"Seconds to wait before retrying, from the provider. Present only when it sent one, and then also as the Retry-After header.","type":"integer","example":30},"upstream":{"description":"What the provider itself reported. Present only when it reported something.","properties":{"code":{"description":"The provider's error code.","type":"string","example":"SCRAPE_TIMEOUT"},"error":{"description":"The provider's error message.","type":"string","example":"Scrape timed out"}},"type":"object"}},"type":"object"},"EnrichErrorResponse":{"description":"Error body for a scrape, search or map request that the web-scraping provider or the pre-flight checks refused.","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"$ref":"#/components/schemas/EnrichError"}}},"type":"object"},"EnrichMapRequest":{"description":"A site whose URLs to discover.","required":["url"],"properties":{"url":{"description":"The site to map. It must be a public HTTPS address: anything else, a private network address or a domain blocked by policy is refused with 422.","type":["string","null"],"example":"https://example.com"},"search":{"description":"Only return URLs that match this text.","type":["string","null"],"example":"pricing"},"sitemap":{"description":"How the site's sitemap is used: include it with the links found on pages, skip it, or return only what it lists.","type":"string","default":"include","enum":["include","skip","only"],"example":"include"},"includeSubdomains":{"description":"Also return URLs on the site's subdomains.","type":["boolean","null"],"example":false},"limit":{"description":"How many URLs to return at most, from 1 to 5000.","type":"integer","default":100,"maximum":5000,"minimum":1,"example":100}},"type":"object"},"EnrichMapResponse":{"description":"The URLs discovered on a site.","required":["success","links"],"properties":{"success":{"description":"Whether the provider mapped the site.","type":"boolean","example":true},"links":{"description":"The URLs found, each as an object. A bare URL from the provider is wrapped as {url}.","type":"array","items":{"required":["url"],"properties":{"url":{"description":"The discovered URL.","type":"string","example":"https://example.com/pricing"},"title":{"description":"The page title, when the provider knew it.","type":"string","example":"Pricing"},"description":{"description":"The page description, when the provider knew it.","type":"string","example":"Plans and prices."}},"type":"object"},"example":[{"url":"https://example.com/pricing","title":"Pricing"}]}},"type":"object"},"EnrichScrapeRequest":{"description":"The page to scrape and what to return from it. Most options are passed to the web-scraping provider as they are, so its own documentation defines them.","required":["url"],"properties":{"url":{"description":"The page to scrape. It must be a public HTTPS address: anything else, a private network address or a domain blocked by policy is refused with 422.","type":["string","null"],"example":"https://example.com/pricing"},"formats":{"description":"What to return from the page, at least one. Asking for several returns all of them in data. json needs extractSchema, and changeTracking needs changeTrackingTag, or each is sent to the provider as a plain format name.","type":"array","items":{"type":"string","enum":["markdown","html","rawHtml","links","images","summary","screenshot","changeTracking","json","branding"]},"default":["markdown"],"example":["markdown","links"]},"actions":{"description":"Browser steps to run on the page before it is scraped, in order. Each has a type; its other fields are passed to the provider unchanged.","type":["array","null"],"items":{"required":["type"],"properties":{"type":{"description":"The kind of step.","type":"string","enum":["wait","click","write","press","scroll","screenshot","scrape","executeJavascript","pdf"]}},"type":"object","additionalProperties":true},"example":[{"type":"wait","milliseconds":1000}]},"onlyMainContent":{"description":"Return only the page's main content, without headers, navigation and footers. The provider decides when left out.","type":["boolean","null"],"example":true},"removeBase64Images":{"description":"Ask the provider to remove inline base64 images. Inline base64 data is always removed from the response either way.","type":["boolean","null"],"example":true},"timeout":{"description":"How long the provider may spend on the page, in milliseconds. The provider decides when left out.","type":["integer","null"],"example":30000},"waitFor":{"description":"Milliseconds to wait for the page to load before it is scraped.","type":["integer","null"],"example":1000},"maxAge":{"description":"Accept a copy of the page the provider cached up to this many milliseconds ago, instead of scraping again.","type":["integer","null"],"example":3600000},"changeTrackingTag":{"description":"Names the baseline the page is compared against. Used when formats includes changeTracking.","type":["string","null"],"example":"pricing-page"},"changeTrackingModes":{"description":"How the change is described, as the provider defines them. Used when formats includes changeTracking.","type":["array","null"],"items":{"type":"string"},"example":["git-diff"]},"changeTrackingSchema":{"description":"A JSON Schema for structured change output. Used when formats includes changeTracking.","type":["object","null"],"example":{"type":"object"},"additionalProperties":true},"changeTrackingPrompt":{"description":"Instructions for describing the change. Used when formats includes changeTracking.","type":["string","null"],"example":"Summarise what changed in the prices"},"extractSchema":{"description":"A JSON Schema the page is extracted into. Used when formats includes json.","type":["object","null"],"example":{"type":"object","properties":{"companyName":{"type":"string"}}},"additionalProperties":true},"extractPrompt":{"description":"Instructions for the extraction. Used when formats includes json.","type":["string","null"],"example":"Extract the company name"},"includeTags":{"description":"Keep only these HTML tags, classes or ids.","type":["array","null"],"items":{"type":"string"},"example":["article"]},"excludeTags":{"description":"Remove these HTML tags, classes or ids.","type":["array","null"],"items":{"type":"string"},"example":["nav","footer"]},"blockAds":{"description":"Block ads and cookie pop-ups while loading the page.","type":["boolean","null"],"example":true},"proxy":{"description":"Which kind of proxy the provider uses to load the page.","type":["string","null"],"default":"auto","enum":["basic","enhanced","auto"],"example":"auto"},"mobile":{"description":"Load the page as a mobile device would.","type":["boolean","null"],"example":false},"parsers":{"description":"File parsers the provider runs on non-HTML targets such as PDFs.","type":["array","null"],"items":{"type":"string"},"example":["pdf"]},"location":{"description":"Where the page is loaded from and in which languages, as the provider defines it.","type":["object","null"],"example":{"country":"US","languages":["en-US"]},"additionalProperties":true}},"type":"object"},"EnrichScrapeResponse":{"description":"What the page returned, in the formats asked for. Inline base64 data is replaced by \"[base64 content removed]\".","required":["success","data"],"properties":{"success":{"description":"Whether the provider scraped the page. This says the call worked, not that the page itself loaded: a missing or failing page is scraped too, so read data.metadata.statusCode for the page's own status.","type":"boolean","example":true},"data":{"description":"One key per format asked for: markdown, html, rawHtml, links, images, summary, screenshot, changeTracking, json or branding, plus metadata about the page such as title and statusCode. The shape of each depends on the format.","type":"object","example":{"markdown":"# Pricing","links":["https://example.com/signup"],"metadata":{"title":"Pricing","statusCode":200}},"additionalProperties":true}},"type":"object"},"EnrichSearchRequest":{"description":"A web search to run. Most options are passed to the web-scraping provider as they are, so its own documentation defines them. Results are always scraped with personal data redacted, and blocked domains are excluded unless includeDomains is set.","required":["query"],"properties":{"query":{"description":"What to search for, up to 500 characters.","type":["string","null"],"maxLength":500,"example":"Acme Corp headquarters"},"sources":{"description":"Which kinds of results to return. Each requested kind is returned under its own key in data.","type":"array","items":{"type":"string","enum":["web","news","images"]},"default":["web"],"example":["web","news"]},"tbs":{"description":"Restrict results by time, as the provider's tbs value, for example qdr:w for the past week.","type":["string","null"],"example":"qdr:w"},"limit":{"description":"How many results to return, from 1 to 100.","type":"integer","default":5,"maximum":100,"minimum":1,"example":5},"scrapeOptions":{"description":"Scrape each result as well, with these options. Known keys include formats and onlyMainContent; the rest is the provider's. Personal data redaction is always switched on.","type":["object","null"],"example":{"formats":["markdown"],"onlyMainContent":true},"additionalProperties":true},"categories":{"description":"Limit the search to these kinds of site.","type":["array","null"],"items":{"type":"string","enum":["github","research","pdf"]},"example":["research"]},"includeDomains":{"description":"Only return results from these domains, at most 50. Cannot be combined with excludeDomains, and a domain blocked by policy is refused with 422.","type":["array","null"],"items":{"type":"string"},"maxItems":50,"example":["example.com"]},"excludeDomains":{"description":"Leave out results from these domains, at most 50, on top of the domains blocked by policy. Cannot be combined with includeDomains.","type":["array","null"],"items":{"type":"string"},"maxItems":50,"example":["example.org"]},"location":{"description":"Where the search is run from, as free text.","type":["string","null"],"example":"Austin, Texas, United States"},"country":{"description":"Two-letter ISO country code to search in.","type":["string","null"],"maxLength":2,"minLength":2,"example":"US"},"lang":{"description":"Language of the results.","type":["string","null"],"example":"en"},"timeout":{"description":"How long the provider may spend, in milliseconds. A positive integer.","type":["integer","null"],"minimum":1,"example":60000},"ignoreInvalidURLs":{"description":"Leave out results whose URL the provider cannot scrape instead of failing.","type":["boolean","null"],"example":true}},"type":"object"},"EnrichSearchResponse":{"description":"The results of a web search. Inline base64 data is replaced by \"[base64 content removed]\".","required":["success","data"],"properties":{"success":{"description":"Whether the provider ran the search.","type":"boolean","example":true},"data":{"description":"Results under one key per source asked for: web (title, description, url and, when scraped, the page content), news (title, snippet, url, date) and images (title, imageUrl). With a single source the provider may return the list of results directly instead, so handle both shapes. When the provider returns no data at all, data is an empty list.","example":{"web":[{"title":"Acme Corp","description":"Acme makes anvils.","url":"https://example.com"}]},"oneOf":[{"type":"object","additionalProperties":true},{"type":"array","items":{"type":"object","additionalProperties":true}}]}},"type":"object"},"ErrorDetail":{"type":"object","properties":{"status":{"type":"string"},"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"}},"title":"ErrorDetail"},"ErrorDetail400":{"type":"object","properties":{"status":{"type":"string","example":"400 BAD_REQUEST"},"title":{"type":"string","example":"Segment 1ab85f0e-3b5c-4a35-bc07-242c68a7d000 is invalid"},"detail":{"type":"string"},"code":{"type":"string"}},"title":"ErrorDetail"},"ErrorDetail404":{"type":"object","properties":{"status":{"type":"string","example":"404 NOT_FOUND"},"title":{"type":"string","example":"Segment 1ab85f0e-3b5c-4a35-bc07-242c68a7d000 not found"},"detail":{"type":"string"},"code":{"type":"string"}},"title":"ErrorDetail"},"ErrorDetailDO":{"title":"ErrorDetailDO","type":"object","properties":{"code":{"type":"string"},"detail":{"type":"string"},"source":{"$ref":"#/components/schemas/ErrorSourceDO"},"status":{"type":"string"},"title":{"type":"string"}}},"ErrorResponse400RootDO":{"type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail400"}}},"title":"ErrorResponse400RootDO"},"ErrorResponse404RootDO":{"type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail404"}}},"title":"ErrorResponse404RootDO"},"ErrorResponseRootDO":{"type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail"}}},"title":"ErrorResponseRootDO"},"ErrorSourceDO":{"title":"ErrorSourceDO","type":"object","properties":{"pointer":{"type":"string"}}},"Exclusion":{"type":"object","description":"An exclusion rule as stored. Values are strings.","properties":{"email":{"type":["string","null"],"description":"The address or pattern the rule matches.","example":"sam@example.com"},"wildcard":{"type":"string","description":"Old flag, \"0\" or \"1\". New rules use matchtype instead.","example":"0"},"hidden":{"type":"string","description":"\"1\" when the rule was added because a contact reported a campaign as spam, else \"0\".","example":"0"},"matchtype":{"type":"string","enum":["exact","begin","end"],"description":"How email is matched: exact for the whole address, begin for addresses that start with it, end for addresses that end with it.","example":"exact"},"channel":{"type":"string","enum":["email","sms","all"],"description":"The channel the rule applies to: email, sms, or all for both.","example":"email"},"created_timestamp":{"type":["string","null"],"description":"When the rule was created, as \"YYYY-MM-DD HH:MM:SS\". Null when not set.","example":"2026-10-01 09:30:00"},"updated_timestamp":{"type":["string","null"],"description":"When the rule was last changed, as \"YYYY-MM-DD HH:MM:SS\". Null when not set.","example":"2026-10-01 09:30:00"},"links":{"type":"object","description":"URLs of the rule's related reads.","properties":{"exclusionLists":{"type":"string","description":"URL of GET /exclusions/{id}/exclusionLists.","example":"https://example.api-us1.com/api/3/exclusions/7/exclusionLists"}}},"id":{"type":"string","description":"ID of the rule.","example":"7"}}},"ExclusionBodyNotObjectError":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code.","example":400},"title":{"type":"string","description":"Short name of the error, in the user's language.","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body.","example":"Request body must be a JSON object, array given."}}}}}},"ExclusionCreate":{"type":"object","required":["email","matchtype","target"],"properties":{"email":{"type":"string","maxLength":250,"description":"The address or pattern to match, at most 250 bytes. With matchtype exact it must be a valid email address.","example":"sam@example.com"},"matchtype":{"type":"string","enum":["exact","begin","end"],"description":"How email is matched: exact for the whole address, begin for addresses that start with it, end for addresses that end with it.","example":"exact"},"channel":{"type":"string","enum":["email","sms","all"],"description":"The channel the rule applies to: email (the default), sms, or all for both.","example":"email"},"target":{"type":"string","enum":["several","all"],"description":"several links the rule to the lists in lists. all links it to all lists, and needs the primary admin or a user in the main admin group. Any other value fails with \"No lists selected\".","example":"several"},"lists":{"type":"array","items":{"type":"integer"},"description":"IDs of the lists to link when target is several. Repeated IDs count once. An empty array fails with \"No lists selected\". List ID 0 links the rule to all lists. List IDs are not checked against existing lists.","example":[3,5]}}},"ExclusionDetail":{"type":"object","description":"One exclusion rule with its lists.","properties":{"id":{"type":"string","description":"ID of the rule.","example":"7"},"email":{"type":["string","null"],"description":"The address or pattern the rule matches.","example":"sam@example.com"},"matchtype":{"type":"string","enum":["exact","begin","end"],"description":"How email is matched: exact for the whole address, begin for addresses that start with it, end for addresses that end with it.","example":"exact"},"hidden":{"type":"string","description":"\"1\" when the rule was added because a contact reported a campaign as spam, else \"0\".","example":"0"},"channel":{"type":"string","enum":["email","sms","all"],"description":"The channel the rule applies to: email, sms, or all for both.","example":"email"},"lists":{"type":"string","description":"Comma-separated IDs of the rule's lists. \"0\" means all lists. Empty when the rule has no lists.","example":"3,5"},"matchall":{"type":"boolean","description":"True when the rule applies to all lists.","example":false},"wildcard":{"type":"string","description":"Old flag, \"0\" or \"1\". New rules use matchtype instead.","example":"0"}}},"ExclusionListLink":{"type":"object","description":"A link between a rule and a list. Values are strings.","properties":{"exclusionid":{"type":"string","description":"ID of the rule.","example":"7"},"listid":{"type":"string","description":"ID of the list. \"0\" means all lists.","example":"3"},"sync":{"type":"string","description":"Old flag. Always \"0\" for new links.","example":"0"},"created_timestamp":{"type":["string","null"],"description":"When the link was created, as \"YYYY-MM-DD HH:MM:SS\". Null when not set.","example":"2026-10-01 09:30:00"},"updated_timestamp":{"type":["string","null"],"description":"When the link was last changed, as \"YYYY-MM-DD HH:MM:SS\". Null when not set.","example":"2026-10-01 09:30:00"},"links":{"type":"array","description":"Always an empty array.","maxItems":0,"example":[]},"id":{"type":"string","description":"ID of the link.","example":"12"}}},"ExclusionNotFoundError":{"type":"object","properties":{"message":{"type":"string","description":"\"No Result found for Exclusion with id\" followed by the ID as a whole number.","example":"No Result found for Exclusion with id 7"}}},"ExclusionSaved":{"type":"object","description":"The rule was written.","properties":{"exclusion":{"type":"object","description":"The rule that was written.","properties":{"id":{"type":"string","description":"ID of the rule.","example":"7"},"email":{"type":["string","null"],"description":"On create, the email as sent. On update, the stored address or pattern.","example":"sam@example.com"}}},"status":{"type":"string","const":"success","description":"Always success.","example":"success"}}},"ExclusionUpdate":{"type":"object","required":["target"],"properties":{"channel":{"type":"string","enum":["email","sms","all"],"description":"The new channel: email, sms, or all for both. When it is left out, the channel stays the same.","example":"email"},"target":{"type":"string","enum":["several","all"],"description":"several links the rule to the lists in lists. all links it to all lists, and needs the primary admin or a user in the main admin group. Any other value fails with \"No lists selected\".","example":"several"},"lists":{"type":"array","items":{"type":"integer"},"description":"IDs of the lists to link when target is several. Repeated IDs count once. An empty array fails with \"No lists selected\". List ID 0 links the rule to all lists. List IDs are not checked against existing lists.","example":[3,5]}}},"ExclusionWriteFailed":{"type":"object","description":"Returned with HTTP 200 when a check fails. Nothing is written.","properties":{"status":{"type":"string","const":"error","description":"Always error.","example":"error"},"message":{"type":"string","description":"What failed. The main create checks, in the order they run, are \"Invalid match type\", then \"No lists selected\" or \"You don't have permission to access this resource\", then \"Invalid channel type\", then \"Email address is required\", \"Not valid email address\" or \"Email address is too long\", then \"Exclusion already exists\". The update first checks the ID, with \"No Result found for Exclusion with id\" and the ID, then the lists, then the channel.","example":"Exclusion already exists"},"code":{"type":["integer","string"],"description":"The HTTP status the failure stands for: 422 for the match type or channel, 400 for the lists or the email, 403 for the permission check, 409 for a duplicate, and 0 for an unknown ID or a failed transaction. A database error also returns 200 with status error; the message is the database error and code is then a string such as HY000.","example":409}}},"FailureDetail":{"properties":{"errorCode":{"description":"The error code the failed messages share.","type":"string"},"errorSource":{"description":"Where the error code comes from: \"ac\" for ActiveCampaign or \"twilio\" for Twilio.","type":"string","enum":["ac","twilio"]},"count":{"description":"Number of failed messages with this error code.","type":"integer"}},"type":"object"},"FailureDetailsResponse":{"properties":{"failures":{"description":"The failed messages of the broadcast, grouped by error code. Empty when none failed.","type":"array","items":{"$ref":"#/components/schemas/FailureDetail"}}},"type":"object"},"FieldDO":{"title":"FieldDO","required":["data_type","name","operator","value"],"type":"object","properties":{"value":{"type":"string","description":"Value the `name` field's value should be evaluated against. Sometimes optional based on `operator`","example":"14"},"data_type":{"type":"string","enum":["string","number","decimal","date","datetime","list",""],"example":"string"},"name":{"type":"string","description":"Field whose value will be evaluated","example":"tagid"},"operator":{"type":"string","description":"All possible operators for evaluating the field's value against the `value` field","enum":["=","<",">","<=",">=","!=","starts with","does not start with","contains","does not contain","is","is not","is in any","missing at least one","empty","not empty","empty|=","empty|<","empty|<=","wildcard match","any","not_previous","between","not between","all","none",""],"example":"="},"external":{"type":"boolean","description":"(Optional. Default False) If `external` is present and true, then the value of this FieldDO's \"value\" attribute is ignored and the externalId passed at-query time is used as the value of this FieldDO's \"value\" attribute. Segments with an `\"external\": true` value will not evaluate without an external-id defined at request time. This attribute is commonly used to ensure the same pre-determined object satisfies multiple conditions","default":false}}},"FieldDetail":{"type":"object","description":"The required and default-value setting for one standard field.","properties":{"id":{"type":"string","description":"The setting's id: the record type and the field name joined by a dot. Use it as the id in PUT /fieldDetails/{id}.","example":"contact.first_name"},"name":{"type":"string","description":"The field name, the part of id after the dot.","example":"first_name"},"type":{"type":"string","description":"The record type the field belongs to: contact, deal or account.","example":"contact"},"isRequired":{"type":"boolean","description":"Whether the field must have a value.","example":false},"defaultValue":{"type":["string","null"],"description":"The value used when the field has none. An empty string when no default is set. For the userid and account_owner fields this is the id of the default owner.","example":""}}},"FieldDetailError":{"type":"object","description":"The body of a failed request.","properties":{"errors":{"type":"array","description":"One item, describing the problem.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as a number.","example":400},"title":{"type":"string","description":"The name of the HTTP status.","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the request. Left out of 404 responses.","example":"A defaultValue must be provided for required fields"}}}}}},"FieldMappingAsyncRequest":{"description":"The stored suggested field mapping request to generate, and the fields it was made with. Sent only by Hosted's own background dispatcher, never by a client.","required":["record_id","source_fields","target_fields"],"properties":{"record_id":{"description":"Id of the stored request, the recordId that asyncGenerate returned. It must name a stored suggested field mapping request.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"source_fields":{"description":"The fields data comes from, at least one.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingField"},"minItems":1},"target_fields":{"description":"The fields data goes into, at least one.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingField"},"minItems":1},"integration_name":{"description":"Name of the integration the source fields belong to.","type":["string","null"],"example":"Stripe"}},"type":"object"},"FieldMappingDispatchedResponse":{"description":"The request that was queued, used to poll for its result.","required":["recordId","message"],"properties":{"recordId":{"description":"Id of the stored request. Pass it as requestId to the poll and results endpoints.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"message":{"description":"Says what happened. The text is fixed but is not a contract.","type":"string","example":"Successfully dispatched async generating request."}},"type":"object"},"FieldMappingFeedbackRequest":{"description":"Whether the user found the suggested field mapping useful.","properties":{"useful":{"description":"True when the user found the suggestion useful, false when not. Counted in an aggregate metric; nothing is stored about the account or the user.","type":"boolean","default":false,"example":true}},"type":"object"},"FieldMappingField":{"description":"A field that can be mapped, on the source or the target side of an integration.","required":["id","title","type"],"properties":{"id":{"description":"Identifier of the field. Suggestions refer to fields by this id, and a suggestion naming an id that is not in the submitted fields is dropped.","type":"string","example":"email"},"title":{"description":"Name of the field as the user sees it.","type":"string","example":"Email address"},"type":{"description":"The field's data type, as the caller names it.","type":"string","example":"string"},"required":{"description":"Whether the field must be mapped.","type":"boolean","example":true},"group":{"description":"Id of the group the field belongs to. Returned unchanged on each match.","type":"string","example":"contact"},"groupTitle":{"description":"Name of that group as the user sees it.","type":"string","example":"Contact"},"schemaId":{"description":"Id of the schema the field belongs to. Returned unchanged on each match.","type":"string","example":"custom-object-schema-1"}},"type":"object"},"FieldMappingMatch":{"description":"One suggested pairing of a source field with a target field, in the form the field mapping screen uses.","required":["targetFieldId","sourceFieldId","hasValidationError","key","targetGroup","sourceGroup","targetSchemaId","sourceSchemaId","rawValue"],"properties":{"targetFieldId":{"description":"Id of the target field.","type":"string","example":"email"},"sourceFieldId":{"description":"Id of the source field the target is filled from.","type":"string","example":"email_address"},"hasValidationError":{"description":"Always false: a suggestion is not validated here.","type":"boolean","example":false},"key":{"description":"Always null.","type":["string","null"],"example":null},"targetGroup":{"description":"The group of the target field, as submitted. Null when it had none.","type":["string","null"],"example":"contact"},"sourceGroup":{"description":"The group of the source field, as submitted. Null when it had none.","type":["string","null"],"example":"lead"},"targetSchemaId":{"description":"The schema id of the target field, as submitted. Null when it had none.","type":["string","null"],"example":null},"sourceSchemaId":{"description":"The schema id of the source field, as submitted. Null when it had none.","type":["string","null"],"example":null},"rawValue":{"description":"Always null: suggestions pair two fields, they never carry a fixed value.","type":["string","null"],"example":null}},"type":"object"},"FieldMappingMatchesResponse":{"description":"The suggested pairings of source and target fields.","required":["message","matches"],"properties":{"message":{"description":"Says what happened. The text is fixed but is not a contract.","type":"string","example":"Suggested mapping generated successfully."},"matches":{"description":"The suggested pairings, only those whose two field ids are among the submitted fields. Empty when the model suggested nothing usable.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingMatch"}}},"type":"object"},"FieldMappingMessageResponse":{"description":"A one-line message saying what happened.","required":["message"],"properties":{"message":{"description":"Says what happened. The text is fixed for each outcome but is not a contract. The cause of a failure is only logged.","type":"string","example":"There was an error while generating a suggested mapping."}},"type":"object"},"FieldMappingRequest":{"description":"The two sets of fields to pair up. The model suggests, for each target field it is confident about, which source field feeds it.","required":["targetFields","sourceFields"],"properties":{"sourceFields":{"description":"The fields data comes from, at least one.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingField"},"minItems":1},"targetFields":{"description":"The fields data goes into, at least one.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingField"},"minItems":1},"integrationName":{"description":"Name of the integration the source fields belong to. When given, the model only pairs that integration's fields with each other and with ActiveCampaign native and custom fields; fields of other integrations are ignored.","type":["string","null"],"example":"Stripe"}},"type":"object"},"FieldMappingResultsErrorResponse":{"description":"The suggested mapping could not be read.","required":["message","matches"],"properties":{"message":{"description":"Always the same text. The cause is only logged.","type":"string","enum":["There was an error while fetching suggested field mapping."],"example":"There was an error while fetching suggested field mapping."},"matches":{"description":"Always null.","type":["array","null"],"items":{"$ref":"#/components/schemas/FieldMappingMatch"},"example":null}},"type":"object"},"FieldMappingStatusResponse":{"description":"The status of a finished suggested field mapping request.","required":["status"],"properties":{"status":{"description":"Always success: a request still being generated answers 409 and one that failed answers 500.","type":"string","enum":["success"],"example":"success"}},"type":"object"},"FieldMappingSuggestion":{"description":"One pairing exactly as the model proposed it, before it is matched against the submitted fields.","required":["sourceField","targetField","confidence","notes"],"properties":{"sourceField":{"description":"Id of the source field.","type":"string","example":"email_address"},"targetField":{"description":"Id of the target field.","type":"string","example":"email"},"confidence":{"description":"How sure the model is, from 0 to 1. The model is asked to leave out pairings it is less than 0.6 sure of.","type":"number","format":"float","maximum":1,"minimum":0,"example":0.95},"notes":{"description":"The model's explanation of the pairing. Can be empty.","type":"string","example":"Both hold the contact's email address."}},"type":"object"},"FieldMappingSuggestionsResponse":{"description":"The model's suggested pairings, saved on the request.","required":["message","matches"],"properties":{"message":{"description":"Says what happened. The text is fixed but is not a contract.","type":"string","example":"Suggested field mapping was created successfully."},"matches":{"description":"The pairings as the model proposed them. Unlike the results endpoint, they are not matched against the submitted fields.","type":"array","items":{"$ref":"#/components/schemas/FieldMappingSuggestion"}}},"type":"object"},"FieldOptionBodyNotObjectError":{"type":"object","properties":{"errors":{"description":"One entry describing the error.","type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"description":"HTTP status code."},"title":{"type":"string","example":"Bad Request","description":"Short name of the error."},"detail":{"type":"string","example":"Request body must be a JSON object, array given.","description":"What was wrong with the body."}}}}}},"FieldRelBodyNotObjectError":{"type":"object","properties":{"errors":{"description":"One entry describing the error.","type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"description":"HTTP status code."},"title":{"type":"string","example":"Bad Request","description":"Short name of the error."},"detail":{"type":"string","example":"Request body must be a JSON object, array given.","description":"What was wrong with the body."}}}}}},"FileSummaryListItem":{"description":"A conversation file summary as listed, without the summary text. Get the summary by id to read it.","required":["id","created_by","created_at","updated_at","original_file_name","stored_file_path","mime_type"],"properties":{"id":{"description":"Id of the file summary.","type":"integer","example":101},"created_by":{"description":"Id of the user who owns the summary.","type":"integer","example":7},"created_at":{"description":"When the summary was created, as an ISO 8601 timestamp with its UTC offset.","type":"string","format":"date-time","example":"2026-10-19T09:30:00-05:00"},"updated_at":{"description":"When the summary was last changed, as an ISO 8601 timestamp with its UTC offset.","type":"string","format":"date-time","example":"2026-10-19T09:45:00-05:00"},"original_file_name":{"description":"The name of the file as the user knows it.","type":"string","example":"brand-guidelines.pdf"},"stored_file_path":{"description":"Where the file itself is stored.","type":"string","example":"s3://example-bucket/ac-agents/uploads/account_id=12345/user_id=7/conversation_id=c8d1e5f2/3a9f1b"},"mime_type":{"description":"The MIME type of the file. Null when it was not recorded.","type":["string","null"],"example":"application/pdf"},"conversation_id":{"description":"Id of the conversation the file was uploaded in.","type":"string","example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"},"description":{"description":"A short description of the file. Present only when one was recorded.","type":"string","example":"Our brand colours, fonts and tone of voice."}},"type":"object"},"FileSummaryResource":{"description":"A summary of a file, either one uploaded in an AI conversation or one saved as a resource.","required":["id","created_by","created_at","updated_at","original_file_name","stored_file_path","mime_type"],"properties":{"id":{"description":"Id of the file summary.","type":"integer","example":101},"created_by":{"description":"Id of the user who owns the summary. Only that user can read, change or delete it.","type":"integer","example":7},"created_at":{"description":"When the summary was created, as an ISO 8601 timestamp with its UTC offset.","type":"string","format":"date-time","example":"2026-10-19T09:30:00-05:00"},"updated_at":{"description":"When the summary was last changed, as an ISO 8601 timestamp with its UTC offset.","type":"string","format":"date-time","example":"2026-10-19T09:45:00-05:00"},"original_file_name":{"description":"The name of the file as the user knows it.","type":"string","example":"brand-guidelines.pdf"},"stored_file_path":{"description":"Where the file itself is stored. For a file saved from a conversation this is the S3 path of the upload. For a file uploaded directly through the resource upload operation it is currently a placeholder, because the file is not yet stored.","type":"string","example":"s3://example-bucket/ac-agents/uploads/account_id=12345/user_id=7/conversation_id=c8d1e5f2/3a9f1b"},"mime_type":{"description":"The MIME type of the file. Null when it was not recorded.","type":["string","null"],"example":"application/pdf"},"conversation_id":{"description":"Id of the conversation the file was uploaded in. Present for conversation summaries and for resources saved from an existing conversation summary; absent for files uploaded directly as resources.","type":"string","example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"},"description":{"description":"A short description of the file. Present only when one was recorded.","type":"string","example":"Our brand colours, fonts and tone of voice."},"summary":{"description":"The summary of the file's content. Left out of the conversation list.","type":"string","example":"A six-page guide to the company brand: palette, typography and voice."}},"type":"object"},"FileUploadErrorResponse":{"description":"Why a file was rejected.","required":["error"],"properties":{"error":{"description":"What is wrong with the file.","type":"string","example":"Only PDF, DOCX, and image files are allowed."}},"type":"object"},"FinalSendCountResult":{"description":"How many contacts a campaign would be sent to now, and whether that is over the account sending limit. While a segment count is still running, the counts are null and runId names the run to poll.","required":["numberOfRecipients","numberOfRecipientsFormatted","numRecipientsPastLimit","runId"],"properties":{"numberOfRecipients":{"description":"Number of contacts the campaign would be sent to: the contacts on its lists, narrowed by its segment when it has one. Null while the segment count is still running.","type":["integer","null"],"example":1250},"numberOfRecipientsFormatted":{"description":"numberOfRecipients formatted for display with thousands separators. Null while the segment count is still running.","type":["string","null"],"example":"1,250"},"numRecipientsPastLimit":{"description":"True when sending to numberOfRecipients contacts would take the account past its sending limit. Always false for an automation campaign, and false while the count is still running.","type":"boolean","example":false},"runId":{"description":"For a campaign with a segment, the ID of the segment count run; pass it to GET /campaign/{campaignId}/final-send-count/{runId} to poll a count that was not ready. For a campaign without a segment the lists are counted directly and this is the runId of the request, so null on the route without one.","type":["string","null"]}},"type":"object"},"FinalizeRequest":{"description":"Worker payload for the finishing step of an AI content automation block: the outcome of the content generation for one contact, posted back by the Bedrock processing service or dispatched by Hosted after POST /ai/dynamic-data/generate.","required":["blockid","contactseriesid","starttime"],"properties":{"generated_content":{"description":"The text the model generated for the contact, to be written to the block's target field. For a prompt action it is a JSON string carrying prompt_action_type and the action's result, which the server turns into the field value. Null when the generation failed or was blocked, in which case the block is skipped.","type":["string","null"],"example":"Hi Ada, thanks for choosing Acme."},"blockid":{"description":"Id of the automation block being completed. Must name an existing block of type aidynamicdata.","type":"integer","example":4821},"contactseriesid":{"description":"Id of the contact's entry in the automation (the contact automation record) waiting at the block.","type":"integer","example":91337},"starttime":{"description":"Unix time with microseconds at which the block started processing the contact, carried through from the process step to report the processing time of the whole run.","type":"number","format":"double","example":1760000000.123456},"guardrail_policy":{"description":"Name of the guardrail policy that blocked the generation, sent with a null generated_content. When set the block is skipped with a guardrail violation recorded in the automation history instead of a generation failure.","type":["string","null"],"example":"content_filter"},"guardrail_details":{"description":"Detail of the guardrail intervention, recorded in the automation history next to guardrail_policy.","type":["string","null"],"example":"Blocked by the HATE content filter"},"block":{"description":"Ignored on input: the server loads the block named by blockid into it.","type":"object","readOnly":true},"contactSeries":{"description":"Ignored on input: the server loads the contact automation record named by contactseriesid into it.","type":"object","readOnly":true}},"type":"object"},"FlowExecutionContactFilterEdit":{"type":"object","properties":{"field":{"type":"string"},"comparison":{"$ref":"#/components/schemas/ComparisonEnum"},"value":{"type":"string"},"id":{"type":"string","format":"uuid"}},"required":["comparison","field","value"]},"FlowExecutionContactListSimple":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"contact":{"allOf":[{"$ref":"#/components/schemas/ContactReadSimple"}],"description":"The Contact that the Flow Execution Contact is for."},"status":{"$ref":"#/components/schemas/FlowExecutionContactStatusEnum"},"created_on":{"type":"string","format":"date-time","title":"Created on"},"status_reason":{"type":"string","readOnly":true,"nullable":true},"is_test":{"type":"boolean"},"flow_version":{"type":"string","format":"uuid","nullable":true},"flow":{"type":"string","format":"uuid","nullable":true},"flow_name":{"type":"string","readOnly":true,"description":"The name of the Flow that the Flow Execution Contact is for."}},"required":["contact","flow_name","id","status_reason"]},"FlowExecutionContactReadDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"contact":{"allOf":[{"$ref":"#/components/schemas/ContactReadSimple"}],"description":"The Contact that the Flow Execution Contact is for."},"status":{"$ref":"#/components/schemas/FlowExecutionContactStatusEnum"},"execution_steps":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionStepReadDetail"},"description":"The Flow Execution Steps that the Flow Execution Contact has."},"created_on":{"type":"string","format":"date-time","title":"Created on"},"flow_execution":{"type":"string","format":"uuid","nullable":true},"status_reason":{"type":"string","readOnly":true,"nullable":true},"flow":{"allOf":[{"$ref":"#/components/schemas/FlowListRead"}],"description":"Details for the Flow"},"flow_version":{"allOf":[{"$ref":"#/components/schemas/FlowVersionSimpleListRead"}],"description":"Details for the Flow Version"},"status_triggered_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"status_last_change_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"inbox_contact_id":{"type":"string","format":"uuid","readOnly":true},"is_test":{"type":"boolean"}},"required":["contact","execution_steps","flow","flow_version","inbox_contact_id","status_last_change_on","status_reason","status_triggered_by"]},"FlowExecutionContactStatusEnum":{"enum":["READY","RUNNING","COMPLETED","CANCELED","EXPIRED","FAILED"],"type":"string","description":"* `READY` - Ready\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `CANCELED` - Canceled\n* `EXPIRED` - Expired\n* `FAILED` - Failed"},"FlowExecutionCreateRequest":{"type":"object","properties":{"execute_for":{"$ref":"#/components/schemas/FlowExecutionCreateRequestExecuteForEnum"},"has_priority":{"type":"boolean","default":false,"description":"Specify as True if you want this execution to                 close any other running flows or conversations."},"contact_list":{"type":"array","items":{"$ref":"#/components/schemas/PatchedContactEdit"}}},"required":["contact_list","execute_for"]},"FlowExecutionCreateRequestExecuteForEnum":{"enum":["LIST"],"type":"string","description":"* `LIST` - LIST"},"FlowExecutionEdit":{"type":"object","properties":{"status":{"type":"string","readOnly":true,"description":"The status of the Flow Execution."},"execute_for":{"$ref":"#/components/schemas/FlowExecutionExecuteForEnum"},"id":{"type":"string","format":"uuid"},"has_priority":{"type":"boolean"},"flow_execution_variables":{},"start_on":{"type":"string","format":"date-time","nullable":true},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"created_on":{"type":"string","format":"date-time","title":"Created on"},"avg_completion_time":{"type":"string"},"status_reason":{"type":"string","readOnly":true,"nullable":true},"status_triggered_by":{"type":"integer","readOnly":true,"nullable":true},"status_last_change_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"contact_filters":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionContactFilterEdit"},"description":"The filters to use to get the Contacts that the Flow Execution will run for."},"contact_list":{"type":"array","items":{"$ref":"#/components/schemas/PatchedContactEdit"},"description":"The list of Contacts that the Flow Execution will run for."},"source":{"$ref":"#/components/schemas/FlowExecutionEditSourceEnum"},"is_hidden":{"type":"boolean"}},"required":["execute_for","status","status_last_change_on","status_reason","status_triggered_by"]},"FlowExecutionEditSourceEnum":{"enum":["HUBSPOT","API","FRONTEND"],"type":"string","description":"* `HUBSPOT` - Hubspot\n* `API` - Api\n* `FRONTEND` - Frontend"},"FlowExecutionExecuteForEnum":{"enum":["FILTERS","LIST","ALL"],"type":"string","description":"* `FILTERS` - Filters\n* `LIST` - List\n* `ALL` - All"},"FlowExecutionList":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/FlowExecutionStatusEnum"},"execute_for":{"$ref":"#/components/schemas/FlowExecutionExecuteForEnum"},"id":{"type":"string","format":"uuid"},"has_priority":{"type":"boolean"},"flow_execution_variables":{},"start_on":{"type":"string","format":"date-time","nullable":true},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"created_on":{"type":"string","format":"date-time","title":"Created on"},"avg_completion_time":{"type":"string"},"status_reason":{"type":"string","nullable":true},"status_triggered_by":{"type":"integer","nullable":true},"status_last_change_on":{"type":"string","format":"date-time","nullable":true},"created_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"description":"The User that created the Flow Execution."},"flow_version":{"type":"string","format":"uuid"}},"required":["created_by","execute_for","flow_version"]},"FlowExecutionReadDetail":{"type":"object","properties":{"status":{"allOf":[{"$ref":"#/components/schemas/FlowExecutionStatusEnum"}],"readOnly":true,"description":"The status of the Flow Execution.\n\n* `PROCESSING` - Processing\n* `READY` - Ready\n* `AWAITING_CONFIRMATION` - Awaiting Confirmation\n* `CONFIRMED` - Confirmed\n* `STARTING` - Starting\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `CANCELED` - Canceled"},"execute_for":{"$ref":"#/components/schemas/FlowExecutionExecuteForEnum"},"id":{"type":"string","format":"uuid"},"has_priority":{"type":"boolean"},"flow_execution_variables":{},"start_on":{"type":"string","format":"date-time","nullable":true},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"created_on":{"type":"string","format":"date-time","title":"Created on"},"avg_completion_time":{"type":"string"},"status_reason":{"type":"string","readOnly":true,"nullable":true},"status_triggered_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"status_last_change_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"created_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"description":"The User that created the Flow Execution."},"contact_filters":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionContactFilterEdit"},"description":"The filters to use to get the Contacts that the Flow Execution will run for. This field isn't required if executing the flow for a Contact List"},"contact_import":{"type":"string","format":"uuid","nullable":true},"flow":{"allOf":[{"$ref":"#/components/schemas/FlowSimpleRead"}],"description":"The Flow that the Flow Execution is running."},"flow_version":{"allOf":[{"$ref":"#/components/schemas/FlowVersionSimpleRead"}],"description":"The Flow Version that the Flow Execution is running."},"last_run_on":{"type":"string","format":"date-time","readOnly":true,"description":"The last time that the Flow Execution was run."}},"required":["created_by","execute_for","flow","flow_version","last_run_on","status","status_last_change_on","status_reason","status_triggered_by"]},"FlowExecutionStatusEnum":{"enum":["PROCESSING","READY","AWAITING_CONFIRMATION","CONFIRMED","STARTING","RUNNING","COMPLETED","CANCELED"],"type":"string","description":"* `PROCESSING` - Processing\n* `READY` - Ready\n* `AWAITING_CONFIRMATION` - Awaiting Confirmation\n* `CONFIRMED` - Confirmed\n* `STARTING` - Starting\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `CANCELED` - Canceled"},"FlowExecutionStepReadDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"step":{"allOf":[{"$ref":"#/components/schemas/FlowStepEdit"}],"readOnly":true},"status_reason":{"type":"string","nullable":true},"has_error":{"type":"boolean"},"expire_on":{"type":"string","format":"date-time","nullable":true},"status":{"$ref":"#/components/schemas/FlowExecutionStepReadDetailStatusEnum"},"validation_failed_attempts":{"type":"integer","maximum":32767,"minimum":0},"execution_result":{"nullable":true},"request_data":{"nullable":true},"messages":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionStepWhatsAppMessage"}},"created_on":{"type":"string","format":"date-time","title":"Created on"},"status_triggered_by":{"type":"integer","nullable":true},"status_last_change_on":{"type":"string","format":"date-time","nullable":true}},"required":["messages","step"]},"FlowExecutionStepReadDetailStatusEnum":{"enum":["WAITING_TO_START","NOT_EXECUTED","RUNNING","COMPLETED","CANCELED","FAILED","EXPIRED"],"type":"string","description":"* `WAITING_TO_START` - Waiting To Start\n* `NOT_EXECUTED` - Not Executed\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `CANCELED` - Canceled\n* `FAILED` - Failed\n* `EXPIRED` - Expired"},"FlowExecutionStepWhatsAppMessage":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/WhatsAppMessage"}},"required":["message"]},"FlowListRead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"name":{"type":"string","maxLength":100},"created_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"created_on":{"type":"string","format":"date-time","title":"Created on"},"is_active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/FlowStatusEnum"},"is_legacy":{"type":"boolean"},"channel":{"allOf":[{"$ref":"#/components/schemas/SimpleChannel"}],"readOnly":true},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"needs_update":{"type":"boolean"},"avg_completion_time":{"type":"string"},"current_version":{"type":"string","format":"uuid","nullable":true},"is_template":{"type":"boolean"},"trigger_type":{"$ref":"#/components/schemas/TriggerTypeEnum"},"trigger_config":{},"test_version":{"type":"string","format":"uuid","nullable":true},"upgrade_version":{"type":"string","format":"uuid","nullable":true},"legacy_version":{"type":"string","format":"uuid","nullable":true}},"required":["channel","created_by","id","name","trigger_type"]},"FlowSimpleRead":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"name":{"type":"string","maxLength":100},"created_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"created_on":{"type":"string","format":"date-time","title":"Created on"},"is_active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/FlowStatusEnum"},"is_legacy":{"type":"boolean"},"channel":{"allOf":[{"$ref":"#/components/schemas/SimpleChannel"}],"readOnly":true},"flow_execution_variables":{"type":"array","items":{"type":"string","maxLength":255},"nullable":true},"trigger_type":{"$ref":"#/components/schemas/TriggerTypeEnum"},"trigger_config":{}},"required":["channel","created_by","id","name","trigger_type"]},"FlowStatusEnum":{"enum":["DRAFT","PUBLISHED"],"type":"string","description":"* `DRAFT` - Draft\n* `PUBLISHED` - Published"},"FlowStepContactUpdateCustomProperty":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]},"FlowStepEdit":{"type":"object","description":"This class is not useful other than for the OpenAPI Schema.","properties":{"flow_version":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":100},"step_type":{"type":"string","maxLength":100},"next_step_default_idx":{"type":"integer","maximum":32767,"minimum":0,"nullable":true},"id":{"type":"string","format":"uuid"},"next_step_default":{"type":"string","format":"uuid"},"next_step_alternate":{"type":"string","format":"uuid"},"answer_failed_next_step":{"type":"string","format":"uuid","nullable":true},"next_steps_for_options":{"type":"array","items":{"type":"string","format":"uuid"}},"answer_type":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/AnswerTypeEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"body":{"type":"string","nullable":true},"body_type":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/MessageTypeEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"body_file_url":{"type":"string","format":"uri","nullable":true,"maxLength":2000},"body_file_type":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/BodyFileTypeEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"body_file":{"allOf":[{"$ref":"#/components/schemas/UploadedAccountFile"}],"readOnly":true},"answer_validation_message":{"type":"string","nullable":true},"answer_instructions":{"type":"string","nullable":true},"answer_options":{"type":"array","items":{"type":"string","maxLength":255},"nullable":true},"answer_phone_default_country":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/AnswerPhoneDefaultCountryEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"next_step_alternate_idx":{"type":"integer","maximum":32767,"minimum":0,"nullable":true},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/StepConditionalCondition"}},"delay_type":{"type":"string","nullable":true,"maxLength":20},"delay_until":{"type":"string","format":"date-time","nullable":true},"action_request_method":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/ActionRequestMethodEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"action_request_url":{"type":"string","format":"uri","nullable":true,"maxLength":2000},"action_request_headers":{"type":"object","additionalProperties":{"type":"string","nullable":true},"nullable":true},"action_request_params":{"type":"object","additionalProperties":{"type":"string","nullable":true},"nullable":true},"action_request_body":{"type":"string","nullable":true},"action_test_response_data":{"type":"string","format":"uuid","nullable":true},"answer_allow_decimals":{"type":"boolean"},"answer_range_min":{"type":"string","nullable":true,"maxLength":50},"answer_range_max":{"type":"string","nullable":true,"maxLength":50},"answer_has_range":{"type":"boolean"},"assign_to_users":{"type":"array","items":{"type":"integer"},"readOnly":true},"ordering_idx":{"type":"integer","maximum":32767,"minimum":0},"has_options_from_variable":{"type":"boolean"},"option_from_variable_value":{"type":"string","nullable":true},"options_from_variable":{"type":"string","nullable":true},"option_from_variable_title":{"type":"string","nullable":true},"option_from_variable_description":{"type":"string","nullable":true},"missing_options_message":{"type":"string","nullable":true},"answer_options_render":{"$ref":"#/components/schemas/AnswerOptionsRenderEnum"},"answer_options_render_list_button_title":{"type":"string","nullable":true,"maxLength":20},"answer_option_descriptions":{"type":"array","items":{"type":"string","nullable":true},"nullable":true},"next_steps_for_options_idx":{"type":"array","items":{"type":"integer","maximum":2147483647,"minimum":-2147483648,"nullable":true},"nullable":true},"contact_tags":{"type":"array","items":{"type":"string","maxLength":255},"nullable":true},"conversation_tags":{"type":"array","items":{"type":"string","maxLength":255},"nullable":true},"append_tags":{"type":"boolean"},"max_wait_time_amount":{"type":"integer","maximum":32767,"minimum":0},"max_wait_time_unit":{"$ref":"#/components/schemas/MaxWaitTimeUnitEnum"},"time_windows":{"type":"array","items":{"$ref":"#/components/schemas/FlowStepTimeWindow"}},"has_max_wait_time":{"type":"boolean"},"set_time_window":{"type":"boolean"},"assign_to_teams":{"type":"array","items":{"type":"integer"},"readOnly":true},"time_window_type":{"nullable":true,"oneOf":[{"$ref":"#/components/schemas/TimeWindowTypeEnum"},{"$ref":"#/components/schemas/BlankEnum"},{"$ref":"#/components/schemas/NullEnum"}]},"has_max_answer_attempts":{"type":"boolean"},"max_answer_attempts":{"type":"integer","maximum":32767,"minimum":0},"answer_failed_next_step_idx":{"type":"integer","maximum":32767,"minimum":0,"nullable":true},"whatsapp_template":{"type":"string","format":"uuid","readOnly":true},"whatsapp_template_variables":{"readOnly":true},"save_contact_answer":{"type":"boolean","default":false},"validate_answer_with_buttons":{"type":"boolean","default":false},"contact_custom_properties":{"type":"array","items":{"$ref":"#/components/schemas/FlowStepContactUpdateCustomProperty"}},"contact_first_name":{"type":"string"},"contact_last_name":{"type":"string"},"contact_email":{"type":"string"},"contact_external_url":{"type":"string"},"next_flow":{"type":"string"},"paths":{"type":"array","items":{"$ref":"#/components/schemas/StepConditionalMultilpePath"}},"firstname":{"type":"string"},"lastname":{"type":"string"},"email":{"type":"string"},"custom_properties":{"type":"array","items":{"type":"string"}},"next_action":{"$ref":"#/components/schemas/NextActionEnum"}},"required":["assign_to_teams","assign_to_users","body_file","conditions","flow_version","name","next_steps_for_options","step_type","time_windows","whatsapp_template","whatsapp_template_variables"]},"FlowStepTimeWindow":{"type":"object","properties":{"weekday":{"allOf":[{"$ref":"#/components/schemas/WeekdayEnum"}],"minimum":0,"maximum":32767},"is_available":{"type":"boolean"},"start_at":{"type":"string","format":"time","nullable":true},"end_at":{"type":"string","format":"time","nullable":true}},"required":["weekday"]},"FlowVersionSimpleListRead":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version_name":{"type":"string","maxLength":255},"version_description":{"type":"string","nullable":true},"published_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"created_on":{"type":"string","format":"date-time","title":"Created on"},"last_updated_on":{"type":"string","format":"date-time","readOnly":true,"title":"Last updated on"},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"avg_completion_time":{"type":"string"},"is_current_version":{"type":"boolean","readOnly":true}},"required":["is_current_version","last_updated_on","published_by"]},"FlowVersionSimpleRead":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"flow":{"$ref":"#/components/schemas/FlowSimpleRead"},"is_current_version":{"type":"boolean","readOnly":true},"version_name":{"type":"string","maxLength":255},"version_description":{"type":"string","nullable":true},"published_by":{"allOf":[{"$ref":"#/components/schemas/SimpleUser"}],"readOnly":true},"created_on":{"type":"string","format":"date-time","title":"Created on"},"last_updated_on":{"type":"string","format":"date-time","readOnly":true,"title":"Last updated on"},"num_contacts":{"type":"integer","maximum":2147483647,"minimum":0},"completed":{"type":"integer","maximum":2147483647,"minimum":0},"expired":{"type":"integer","maximum":2147483647,"minimum":0},"running":{"type":"integer","maximum":2147483647,"minimum":0},"canceled":{"type":"integer","maximum":2147483647,"minimum":0},"failed":{"type":"integer","maximum":2147483647,"minimum":0},"avg_completion_time":{"type":"string"}},"required":["flow","is_current_version","last_updated_on","published_by"]},"FontAddedResponse":{"description":"The family as recorded for the account.","required":["font"],"properties":{"font":{"$ref":"#/components/schemas/FontRecord","description":"The font, in the catalogue's spelling whatever casing was sent."}},"type":"object"},"FontErrorResponse":{"description":"Error body with a single message.","required":["error"],"properties":{"error":{"description":"Always this fixed message.","type":"string","enum":["Unknown font family"],"example":"Unknown font family"}},"type":"object"},"FontRecord":{"description":"One font family a picker can offer, in the shape the live editor and brand kit pickers consume.","required":["family","stack","url","type"],"properties":{"family":{"description":"Family name in the catalogue's spelling, which is also the CSS font-family name.","type":"string","example":"Inter"},"stack":{"description":"CSS font-family stack: the family followed by its fallbacks.","type":"string","example":"'Inter', Arial, Helvetica, sans-serif"},"url":{"description":"Bunny Fonts stylesheet address for this family alone; null for a web-safe family, which renders from what the device has.","type":["string","null"],"example":"https://fonts.bunny.net/css?family=inter:400,700"},"type":{"description":"standard for a web-safe family, custom for a webfont. The live picker groups on these spellings.","type":"string","enum":["standard","custom"],"example":"custom"}},"type":"object"},"FontStylesheetRecord":{"description":"One Bunny Fonts stylesheet address and the families it covers, so a picker can point every entry at the shared address holding it.","required":["url","families"],"properties":{"url":{"description":"Bunny Fonts address loading every family listed, in one request. Long sets are split so no address exceeds about 6,000 characters.","type":"string","example":"https://fonts.bunny.net/css?family=inter:400,700|lato:400,700"},"families":{"description":"The families this address covers. Web-safe families have no stylesheet and appear in none.","type":"array","items":{"type":"string"},"example":["Inter","Lato"]}},"type":"object"},"FontsResponse":{"description":"A list of fonts and the stylesheet addresses that render them.","required":["fonts","stylesheets"],"properties":{"fonts":{"description":"The fonts, in the order the picker shows them.","type":"array","items":{"$ref":"#/components/schemas/FontRecord"}},"stylesheets":{"description":"The Bunny Fonts addresses covering the webfonts among them.","type":"array","items":{"$ref":"#/components/schemas/FontStylesheetRecord"}}},"type":"object"},"FormCustomFieldOption":{"description":"One value a dropdown, radio, checkbox or listbox custom field offers.","required":["label","value"],"properties":{"label":{"description":"Text shown to the contact for this option.","type":"string","example":"Small"},"value":{"description":"Value stored on the contact when this option is picked.","type":"string","example":"small"},"isDefault":{"description":"Always 1, and present only on the option the field preselects. Left out on every other option.","type":"integer","enum":[1],"example":1}},"type":"object"},"FormCustomFieldRecord":{"description":"One contact custom field of the account, in the shape the form generation agent places it on a form.","required":["title","header","type","id"],"properties":{"title":{"description":"Name of the custom field.","type":"string","example":"Company size"},"header":{"description":"The same as title: the label the form shows above the field, which is how a form cfields entry names it.","type":"string","example":"Company size"},"type":{"description":"Field type, as stored on the custom field: text, textarea, dropdown, radio, checkbox, listbox, hidden, date, datetime or lookup.","type":"string","example":"dropdown"},"id":{"description":"ID of the custom field, as a numeric string.","type":"string","example":"12"},"options":{"description":"The values the field offers, in display order. Present only when the field has at least one option: dropdown, radio, checkbox and listbox fields; left out otherwise.","type":"array","items":{"$ref":"#/components/schemas/FormCustomFieldOption"}}},"type":"object"},"FormDraftSavedResponse":{"description":"The stored draft: its ID and the data as saved.","required":["id","data"],"properties":{"id":{"description":"ID of the draft: the id sent in the body, or a new UUID when none was sent. Pass it to GET /ai/forms/draft/{id} and to later saves of the same draft.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"data":{"description":"The data object exactly as sent, now stored under the id.","type":"object"}},"type":"object"},"FormErrorResponse":{"description":"Error body with a single message.","required":["error"],"properties":{"error":{"description":"What went wrong, as a fixed sentence.","type":"string","example":"Draft not found"}},"type":"object"},"FormFontRecord":{"description":"One font the form builder can apply, keyed in the response by its slug.","required":["variants","isVariable","styles","weights","familyName","defSubset","category","provider","fallbacks"],"properties":{"variants":{"description":"Character subsets the font ships, each with the number of style and weight variants available for it.","type":"object","example":{"latin":12,"latin-ext":12,"cyrillic":12},"additionalProperties":{"type":"integer","example":12}},"isVariable":{"description":"True when the font is a variable font, so any weight in its range renders, not only the ones listed in weights.","type":"boolean","example":true},"styles":{"description":"Styles the font ships.","type":"array","items":{"type":"string","enum":["italic","normal"]},"example":["italic","normal"]},"weights":{"description":"CSS font weights the font ships, ascending.","type":"array","items":{"type":"integer"},"example":[400,500,600,700,800,900]},"familyName":{"description":"Display name, which is also the CSS font-family name.","type":"string","example":"Alegreya"},"defSubset":{"description":"Subset loaded by default. Always latin.","type":"string","example":"latin"},"category":{"description":"Font classification.","type":"string","enum":["serif","sans-serif","handwriting","monospace","display"],"example":"serif"},"provider":{"description":"Where the font is loaded from: BunnyFonts for web fonts, system for fonts installed on every device, which load nothing.","type":"string","enum":["BunnyFonts","system"],"example":"BunnyFonts"},"fallbacks":{"description":"CSS font-family fallback list to append after familyName.","type":"string","example":"'Times New Roman', Times, Baskerville, Georgia, serif"}},"type":"object"},"FormImageSearchRequest":{"description":"What photo to look for.","required":["prompt"],"properties":{"prompt":{"description":"What the photo should show, in plain words; a model turns it into search terms.","type":"string","example":"A friendly dentist office waiting room"},"orientation":{"description":"Shape of photo to prefer. Omitted: any orientation.","type":["string","null"],"enum":["portrait","landscape","square"],"example":"landscape"}},"type":"object"},"FormImageSearchResponse":{"description":"The one stock photo picked for the prompt.","required":["photo"],"properties":{"photo":{"$ref":"#/components/schemas/FormStockPhoto","description":"The first photo the stock image search returned for the prompt's search terms. Never null: a search with no match is a 500."}},"type":"object"},"FormLabel":{"description":"The association between a form and a label. It is not the label itself, which is read with GET /labels/{id}; a label upgraded to an initiative is the same record.","required":["id","form","label"],"properties":{"id":{"description":"ID of the association. Pass it to DELETE /formLabels/{id} to take the label off the form; it is not the label ID.","type":"string","example":"12"},"form":{"description":"ID of the labelled form. Read back as a numeric string; the create response echoes the value as sent.","type":["string","integer"],"example":"3"},"label":{"description":"ID of the label. Read back as a numeric string; the create response echoes the value as sent.","type":["string","integer"],"example":"7"},"created_timestamp":{"description":"When the association was created, as YYYY-MM-DD HH:MM:SS. Absent from the create response.","type":"string","example":"2026-09-23 15:37:14"},"updated_timestamp":{"description":"When the association was last changed, as YYYY-MM-DD HH:MM:SS. Absent from the create response.","type":"string","example":"2026-09-23 15:37:14"},"created_by":{"description":"ID of the user who created the association, when recorded. Absent from the create response.","type":["string","null"],"example":"1"},"updated_by":{"description":"ID of the user who last changed the association, when recorded. Absent from the create response.","type":["string","null"],"example":"1"},"title":{"description":"Name of the label. Present only on GET /formLabels with include_folder=1.","type":"string","example":"Spring launch"},"color":{"description":"Colour of the label as six hexadecimal digits without a leading #. Present only on GET /formLabels with include_folder=1.","type":"string","example":"edf0f7"},"links":{"description":"URLs of the association's related reads.","properties":{"labels":{"description":"URL that returns the label, GET /formLabels/{id}/labels.","type":"string","example":"https://:account.api-us1.com/api/3/formLabels/12/labels"},"forms":{"description":"URL that returns the form, GET /formLabels/{id}/forms.","type":"string","example":"https://:account.api-us1.com/api/3/formLabels/12/forms"}},"type":"object"}},"type":"object"},"FormSiftRequest":{"description":"A form as the form builder holds it, to send to Sift as a form update event.","required":["id","form"],"properties":{"id":{"description":"ID of the form. Send it as a JSON string, the way the form builder does.","type":"string","example":"23"},"form":{"description":"The form model as the form builder holds it (name, layout, style, fields, actions and the rest). Forwarded to Sift as it is; Hosted reads none of it.","type":"object","example":{"name":"My form","layout":"inline-form","submit":"show-thank-you","button":"Submit","thanks":"Thanks!"},"additionalProperties":true}},"type":"object"},"FormStockPhoto":{"description":"One stock photo from Pexels, with a scaled rendition to display and the original to crop from.","required":["id","url","src","alt","name","originalSrc","width","height","originalWidth","originalHeight"],"properties":{"id":{"description":"Pexels ID of the photo.","type":"integer","example":1181671},"url":{"description":"Pexels page of the photo, https://www.pexels.com/photo/<slug-and-id>/.","type":"string","example":"https://www.pexels.com/photo/woman-in-black-blazer-sitting-on-chair-1181671/"},"src":{"description":"URL of the large2x rendition, scaled down from the original; the one to place on the form.","type":"string","example":"https://images.pexels.com/photos/1181671/pexels-photo-1181671.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"},"alt":{"description":"Alt text Pexels gives the photo.","type":"string","example":"Woman in black blazer sitting on chair"},"name":{"description":"Slug of the photo taken from its Pexels page URL, or the alt text when the URL has no slug.","type":"string","example":"woman-in-black-blazer-sitting-on-chair-1181671"},"originalSrc":{"description":"URL of the full-size original.","type":"string","example":"https://images.pexels.com/photos/1181671/pexels-photo-1181671.jpeg"},"width":{"description":"Pixel width of the src rendition; null when Pexels gave no size for the original.","type":["integer","null"],"example":940},"height":{"description":"Pixel height of the src rendition; null when Pexels gave no size for the original.","type":["integer","null"],"example":650},"originalWidth":{"description":"Pixel width of the original, the ceiling for any crop; null when Pexels gave none.","type":["integer","null"],"example":5760},"originalHeight":{"description":"Pixel height of the original; null when Pexels gave none.","type":["integer","null"],"example":3840}},"type":"object"},"FormStructureValidationError":{"description":"The problems found at one place of the form structure.","required":["path","error-message"],"properties":{"path":{"description":"Where in the body the problems are, as a slash path: /form, /form/layout, /form/actiondata/actions or /form/cfields.","type":"string","example":"/form/cfields"},"error-message":{"description":"One sentence per problem at that path.","type":"array","items":{"type":"string","example":"Either email or phone field is required"}}},"type":"object"},"FormStructureValidationErrorResponse":{"description":"The form structure is incomplete or inconsistent; nothing was saved.","required":["error"],"properties":{"error":{"description":"One entry per path with problems, in the order the checks run.","type":"array","items":{"$ref":"#/components/schemas/FormStructureValidationError"}}},"type":"object"},"FormSubmissionRecord":{"description":"One submission of the form, or for type unique and contacts one contact with the date that counts for them.","required":["contactId","email","submittedAt"],"properties":{"submissionId":{"description":"ID of the submission. Present for type all only.","type":"integer","example":9001},"contactId":{"description":"ID of the contact who submitted.","type":"integer","example":17},"email":{"description":"Email of the contact, or null when the contact no longer exists.","type":["string","null"],"example":"ada@example.com"},"submittedAt":{"description":"When it was submitted, Y-m-d H:i:s in the account's time zone. For type all the submission's own time, for unique the contact's latest submission of the form, for contacts the contact's first ever form submission.","type":"string","example":"2026-07-14 09:12:46"}},"type":"object"},"FormSubmissionsAggregatedFilters":{"description":"The query parameters the series was built from, with the defaults filled in.","required":["formId","type","aggregation","dateFrom","dateTo"],"properties":{"formId":{"description":"ID of the form.","type":"integer","example":42},"type":{"description":"What was counted.","type":"string","enum":["all","unique","contacts"],"example":"all"},"aggregation":{"description":"Bucket size.","type":"string","enum":["day","week","month"],"example":"day"},"dateFrom":{"description":"First day counted, Y-m-d.","type":"string","example":"2026-07-01"},"dateTo":{"description":"Last day counted, Y-m-d.","type":"string","example":"2026-07-13"}},"type":"object"},"FormSubmissionsAggregatedResponse":{"description":"Per-period counts of the form's submissions over the requested range.","required":["filters","total","results"],"properties":{"filters":{"$ref":"#/components/schemas/FormSubmissionsAggregatedFilters","description":"The filters applied."},"total":{"description":"Sum of the counts in results. For type unique a contact is counted once per bucket, so this can exceed the distinct contacts over the whole range.","type":"integer","example":57},"results":{"description":"One entry per bucket from the one containing dateFrom to the one containing dateTo, in order, with 0 for buckets without rows. Keyed by the bucket's first day, Y-m-d: the day itself, the Monday of the week, or the first of the month, so the first and last keys can fall outside the requested range although the counts never do.","type":"object","example":{"2026-07-01":4,"2026-07-02":0,"2026-07-03":9},"additionalProperties":{"type":"integer","example":4}}},"type":"object"},"FormSubmissionsFilters":{"description":"The query parameters the list was filtered by, with the defaults filled in.","required":["formId","type","dateFrom","dateTo"],"properties":{"formId":{"description":"ID of the form.","type":"integer","example":42},"type":{"description":"Which rows were listed.","type":"string","enum":["all","unique","contacts"],"example":"all"},"dateFrom":{"description":"First day included, Y-m-d, or null when the list was not bounded below.","type":["string","null"],"example":"2026-07-01"},"dateTo":{"description":"Last day included, Y-m-d, or null when the list was not bounded above.","type":["string","null"],"example":"2026-07-31"}},"type":"object"},"FormSubmissionsResponse":{"description":"One page of the form's submissions and the filters that produced it.","required":["filters","total","limit","offset","results"],"properties":{"filters":{"$ref":"#/components/schemas/FormSubmissionsFilters","description":"The filters applied."},"total":{"description":"Rows matching the filters across all pages: submissions for type all, distinct contacts for unique and contacts.","type":"integer","example":128},"limit":{"description":"Page size applied.","type":"integer","example":500},"offset":{"description":"Rows skipped before this page.","type":"integer","example":0},"results":{"description":"The page, newest first by submittedAt.","type":"array","items":{"$ref":"#/components/schemas/FormSubmissionRecord"}}},"type":"object"},"FranchiseeAccountMapping":{"description":"A franchisee account linked to a franchisor account, as jsonSerialize() writes it.","required":["accountId","franchisorAccountId","approvalRequired","createdTimestamp","updatedTimestamp"],"properties":{"accountId":{"description":"ID of the franchisee account.","type":"integer","example":2002},"franchisorAccountId":{"description":"ID of the franchisor account the franchisee is linked to.","type":"integer","example":1001},"approvalRequired":{"description":"Whether the franchisee needs the franchisor to approve its campaigns before they send.","type":"boolean","example":true},"createdTimestamp":{"description":"When the link was created, as a database date and time (Y-m-d H:i:s).","type":"string","example":"2026-01-15 10:30:00"},"updatedTimestamp":{"description":"When the link was last changed, as a database date and time (Y-m-d H:i:s).","type":"string","example":"2026-01-15 10:30:00"}},"type":"object"},"FromMarkupRequest":{"description":"Finished email markup from the generation engine to persist as a current-editor (ed_version 3) campaign, or as an asset draft or a library template when the matching flag is set. Hosted inlines the css into the html for delivery and stores both as the editable source; nothing is generated here.","required":["html","source"],"properties":{"html":{"description":"The email HTML, at most 2,000,000 characters, stored as the editable source and inlined for delivery.","type":"string","example":"<html><body><h1>October arrivals</h1></body></html>"},"css":{"description":"The email CSS, at most 500,000 characters, inlined into the html for delivery.","type":"string","example":"h1 { color: #333; }"},"subject":{"description":"Subject line for the message, or null for none.","type":["string","null"],"example":"Your October picks are here"},"preHeader":{"description":"Preheader text for the message, or null for none.","type":["string","null"],"example":"New arrivals, member offers and more"},"campaignName":{"description":"Name for the campaign, and for the template when templateName is omitted. Omitted, a placeholder name is used.","type":["string","null"],"example":"October newsletter"},"source":{"description":"Where the markup comes from; the campaign is filed in that source's folder.","type":"string","enum":["agent","initiatives-detail"],"example":"agent"},"labelId":{"description":"Id of a campaign folder (label) of the account to file the campaign under, or null.","type":["integer","null"],"example":3},"seriesId":{"description":"Id of an automation of the account to create the campaign for, or null for a standalone campaign.","type":["integer","null"],"example":12},"isAssetDraft":{"description":"True to save the markup as an asset draft instead of a live campaign. Honoured only when asset-draft creation is enabled for the account; otherwise a live campaign is created. isTemplate takes precedence.","type":"boolean","example":false},"isTemplate":{"description":"True to save the markup into the template library instead of creating a campaign or a draft. Needs the permission to create templates.","type":"boolean","example":false},"templateName":{"description":"Library name for the saved template, at most 255 characters. Omitted, campaignName is used.","type":["string","null"],"example":"October newsletter layout"},"designIr":{"description":"The engine's design IR for this markup as a JSON object or array serialised to a string, at most 4,000,000 bytes, or null. Carried onto an asset draft so the commit can store it against the campaign; not stored on a live campaign or a template by this call.","type":["string","null"],"example":"{\"version\":1,\"blocks\":[]}"},"idempotencyKey":{"description":"Caller's retry key. A repeat request with the same key and the same fields replays the first response instead of creating a second campaign; the same key with different fields is refused with 409. Omitted, every call creates.","type":["string","null"],"example":"toolu_01MdDJX8YPKg"},"candidateId":{"description":"Id of the brand candidate the markup was styled under, or null. Recorded on the campaign or draft so a first send can commit the candidate into the account's brand kit.","type":["string","null"],"example":"cand_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"externalIdentifier":{"description":"A cohort's label for the asset draft, {cohort_set_id}:{cohort_key} with a lowercase UUID and c1 to c5, used as the draft's external identifier in place of a generated one so the draft can be found by the label. Read only when the markup is saved as an asset draft. Omitted, an identifier is generated.","type":["string","null"],"example":"8f14e45f-ceea-467a-9b36-0c5d7a1e2b3c:c2"}},"type":"object"},"GenerateAutomationInput":{"additionalProperties":false,"properties":{"prompt":{"description":"The whole request in the user's own words: what starts the automation, what it does next, and any emails it sends.","maxLength":20000,"minLength":1,"title":"Prompt","type":"string"},"idempotency_key":{"anyOf":[{"maxLength":200,"minLength":1,"type":"string"},{"type":"null"}],"default":null,"description":"Names one request: the same key returns the same run instead of building twice. Reuse a key only for a run reported lost.","title":"Idempotency Key"},"language":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Language for the automation's emails, only when the user names one outright.","examples":["English","Spanish"],"title":"Language"}},"required":["prompt"],"title":"GenerateAutomationInput","type":"object"},"GenerateDispatchRequest":{"description":"Queue payload for running a campaign generation. CampaignGenerationService::triggerCreation builds it from the body of POST /ai/campaign/generation/generate; the server resolves the stored request, brand kit, summarization, existing campaign and message, and the block configurations from the ids.","required":["external_identifier","source","campaign_name","template","prompt","lang"],"properties":{"external_identifier":{"description":"UUID of the generation request. Must name a stored generation record.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"source":{"description":"Where the request came from; agent and initiatives-detail also file the campaign in that source's folder.","type":"string","example":"agent"},"campaign_name":{"description":"Name for the campaign; PLACEHOLDER until the model names it.","type":"string","example":"October newsletter"},"template":{"description":"Key of the layout to generate on.","type":"string","enum":["promote","welcome","monthly","whatsnew","announcement","letsmove","clean","producthighlight","flashsale","chillvibes","boldheader","colorblocks","fashioneditorial","flashsalecountdown","freetrialcountdown","elegantambiance"],"example":"promote"},"prompt":{"description":"The brief the campaign is written from.","type":"string","example":"Announce our October arrivals to newsletter subscribers"},"lang":{"description":"Language to write in.","type":"string","example":"en"},"brandkit_uuid":{"description":"UUID of the brand kit to style the email with, or null for none.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarization_uuid":{"description":"UUID of the content summarization to draw the copy from, or null for none.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"series_id":{"description":"Id of the automation to create the campaign for, or null for a standalone campaign.","type":["integer","null"],"example":12},"tone":{"description":"Tone of voice for the copy, or null to leave it to the model.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"brandkitRecord":{"description":"The stored brand kit, from brandkit_uuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"summarizationRecord":{"description":"The stored summarization, from summarization_uuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"use_summarization_link":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"subject":{"description":"Subject line to keep. Null lets the model write one.","type":["string","null"],"example":"Your October picks are here"},"pre_header":{"description":"Preheader text to keep. Null lets the model write one.","type":["string","null"],"example":"New arrivals, member offers and more"},"blocks":{"description":"Additional blocks to place in the layout, as selected from the prompt, each with its type and configuration.","type":"array","items":{"required":["type"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"blockConfigurations":{"description":"The blocks as configuration objects, built from blocks. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"labelId":{"description":"Id of the campaign folder (label) to file the campaign under, or null.","type":["integer","null"],"example":3},"campaign_id":{"description":"Id of an existing campaign of the account to write the content into instead of creating one, or null.","type":["integer","null"],"example":4821},"existingCampaign":{"description":"The existing campaign, from campaign_id. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"message_id":{"description":"Id of the existing message to write into when campaign_id is given, or null. It must not already have editor markup.","type":["integer","null"],"example":9134},"existingMessage":{"description":"The existing message, from message_id. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"sessionid":{"description":"Caller's session id, carried through for tracing.","type":["string","null"],"example":"sess_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"cta_url":{"description":"URL for the primary button, or null or blank to use the summarization's URL when one is linked.","type":["string","null"],"example":"https://example.com/october"},"is_asset_draft":{"description":"True to write the result as an asset draft instead of a live campaign. Honoured only when asset-draft creation is enabled for the account.","type":"boolean","example":false},"images":{"description":"Images to place in the email, at most 7, each with its http or https URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image, at most 2048 characters.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}},"external_content":{"description":"Up to 4000 characters of reference text for the model to draw on, or null.","type":["string","null"],"example":"Our October arrivals include the Autumn coat in three colours and the Harvest candle set."}},"type":"object"},"GenerateRequest":{"description":"Worker payload for the followup email generation, dispatched by RequestController::create with the send block it just made.","required":["blockId","prompt","name","outputLang"],"properties":{"blockId":{"description":"Id of the empty send block created by POST /ai/campaigns/followup. Must name a block of type send.","type":"integer","example":912},"prompt":{"description":"What the followup email should say, as given to POST /ai/campaigns/followup.","type":"string","example":"Thank readers who clicked the autumn sale link and offer them free shipping this week"},"name":{"description":"Name of the automation, used as the name of the campaign created in the send block.","type":"string","example":"Campaign Followup for 4821"},"outputLang":{"description":"Language the email is written in.","type":["string","null"],"example":"en"},"tone":{"description":"Voice of the generated email, one of the AI content tones. Any other value falls back to encouraging.","type":"string","example":"friendly"},"block":{"description":"Ignored on input: the server loads the send block named by blockId into it.","type":"object","readOnly":true},"brandkitUuid":{"description":"UUID of the brand kit to style the email with; omitted, none is applied. Must name a stored brand kit when given.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"brandkitRecord":{"description":"Ignored on input: the server loads the brand kit record named by brandkitUuid into it.","type":"object","readOnly":true}},"type":"object"},"GenerateSegmentRequest":{"description":"A natural-language description of the contacts to segment, sent to the Segment On Demand service.","required":["prompt"],"properties":{"prompt":{"description":"What the segment should match, in the user's words. Must not be blank.","type":"string","example":"Contacts tagged VIP who opened a campaign in the last 30 days"},"source":{"description":"Where the request comes from, recorded with the generation for tracing. Read by POST /ai/segmentsV2/generate only, where an omitted or empty value is recorded as segment-ai-builder-source-unknown; POST /ai/segment/generate ignores it.","type":"string","example":"segment-ai-builder"}},"type":"object"},"GeneratedBroadcastResponse":{"description":"A finished broadcast generation request.","required":["source","status","broadcastId"],"properties":{"source":{"description":"Where the request came from: ai_index creates a broadcast, ai_builder and sms_index update one.","type":"string","enum":["ai_index","ai_builder","sms_index"],"example":"ai_index"},"status":{"description":"Always success on this route: in_progress answers 409 and error answers 500.","type":"string","enum":["success"],"example":"success"},"broadcastId":{"description":"ID of the SMS broadcast that was created or updated; null when the record was created without one.","type":["integer","null"],"example":5120}},"type":"object"},"GeneratedImageSaveRequest":{"description":"Which generated image to move from the temporary store into Content Manager.","required":["requestUUID","imageUUID"],"properties":{"requestUUID":{"description":"UUID of the generation request; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"imageUUID":{"description":"UUID of the image under that request; must exist and be completed (not pending, failed or already saved).","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"GeneratedInboxConversationSummary":{"description":"A finished Inbox conversation summary generation. The summary itself is stored on the conversation in the Inbox service, not returned here.","required":["external_identifier","status"],"properties":{"external_identifier":{"description":"Id of the generation, the requestId that update returned.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"status":{"description":"Always success: a generation that is still running answers 409 and one that failed answers 500.","type":"string","enum":["success"],"example":"success"},"error_reason":{"description":"Why the generation failed. Present only on a failed record, which this endpoint does not return as a 200.","type":["string","null"],"example":null}},"type":"object"},"GeneratedInboxReply":{"description":"A finished Inbox reply generation.","required":["source","status","body","conversation_uuid","sender_uuid","sender_type"],"properties":{"source":{"description":"Where the reply was requested from, as sent to generate.","type":"string","example":"inbox_composer"},"status":{"description":"Always success: a generation that is still running answers 409 and one that failed answers 500.","type":"string","enum":["success"],"example":"success"},"body":{"description":"The generated reply.","type":"string","example":"Hi Sam, thanks for reaching out! Your order shipped yesterday and should arrive by Friday."},"conversation_uuid":{"description":"Conversation the reply was generated for, as sent to generate.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"sender_uuid":{"description":"Sender the reply is for, as sent to generate.","type":"string","example":"7d5e2b1a-9c34-4f60-8a71-3b2c1d0e9f88"},"sender_type":{"description":"Type of the sender, as sent to generate.","type":"string","example":"user"}},"type":"object"},"GeneratedTemplatePair":{"description":"The light and dark templates generated from one base template; a mode is null when its job failed or its template could not be read.","required":["light","dark"],"properties":{"light":{"description":"The light-mode template, or null.","oneOf":[{"$ref":"#/components/schemas/GeneratedTemplateRef"},{"type":"null"}]},"dark":{"description":"The dark-mode template, or null.","oneOf":[{"$ref":"#/components/schemas/GeneratedTemplateRef"},{"type":"null"}]}},"type":"object"},"GeneratedTemplateRef":{"description":"A saved email template.","required":["id","name"],"properties":{"id":{"description":"ID of the email template.","type":"integer","example":1842},"name":{"description":"Name of the email template.","type":"string","example":"Welcome (light)"}},"type":"object"},"GenerationContextResponse":{"description":"Compact account context for campaign-generation decisions, limited to the requested categories.","properties":{"recent_campaigns":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecentCampaignSummary"},"type":"array"},{"type":"null"}],"default":null,"description":"Recent campaign summaries, most recently scheduled first. Present only when requested via `include`.","title":"Recent Campaigns"},"audiences":{"anyOf":[{"items":{"$ref":"#/components/schemas/AudienceSummary"},"type":"array"},{"type":"null"}],"default":null,"description":"Contact-list audience summaries. Present only when requested via `include`.","title":"Audiences"},"unavailable":{"default":[],"description":"Categories from `include` that failed to load. Empty when every requested category succeeded.","items":{"type":"string"},"title":"Unavailable","type":"array"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"title":"Campaign Generation Context Result","type":"object"},"GeoAddress":{"type":"object","properties":{"ip4":{"type":"string","description":"The first IPv4 address that resolved to this location, as an unsigned integer in text form. Other addresses that resolve to the same coordinates share this record, so this is not every address seen there.","example":"1123637995"},"country2":{"type":"string","description":"Two-letter ISO 3166-1 country code. Empty when the lookup returned no country.","example":"US"},"country":{"type":"string","description":"Country name in English. Empty when the lookup returned no country.","example":"United States"},"state":{"type":"string","description":"Name of the region, such as a state or province. Empty when the lookup returned none; older locations may hold the legacy region name.","example":"New York"},"city":{"type":"string","description":"City name. Empty when the lookup returned no city.","example":"New York"},"zip":{"type":"string","description":"Postal code. Empty when the lookup returned none.","example":"10001"},"area":{"type":"string","description":"Telephone area code. \"0\" for every location recorded since 2018, because the current lookup does not provide one; older locations may hold a real code.","example":"0"},"lat":{"type":"string","description":"Latitude in decimal degrees, with six decimal places.","example":"40.712800"},"lon":{"type":"string","description":"Longitude in decimal degrees, with six decimal places.","example":"-74.006000"},"tz":{"type":"string","description":"Time zone of the location as an IANA name. Empty when the lookup returned none.","example":"America/New_York"},"tstamp":{"type":["string","null"],"description":"When this location was first recorded.","example":"2023-12-20T14:14:46-06:00"},"links":{"type":"array","description":"Always empty. A location has no related records to link to.","items":{}},"id":{"type":"string","description":"ID of the location.","example":"3"}},"description":"A location that one or more IPv4 addresses resolved to."},"GeoIp":{"type":"object","properties":{"contact":{"type":"string","description":"ID of the contact the address was seen for. \"0\" when that contact was merged into another contact; after an ordinary deletion the entry keeps the deleted contact's id.","example":"49"},"campaignid":{"type":"string","description":"ID of the campaign the address was seen on. \"0\" when it was not seen on a campaign, for example on a form submission.","example":"11"},"messageid":{"type":"string","description":"ID of the campaign message the address was seen on. \"0\" when it was not seen on a campaign message, including form submissions that carry a campaign id.","example":"12"},"geoaddrid":{"type":"string","description":"ID of the location the address resolved to.","example":"2"},"ip4":{"type":"string","description":"The IPv4 address as an unsigned integer in text form.","example":"1123637995"},"tstamp":{"type":["string","null"],"description":"When the address was recorded.","example":"2021-05-12T11:10:06-05:00"},"links":{"type":"object","description":"URLs of the records related to this entry.","properties":{"geoAddress":{"type":"string","description":"URL of the location the address resolved to.","example":"https://:account.api-us1.com/api/3/geoIps/4/geoAddress"}}},"id":{"type":"string","description":"ID of the entry.","example":"4"},"geoAddress":{"type":["string","null"],"description":"ID of the location the address resolved to, the same as geoaddrid. Null when geoaddrid is 0.","example":"2"}},"description":"One IPv4 address recorded for a contact."},"GlobalDataAccount":{"description":"Account-level settings, plan, entitlement and usage values the app reads at start-up","properties":{"account_id":{"description":"The account ID as used by site and event tracking: the database ID plus a fixed offset chosen by its last digit. account_id_old holds the database ID.","type":"integer","example":609474506},"isSuspended":{"description":"True when the account is suspended (its session status is `suspend`).","type":"boolean","example":false},"statuses_count":{"description":"Number of the user's active in-app notifications that are neither clicked nor closed.","type":"integer","example":2},"site_name":{"description":"Site name from the account's site settings; an empty string when there is none.","type":"string","example":"Example Inc."},"serial":{"description":"The installation serial stored in em_backend. The site settings withhold it, so it is read from the database.","type":"string","example":""},"timeformat":{"description":"Time display format, strftime-style; an empty string when not set.","type":"string","example":"%H:%M"},"dateformat":{"description":"Date display format, strftime-style; an empty string when not set.","type":"string","example":"%m/%d/%Y"},"datetimeformat":{"description":"Date and time display format, strftime-style; an empty string when not set.","type":"string","example":"%m/%d/%Y %H:%M"},"geo_ip":{"description":"GeoIP lookup of the caller's IP address.","properties":{"country_code":{"description":"Two-letter country code, or null when the address could not be placed.","type":["string","null"],"example":"US"}},"type":"object"},"plusFields":{"description":"Every plus field (em_plus_field), keyed by its name in camelCase. The value is false when the field is inactive for the account; otherwise the field's definition with originalKey set to the stored name.","type":"object","additionalProperties":true},"showScores":{"description":"True when the account is entitled to contact scoring, is not resold, the user is the primary admin and the admin's branding links are on.","type":"boolean","example":true},"hasPartnerUpgradeUrl":{"description":"True when the account is resold and its partner has a custom upgrade URL turned on, so upgrade clicks are sent to the partner.","type":"boolean","example":false},"ccpaTosConfig":{"description":"The accepted CCPA terms of service for integrations (the config named integrations.accepted_tos.ccpa whose accepted_at is set), in the /configs resource format with accepted_at and rejected_at reduced to their latest value. Null when they were never accepted.","type":["object","null"],"additionalProperties":true},"newExportAvailable":{"description":"True when a contact export finished since the user last opened the exports page.","type":"boolean","example":false},"provisioningJWT":{"description":"An HS256 JWT for the billing provisioning service (audience billing-provisioning, subject admin@<account hostname>, with the account ID and hostname as claims). An empty string when the signing secret is not configured.","type":"string","example":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30."},"isEcommerce":{"description":"Whether the app shows the ecommerce getting-started item: an ecommerce or ecom-core entitlement with the onboarding industry \"E-Commerce / Retail\", or a Shopify, WooCommerce, BigCommerce, Square or Magento connection. Cached for the account for three days.","type":"boolean","example":false},"account":{"description":"The account hostname.","type":"string","example":"example.activehosted.com"},"account_id_old":{"description":"The account's database ID.","type":"integer","example":123456},"acv":{"description":"Annual contract value stored on the account record, as an integer.","type":"integer","example":0},"cname":{"description":"The account's custom domain, or null when it has none.","type":["string","null"],"example":null},"expire":{"description":"Expiry date and time stored on the account record (Y-m-d H:i:s).","type":"string","example":"2027-01-01 00:00:00"},"has_accounts":{"description":"Whether the account is entitled to Accounts (CRM companies), falling back to its plan when it has no entitlement record.","type":"boolean","example":true},"has_landing_pages_react":{"description":"Whether the user's groups may use landing pages (the pg_landing_pages_access permission). Always equal to has_landing_pages_nav.","type":"boolean","example":true},"date_time":{"description":"When the account was created (Y-m-d H:i:s).","type":"string","example":"2024-03-05 14:20:11"},"date_first_login":{"description":"When the account was first logged in to (Y-m-d H:i:s), as stored on the account record.","type":"string","example":"2024-03-05 14:25:40"},"is_account_older_than30_days":{"description":"True when the account was created more than 30 days ago.","type":"boolean","example":true},"is_ac_account":{"description":"True only for ActiveCampaign's own account in this environment.","type":"boolean","example":false},"currency":{"description":"Currency code from the account's localisation settings; USD when none is set.","type":"string","example":"USD"},"user_seat_limit":{"description":"Allowed user seats from the user-seats entitlement: -1 when unlimited, 0 when the account has no such entitlement.","type":"integer","example":3},"domain_verification_required":{"description":"Whether the account must verify its sending domains (account config).","type":"boolean","example":false},"has_landing_pages_nav":{"description":"Whether the user's groups may use landing pages (the pg_landing_pages_access permission). Always equal to has_landing_pages_react.","type":"boolean","example":true},"is_shopify_merchant":{"description":"Whether the account is billed through Shopify (it has a Shopify merchant record).","type":"boolean","example":false},"app_tags":{"description":"The distinct tags of integration marketplace apps, each with the lowest ID that carries it.","type":"array","items":{"properties":{"tag":{"description":"Tag name, HTML-escaped.","type":"string","example":"Ecommerce"},"id":{"description":"Lowest app tag ID with this name, as a string.","type":"string","example":"4"}},"type":"object"}},"has_automations_map":{"description":"Whether the account is entitled to the automations map.","type":"boolean","example":true},"supports_shopify_write":{"description":"False for HIPAA accounts, which may not write to Shopify; true otherwise.","type":"boolean","example":true},"has_ecom_reporting":{"description":"Whether the account has an ecommerce integration connected.","type":"boolean","example":false},"has_win_probability":{"description":"Whether the account is entitled to deal win probability.","type":"boolean","example":false},"version":{"description":"The version the account is on, as stored on the account record; dev in a development environment.","type":"string"},"has_attribution":{"description":"Whether the account may use attribution without upgrading its plan.","type":"boolean","example":true},"has_conversions":{"description":"Always true: conversions are enabled for every account.","type":"boolean","example":true},"has_deals":{"description":"Whether the user may use deals: the account's CRM entitlement combined with the user's CRM seat.","type":"boolean","example":true},"has_campaigns":{"description":"Whether the account is entitled to campaigns.","type":"boolean","example":true},"can_add_lists":{"description":"Whether the user may create lists.","type":"boolean","example":true},"has_lists":{"description":"Whether the user may open lists.","type":"boolean","example":true},"has_custom_objects_schemas":{"description":"Whether the account is entitled to custom objects, or a feature flag forces it on.","type":"boolean","example":false},"has_site_messages":{"description":"Whether the account is entitled to site messages.","type":"boolean","example":true},"has_tasks":{"description":"Whether the account has CRM (deals) features, which tasks follow.","type":"boolean","example":true},"has_deep_data":{"description":"Whether the account may use Deep Data integrations: it is not on Lite, is allow-listed, or is entitled to ecommerce.","type":"boolean","example":true},"has_ecommerce":{"description":"Always equal to has_deep_data.","type":"boolean","example":true},"has_integrations":{"description":"Whether the account has any connection other than non-ecommerce ones.","type":"boolean","example":false},"has_looker_deals_report":{"description":"Whether the account is allow-listed for the Looker deals report (account config).","type":"boolean","example":false},"has_custom_reporting":{"description":"Whether the account is entitled to custom reports.","type":"boolean","example":false},"has_one_to_one_email":{"description":"Whether the account is entitled to one-to-one email.","type":"boolean","example":true},"has_s_s_o":{"description":"Whether the account is entitled to single sign-on.","type":"boolean","example":false},"has_sentiment_analysis":{"description":"Whether the account is entitled to sentiment analysis.","type":"boolean","example":false},"plan_tier":{"description":"The marketing (em) plan tier number; null when the account has no em subscription, as on multi-product plans.","type":["integer","null"],"example":17},"plan_term":{"description":"Billing term of the em plan from the plan table; 0 when there is none.","type":"integer","example":1},"crm_plan_tier":{"description":"The CRM plan tier number, or null when there is none.","type":["integer","null"],"example":null},"crm_seat_limit":{"description":"CRM seats: 0 without CRM, -1 when unlimited.","type":"integer","example":0},"em_seat_limit":{"description":"Marketing seats: 0 without campaigns, -1 when unlimited.","type":"integer","example":25},"is_trial":{"description":"Whether the em plan tier is a trial tier.","type":"boolean","example":false},"is_credit_based":{"description":"Whether the account is on the credit-based em plan.","type":"boolean","example":false},"is_sandbox_account":{"description":"Whether the account is a reseller sandbox account.","type":"boolean","example":false},"is_lite":{"description":"Whether the em plan tier is Lite.","type":"boolean","example":false},"is_small_business":{"description":"Whether the em plan tier is Plus (small business).","type":"boolean","example":true},"is_professional":{"description":"Whether the em plan tier is Professional.","type":"boolean","example":false},"is_enterprise":{"description":"Whether the em plan tier is Enterprise.","type":"boolean","example":false},"is_owned":{"description":"Whether the account has an assigned account representative.","type":"boolean","example":false},"has_seat_checking":{"description":"Whether seat limits are enforced: true unless the account is on a legacy plan tier.","type":"boolean","example":true},"rs":{"description":"Whether the account is resold (it has a reseller ID).","type":"boolean","example":false},"lang":{"description":"The account's language.","type":"string","example":"english"},"notification_email":{"description":"The email address on the account record.","type":"string","example":"owner@example.com"},"affiliate":{"description":"Whether the account is an affiliate account.","type":"boolean","example":false},"enterprise":{"description":"The enterprise flag stored on the account record.","type":"boolean","example":false},"beta":{"description":"The beta flag stored on the account record.","type":"boolean","example":false},"userlimit":{"description":"The usercount value stored on the account record.","type":"integer","example":3},"user_limit_reached":{"description":"True when every user seat is taken and adding a user needs an upgrade.","type":"boolean","example":false},"no_app_tpl_access":{"description":"True when the plan must be upgraded to use app templates.","type":"boolean","example":false},"no_group_access":{"description":"True when the plan must be upgraded to use user groups.","type":"boolean","example":false},"upgrade_branding":{"description":"Always the opposite of has_custom_branding.","type":"boolean","example":true},"has_custom_branding":{"description":"Whether the account is entitled to custom branding.","type":"boolean","example":false},"has_scores":{"description":"Whether the account is entitled to contact scoring.","type":"boolean","example":true},"has_form_branding":{"description":"True for Lite accounts created after 2018-04-16.","type":"boolean","example":false},"has_form_branding_toggle_visible":{"description":"Whether the form branding toggle is shown; for a resold account its reseller decides.","type":"boolean","example":true},"can_use_form_branding_toggle":{"description":"Whether the form branding toggle may be changed.","type":"boolean","example":true},"subcnt":{"description":"Contacts counted against the contact limit.","type":"integer","example":1200},"sublimit":{"description":"The contact limit.","type":"integer","example":2500},"sublimitperc":{"description":"subcnt divided by sublimit (0.48 is 48% used); 0 when the limit is not positive.","type":"number","format":"float","example":0.48},"sublimitleft":{"description":"Contacts left before the limit, never below 0.","type":"integer","example":1300},"close2sublimit":{"description":"True once more than 85% of the contact limit is used.","type":"boolean","example":false},"maillimit":{"description":"Emails the account may send in the current billing period; -1 when unlimited.","type":"integer","example":25000},"mailcnt":{"description":"Emails sent since the billing period started.","type":"integer","example":4200},"maillimitleft":{"description":"maillimit minus mailcnt. Not meaningful when maillimit is -1.","type":"integer","example":20800}},"type":"object"},"GlobalDataAdmin":{"description":"The signed-in user's record merged with the limits, permissions and branding of the user's groups. Besides the properties listed it carries the remaining em_user columns (password and apikey are removed), one p_* or pg_* permission key per group permission (each 1 for the primary admin), the limit_* values of the user's groups, and brand_* keys copied from the branding of the user's first group.","properties":{"id":{"description":"The user ID, as a string.","type":"string","example":"1"},"absid":{"description":"ID of the user's global login, as a string.","type":"string","example":"4567"},"username":{"description":"Login name from the global login record; null when that record is missing.","type":["string","null"],"example":"jdoe"},"first_name":{"description":"First name from the global login record; null when that record is missing.","type":["string","null"],"example":"John"},"last_name":{"description":"Last name from the global login record; null when that record is missing.","type":["string","null"],"example":"Doe"},"email":{"description":"Email address from the global login record; null when that record is missing.","type":["string","null"],"example":"johndoe@example.com"},"fullname":{"description":"First and last name joined by a space; a single space when either is missing.","type":"string","example":"John Doe"},"lang":{"description":"The user's language.","type":"string","example":"english"},"locale":{"description":"Locale code for lang (english is en-US, portuguese - brazil is pt-BR); en when the language has no locale.","type":"string","example":"en-US"},"local_zoneid":{"description":"The user's time zone identifier.","type":"string","example":"America/Chicago"},"t_offset":{"description":"Whole hours of the time zone's current UTC offset, without sign.","type":"integer","example":5},"t_offset_o":{"description":"Sign of the time zone's UTC offset.","type":"string","enum":["+","-"],"example":"-"},"t_offset_min":{"description":"Minutes part of the time zone's UTC offset.","type":"integer","example":0},"groups":{"description":"IDs of the user's groups, keyed by the same ID. Group 3 is the admin group; a guest gets group 1.","type":"object","example":{"3":3},"additionalProperties":{"type":"integer"}},"lists":{"description":"IDs of the lists the user's groups may use, keyed by the same ID. An empty array when they reach no list.","type":"object","example":{"1":"1","4":"4"},"additionalProperties":{"type":"string"}},"accessadmin":{"description":"Always 1.","type":"integer","example":1},"emails_sent":{"description":"Emails the user's group has sent against its group mail limit; 0 for admin-group users and when the groups set no mail limit.","type":"integer","example":0},"send_approved":{"description":"Always true.","type":"boolean","example":true},"emailhash":{"description":"MD5 of the lower-cased email address.","type":"string","example":"fd876f8cd6a58277fc664d47ea10ad19"}},"type":"object","additionalProperties":true},"GlobalDataBranding":{"description":"The account-wide branding settings and the app page template split around the page content","properties":{"id":{"description":"Branding record ID.","type":"string","example":"1"},"groupid":{"description":"Group the branding belongs to; always 3, the account-wide branding.","type":"string","example":"3"},"site_name":{"description":"Site name shown in the app.","type":"string","example":"Example Inc."},"site_logo":{"description":"URL of the large logo.","type":["string","null"],"example":"https://example.com/logo.png"},"site_logo_small":{"description":"URL of the small logo.","type":["string","null"],"example":"https://example.com/logo-small.png"},"header_text":{"description":"1 when a text header is set.","type":"string","example":"0"},"header_text_value":{"description":"The text header.","type":["string","null"],"example":""},"header_html":{"description":"1 when an HTML header is set.","type":"string","example":"0"},"header_html_value":{"description":"The HTML header.","type":["string","null"],"example":""},"footer_text":{"description":"1 when a text footer is set.","type":"string","example":"0"},"footer_text_value":{"description":"The text footer.","type":["string","null"],"example":""},"footer_html":{"description":"1 when an HTML footer is set.","type":"string","example":"0"},"footer_html_value":{"description":"The HTML footer.","type":["string","null"],"example":""},"copyright":{"description":"Copyright display setting, 0 or 1.","type":"string","example":"1"},"version":{"description":"Version display setting, 0 or 1.","type":"string","example":"1"},"license":{"description":"License display setting, 0 or 1.","type":"string","example":"1"},"links":{"description":"Branding links setting, 0 or 1.","type":"string","example":"1"},"demo":{"description":"Demo setting, 0 or 1.","type":"string","example":"1"},"help":{"description":"Help links setting, 0 or 1.","type":"string","example":"1"},"admin_template_htm":{"description":"Custom app page template HTML.","type":["string","null"],"example":null},"admin_template_htm_backup":{"description":"Previous custom app page template HTML.","type":["string","null"],"example":null},"admin_template_css":{"description":"Custom app CSS.","type":["string","null"],"example":null},"admin_template_css_backup":{"description":"Previous custom app CSS.","type":["string","null"],"example":null},"public_template_htm":{"description":"Custom public page template HTML.","type":["string","null"],"example":null},"public_template_css":{"description":"Custom public page CSS.","type":["string","null"],"example":null},"favicon":{"description":"URL of the favicon.","type":["string","null"],"example":null},"zendesk_widget_enabled":{"description":"Whether the Zendesk help widget is enabled, 0 or 1.","type":"string","example":"1"},"created_timestamp":{"description":"When the branding was created.","type":["string","null"],"example":"2024-03-05 14:20:11"},"updated_timestamp":{"description":"When the branding was last updated.","type":["string","null"],"example":"2025-06-01 09:00:00"},"has_header":{"description":"True when the app page template has a %NAV% placeholder, where the app renders its own navigation.","type":"boolean","example":true},"has_footer":{"description":"True when the app page template has a %FOOTER% placeholder, where the app renders its own footer.","type":"boolean","example":true},"content_pre":{"description":"App page template HTML before %NAV%, trimmed; an empty string when the template has no %NAV%.","type":"string","example":""},"content_body":{"description":"App page template HTML between %NAV% and %PAGECONTENT%, trimmed; an empty string when the template has no %NAV%.","type":"string","example":""},"content_post":{"description":"App page template HTML after %PAGECONTENT%, trimmed.","type":"string","example":""}},"type":"object"},"GlobalDataConnection":{"description":"One integration connection in the /connections resource format","properties":{"service":{"description":"Service identifier.","type":"string","example":"shopify"},"externalid":{"description":"The connection's ID in the external service.","type":"string","example":"foo.myshopify.com"},"name":{"description":"Display name of the connection.","type":"string","example":"Foo, Inc."},"isInternal":{"description":"1 for an internal connection, 0 for a third-party one (which must have logoUrl and linkUrl).","type":"string","example":"1"},"connectionType":{"description":"Connection type, for example ecommerce or non_ecommerce.","type":["string","null"],"example":"ecommerce"},"status":{"description":"1 when connected, 0 when in error.","type":"string","example":"1"},"syncStatus":{"description":"1 while a sync runs, 0 when stopped.","type":"string","example":"0"},"sync_request_time":{"description":"When a sync was last requested (ISO 8601).","type":["string","null"],"example":null},"sync_start_time":{"description":"When the last requested sync actually started in Deep Data (ISO 8601).","type":["string","null"],"example":null},"lastSync":{"description":"When the last sync finished (ISO 8601).","type":["string","null"],"example":"2026-10-14T13:09:07-05:00"},"logoUrl":{"description":"URL of the logo, used for third-party connections.","type":"string","example":""},"linkUrl":{"description":"URL that supports the integration.","type":"string","example":""},"credentialExpiration":{"description":"When the stored credentials expire (ISO 8601).","type":["string","null"],"example":null},"cdate":{"description":"When the connection was created (ISO 8601).","type":["string","null"],"example":"2026-02-02T13:09:07-06:00"},"udate":{"description":"When the connection was last updated (ISO 8601).","type":["string","null"],"example":"2026-02-02T13:09:12-06:00"},"disconnectDate":{"description":"When the connection was disconnected (ISO 8601); null while connected.","type":["string","null"],"example":null},"listId":{"description":"ID of the list the connection adds contacts to.","type":["string","null"],"example":"0"},"planTier":{"description":"Plan tier stored for the connection.","type":["string","null"],"example":null},"serviceName":{"description":"Display name of the service; the service identifier when it is not a known service.","type":"string","example":"Shopify"},"links":{"description":"URLs of the related options and customers.","type":"object","example":{"options":"https://example.api-us1.com/api/3/connections/1/options","customers":"https://example.api-us1.com/api/3/connections/1/customers"},"additionalProperties":{"type":"string"}},"id":{"description":"Connection ID.","type":"string","example":"1"}},"type":"object"},"GlobalDataContactPersonalizationTag":{"description":"A contact custom field personalization tag and its label","properties":{"tag":{"description":"The field's tag, wrapped in percent signs.","type":"string","example":"%COMPANY_SIZE%"},"title":{"description":"The translated word for contact and the field title, as in \"Contact: Company size\".","type":"string","example":"Contact: Company size"}},"type":"object"},"GlobalDataErrorResponse":{"description":"Body a globalData action returns when building its response throws. The cause is not returned.","required":["message"],"properties":{"message":{"description":"Always this fixed text.","type":"string","example":"An exception occurred."}},"type":"object"},"GlobalDataPendoAccount":{"description":"The account as Pendo identifies it. When the account has an onboarding record it also carries onboarding_business_contacts, onboarding_business_industry, onboarding_business_location, onboarding_products, onboarding_goals and onboarding_goals_other; for each active BigCommerce, Salesforce, Shopify, Square or WooCommerce connection it carries ecom_<service> with the connection's creation date.","properties":{"id":{"description":"Pendo account ID: account ID and environment type joined by a hyphen.","type":"string","example":"123456-production"},"name":{"description":"The account hostname.","type":"string","example":"example.activehosted.com"},"expire":{"description":"When the account expires.","type":["string","null"],"example":"2027-01-01T00:00:00-06:00"},"account_version":{"description":"The version the account is on, as stored on the account record.","type":"string"},"created_at":{"description":"When the account was created.","type":["string","null"],"example":"2024-03-05T14:20:11-06:00"},"crm_plan_tier":{"description":"The CRM plan tier number, or null.","type":["integer","null"],"example":null},"is_affiliate":{"description":"Whether the account is an affiliate account.","type":"boolean","example":false},"is_reseller":{"description":"Whether the account is resold.","type":"boolean","example":false},"is_trial":{"description":"Whether the em plan tier is a trial tier.","type":"boolean","example":false},"language":{"description":"The account's language.","type":"string","example":"english"},"contact_limit":{"description":"The contact limit stored on the account (em_limit_sub).","type":"integer","example":2500},"mail_sending_limit":{"description":"Emails the account may send in the billing period; -1 when unlimited.","type":"integer","example":25000},"plan_tier":{"description":"Plan tier name: from the billing package's main product when there is one (capitalised, as in \"Plus\"), otherwise the legacy em plan tier description; null when the account has neither.","type":["string","null"],"example":"Plus"},"plan_main_product":{"description":"Code of the billing package's main product; legacy for an em plan; null when there is neither.","type":["string","null"],"example":"marketing"},"plan_cohort":{"description":"The billing package's cohort; legacy for an em plan; null when there is neither.","type":["string","null"],"example":"legacy"},"plan_addons":{"description":"Codes of the billing package's add-on products, sorted; null for an em plan or when there is no plan.","type":["array","null"],"items":{"type":"string"},"example":[]},"plan_tier_number":{"description":"The em plan tier number, or null.","type":["integer","null"],"example":17},"reseller_id":{"description":"Reseller ID; 0 when the account is not resold.","type":"string","example":"0"},"is_shopify_billed":{"description":"Whether the account is billed through Shopify.","type":"boolean","example":false},"approaching_sub_limit":{"description":"True once more than 85% of the contact limit is used.","type":"boolean","example":false},"country_code":{"description":"GeoIP country code of the caller's IP address, or null.","type":["string","null"],"example":"US"},"automations_count":{"description":"Active automations on the account, hidden ones included.","type":"integer","example":4},"list_count":{"description":"Lists on the account.","type":"integer","example":3},"active_contacts":{"description":"Active contacts on the account.","type":"integer","example":1200},"acv":{"description":"Annual contract value stored on the account, as an integer.","type":"integer","example":0}},"type":"object","additionalProperties":true},"GlobalDataPendoConfig":{"description":"What the app passes to the Pendo snippet to identify the visitor and the account","properties":{"visitor":{"$ref":"#/components/schemas/GlobalDataPendoVisitor","description":"The visitor."},"account":{"$ref":"#/components/schemas/GlobalDataPendoAccount","description":"The account."},"apiKey":{"description":"The Pendo API key the snippet is installed with.","type":"string","example":"00000000-0000-0000-0000-000000000000"}},"type":"object"},"GlobalDataPendoVisitor":{"description":"The signed-in user as Pendo identifies them","properties":{"id":{"description":"Pendo visitor ID: user ID, account ID and environment type joined by hyphens.","type":"string","example":"1-123456-production"},"is_primary_admin":{"description":"\"true\" for the primary admin (user 1), \"false\" for anyone else. A string, not a boolean.","type":"string","enum":["true","false"],"example":"true"},"permission_group":{"description":"Title of the user's permission group.","type":"string","example":"Admin"},"user_language":{"description":"The user's language.","type":"string","example":"english"},"user_email":{"description":"The user's email address.","type":"string","example":"johndoe@example.com"},"user_created_at":{"description":"When the user was created; for the primary admin without a creation date, when the account was created.","type":["string","null"],"example":"2024-03-05T14:20:11-06:00"},"last_login":{"description":"When the user last logged in.","type":["string","null"],"example":"2026-10-14T08:12:00-05:00"},"automations_count":{"description":"Active, visible automations the user can see (all of them for admin-group users, otherwise those shared with the user's groups).","type":"integer","example":4},"last_automation_created_date":{"description":"When the user last created an automation that is not hidden.","type":["string","null"],"example":"2026-09-30T10:00:00-05:00"},"last_automation_activated_date":{"description":"When the user last set an automation active.","type":["string","null"],"example":"2026-09-30T10:05:00-05:00"},"last_campaign_created_date":{"description":"When the user last created a campaign, automation emails included.","type":["string","null"],"example":"2026-10-01T09:00:00-05:00"},"last_campaign_sent_date":{"description":"When a campaign the user created was last sent, automation emails included.","type":["string","null"],"example":"2026-10-02T09:00:00-05:00"}},"type":"object"},"GlobalDataPersonalizationTag":{"description":"A personalization tag and its translated label","properties":{"tag":{"description":"The tag as written in content, wrapped in percent signs.","type":"string","example":"%DEAL_TITLE%"},"descript":{"description":"Label shown for the tag, in the user's language. Custom field tags are prefixed with the object name, as in \"Deal: Budget\".","type":"string","example":"Deal Title"}},"type":"object"},"GlobalDataPersonalizationTags":{"description":"Personalization tags by object type. Only the types asked for in filters are present.","properties":{"ecomPersTags":{"description":"Present for ECOMMERCE. The ecommerce tags keyed by short name (total_revenue, total_orders, total_products, last_order_price, last_order_currency, last_order_shipping_method, last_order_product_count, last_product_id, last_product_name, last_product_category). An empty array when the account has no ecommerce integration enabled or is on Lite.","oneOf":[{"type":"object","additionalProperties":{"$ref":"#/components/schemas/GlobalDataPersonalizationTag"}},{"type":"array","items":{"type":"object"},"maxItems":0}]},"dealPersTags":{"description":"Present for DEALS. The standard deal tags followed by one per deal custom field with a personalization tag. Empty when the user may not use deals.","type":"array","items":{"$ref":"#/components/schemas/GlobalDataPersonalizationTag"}},"accountPersTags":{"description":"Present for ACCOUNT. The standard account (company) tags followed by one per account custom field. Empty when the account has no Accounts feature.","type":"array","items":{"$ref":"#/components/schemas/GlobalDataPersonalizationTag"}},"contactPersTags":{"description":"Present for CONTACT. One tag per contact custom field. The standard contact tags (%EMAIL%, %FIRSTNAME% and so on) are not included.","type":"array","items":{"$ref":"#/components/schemas/GlobalDataContactPersonalizationTag"}}},"type":"object"},"GlobalDataUser":{"description":"The signed-in user's stored settings and whether the user is the primary admin","properties":{"id":{"description":"User ID.","type":"string","example":"1"},"absid":{"description":"ID of the user's global login.","type":"string","example":"4567"},"parentid":{"description":"ID of the user who created this user; 0 when none.","type":"string","example":"0"},"approved":{"description":"1 when the user is approved.","type":"string","example":"1"},"username":{"description":"Login name.","type":"string","example":"jdoe"},"first_name":{"description":"First name.","type":"string","example":"John"},"last_name":{"description":"Last name.","type":"string","example":"Doe"},"email":{"description":"Email address.","type":"string","example":"johndoe@example.com"},"phone":{"description":"Phone number.","type":"string","example":""},"signature":{"description":"Email signature.","type":["string","null"],"example":null},"last_login":{"description":"When the user last logged in (Y-m-d H:i:s).","type":["string","null"],"example":"2026-10-14 08:12:00"},"lang":{"description":"The user's language.","type":"string","example":"english"},"default_deals":{"description":"The deals view the user last chose, as JSON with type, id (pipeline), user and status; an empty string when none.","type":"string","example":"{\"type\":\"col\",\"id\":1,\"user\":0,\"status\":0}"},"t_offset":{"description":"Stored UTC offset hours.","type":"string","example":"0"},"t_offset_min":{"description":"Stored UTC offset minutes.","type":"string","example":"0"},"t_offset_o":{"description":"Stored UTC offset sign.","type":"string","enum":["+","-"],"example":"+"},"lists_per_page":{"description":"Lists shown per page.","type":"string","example":"20"},"messages_per_page":{"description":"Messages shown per page.","type":"string","example":"20"},"subscribers_per_page":{"description":"Contacts shown per page.","type":"string","example":"20"},"htmleditor":{"description":"1 when the HTML editor is on.","type":"string","example":"1"},"editorsize_w":{"description":"Editor width.","type":"string","example":"100%"},"editorsize_h":{"description":"Editor height.","type":"string","example":"600px"},"local_zoneid":{"description":"Time zone identifier.","type":"string","example":"America/Chicago"},"local_dst":{"description":"1 when daylight saving time applies.","type":"string","example":"0"},"autoupdate":{"description":"Auto-update interval in seconds.","type":"string","example":"600"},"autosave":{"description":"Auto-save interval in seconds; 0 when off.","type":"string","example":"0"},"sdate":{"description":"Stored sdate value (Y-m-d H:i:s).","type":["string","null"],"example":null},"ldate":{"description":"Stored ldate value (Y-m-d).","type":["string","null"],"example":null},"ltime":{"description":"Stored ltime value (H:i:s).","type":["string","null"],"example":null},"password_updated_utc_timestamp":{"description":"When the password was last changed (UTC).","type":["string","null"],"example":"2026-01-02 10:00:00"},"notify_interval":{"description":"How often notification emails are sent.","type":"string","example":"instant"},"notify_interval_day":{"description":"Day setting for notification emails.","type":"string","example":"0"},"notify_interval_hour":{"description":"Hour setting for notification emails (H:i:s).","type":"string","example":"00:00:00"},"notify_options":{"description":"Stored notification options.","type":["string","null"],"example":null},"cdate":{"description":"When the user was created (Y-m-d H:i:s).","type":["string","null"],"example":"2024-03-05 14:20:11"},"udate":{"description":"When the user was last updated (Y-m-d H:i:s).","type":["string","null"],"example":"2026-10-01 12:00:00"},"mfa_enabled":{"description":"1 when multi-factor authentication is on for the user.","type":"string","example":"0"},"main_admin_group":{"description":"Whether the user is in the admin group (group 3). Always true for the primary admin; false for a user without the p_admin permission.","type":"boolean","example":true},"email_hash":{"description":"MD5 of the email address as stored (not lower-cased).","type":"string","example":"fd876f8cd6a58277fc664d47ea10ad19"},"main_admin":{"description":"Whether the user is the primary admin (user 1).","type":"boolean","example":true}},"type":"object"},"GlobalDataUserJson":{"description":"The signed-in user in the JSON API document format: the user under user, and one array per related resource already loaded on the session user, keyed by its plural name (userGroups, groups, configs). When groups is present and the automations read-only feature is on, every group carries pgAutomationRead, \"1\" or \"0\".","properties":{"user":{"$ref":"#/components/schemas/GlobalDataUserJsonUser","description":"The user."}},"type":"object","additionalProperties":true},"GlobalDataUserJsonUser":{"description":"The signed-in user in the /users resource format","properties":{"username":{"description":"Login name.","type":"string","example":"jdoe"},"firstName":{"description":"First name.","type":"string","example":"John"},"lastName":{"description":"Last name.","type":"string","example":"Doe"},"email":{"description":"Email address.","type":"string","example":"johndoe@example.com"},"phone":{"description":"Phone number.","type":"string","example":""},"signature":{"description":"Email signature.","type":["string","null"],"example":null},"lang":{"description":"The user's language.","type":"string","example":"english"},"localZoneid":{"description":"Time zone identifier.","type":"string","example":"America/Chicago"},"mfaEnabled":{"description":"1 when multi-factor authentication is on for the user.","type":"string","example":"0"},"roles":{"description":"The user's roles as stored (a JSON list), or null when none are set.","type":["string","null"],"example":null},"links":{"description":"URLs of the user's related resources, keyed by relationship: lists, userGroup, dealGroupTotals, dealGroupUsers, configs, dealConnection, seatUser.","type":"object","example":{"lists":"https://example.api-us1.com/api/3/users/1/lists","userGroup":"https://example.api-us1.com/api/3/users/1/userGroup"},"additionalProperties":{"type":"string"}},"id":{"description":"User ID.","type":"string","example":"1"}},"type":"object"},"Goal":{"type":"object","properties":{"id":{"type":"string","description":"ID of the goal.","example":"3"},"seriesid":{"type":"string","description":"ID of the automation that holds the goal. Same value as automation.","example":"12"},"blockid":{"type":"string","description":"ID of the automation step (block) that holds the goal. Same value as automationBlock.","example":"57"},"name":{"type":"string","description":"Name of the goal.","example":"Made a purchase"},"cdate":{"type":["string","null"],"format":"date-time","description":"When the goal was created, as ISO 8601 with a UTC offset. Null when not set.","example":"2026-08-20T10:15:00-05:00"},"dirty_stats":{"type":"string","description":"1 when the goal's statistics need recalculating, otherwise 0.","example":"0"},"links":{"type":"object","additionalProperties":{"type":"string"},"description":"URLs of the goal's related reads: automation, automationBlock and contactGoals."},"automation":{"type":["string","null"],"description":"ID of the automation. Same value as seriesid, but null when seriesid is \"0\".","example":"12"},"automationBlock":{"type":["string","null"],"description":"ID of the automation step. Same value as blockid, but null when blockid is \"0\".","example":"57"}},"description":"A goal in an automation."},"GoalRecommendation":{"description":"The asset (an automation recipe or a campaign template) recommended for one business goal or goal recipe template, and where its selection stands.","required":["assetType","templateId","metadata","goalId","relatedSelection","selectionStatus","used"],"properties":{"assetType":{"description":"Kind of asset recommended.","type":["string","null"],"enum":["automation","campaign"],"example":"automation"},"templateId":{"description":"The selected asset: the automation recipe template hash, or the campaign template. Null until selection picks one.","type":["string","null"]},"metadata":{"description":"Working data for the selection: the matched automation goal key for an automation, or the message prompt for a campaign. Null until selection sets it.","type":["string","null"]},"goalId":{"description":"The business goal ID, or the goal recipe template hash, this recommendation is for.","type":["string","null"],"example":"123"},"relatedSelection":{"description":"Reserved. The current selection flow never sets it, so it is null.","type":["string","null"]},"selectionStatus":{"description":"Where selection stands. done means templateId is the final pick; error means selection failed.","type":["string","null"],"enum":["queued","selecting_related","selecting","personalizing","done","error"],"example":"done"},"used":{"description":"Whether the account has used the recommended asset.","type":["boolean","null"],"example":false},"additionalData":{"description":"Extra data about the recommended asset. For an automation, automationRecipes: the candidate recipes selection chose from. For a campaign, title and description: the personalized campaign copy. Left out when empty.","type":"object","additionalProperties":true}},"type":"object"},"GoalRecommendationResponse":{"description":"A recommendation whose selection is already done.","required":["recommendation"],"properties":{"recommendation":{"$ref":"#/components/schemas/GoalRecommendation"}},"type":"object"},"GoalShowcase":{"type":"object","properties":{"entries":{"type":"integer","description":"Times the goal's automation has been entered."},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":["integer","string"]},"tag":{"type":"string"},"count":{"type":["integer","string"]}}}},"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":["integer","string"]},"name":{"type":"string"},"count":{"type":["integer","string"]}}}},"timespans":{"type":"array","items":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"},"count":{"type":"integer"}}}}}},"GoalStats":{"type":"object","description":"All values are 0 when the automation has not been entered yet.","properties":{"rank":{"type":"integer","description":"1-based rank of this goal by success rate among the goals in its automation."},"goalCount":{"type":"integer","description":"Number of goals in the automation."},"rate":{"type":["string","integer"],"description":"Success rate as a percentage formatted to four decimals, e.g. `25.0000`."},"rateChange":{"type":["number","integer"],"description":"Change in success rate, in percentage points, versus 30 days ago, formatted to four decimals."},"averageTime":{"type":["number","integer"],"description":"Average time to reach the goal, in milliseconds."}}},"GroupTranslationDO":{"type":"object","title":"GroupTranslationDO","description":"Translated condition group","properties":{"operator":{"type":"string","description":"Logical operator for conditions in this group","enum":["and","or"]},"conditions":{"type":"object","description":"Map of condition IDs to their human-readable text","additionalProperties":{"type":"string"}}}},"GroupTypesSyncGroupType":{"description":"A group type: the kind of record its groups hold.","required":["id","label","default_group_id"],"properties":{"id":{"description":"ID of the group type.","type":"integer","example":1},"label":{"description":"What the type groups. Only `em_field` (contact custom fields) is synced; any other label is a no-op. Other labels include `deal_custom_field` and `account_custom_field`.","type":"string","example":"em_field"},"default_group_id":{"description":"ID of the type's default group, which fields missing from every group are added to.","type":"integer","example":1}},"type":"object"},"GroupTypesSyncRequest":{"description":"The group type list a `GET /groupTypes` call produced, as it was queued. Only the first entry is reconciled.","properties":{"groupTypes":{"description":"Group types. Only the first entry is read; when this key is missing nothing is synced.","type":"array","items":{"$ref":"#/components/schemas/GroupTypesSyncGroupType"}}},"type":"object"},"HTTPValidationError":{"title":"HTTPValidationError","type":"object","properties":{"detail":{"title":"Detail","type":"array","items":{"$ref":"#/components/schemas/ValidationError"}}}},"HttpExceptionError":{"description":"One error in an HttpExceptionErrorResponse.","required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":409},"title":{"description":"Short name of the HTTP status.","type":"string","example":"Conflict"},"detail":{"description":"What went wrong. Left out when the action gives no message.","type":"string","example":"No Personalized Goal Recipe found by template hash 3KP9Mla"}},"type":"object"},"HttpExceptionErrorResponse":{"description":"Error body for a request the action refuses with an HTTP error status, such as 404 or 409.","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"$ref":"#/components/schemas/HttpExceptionError"}}},"type":"object"},"IdeasCreateRequest":{"description":"What the Share an idea dialog sends. Who is sharing, and from which account, is taken from the session, never from the body.","required":["description"],"properties":{"kind":{"description":"IDEA for a suggestion, PROBLEM for something that is not working.","type":"string","enum":["IDEA","PROBLEM"],"example":"IDEA"},"title":{"description":"Title of the idea, 3 to 140 characters once trimmed. The app does not send one: when it is left out or null, the Ideas service writes a title from the description. An empty string is refused as too short.","type":["string","null"],"example":"Bulk-edit a custom field"},"description":{"description":"What the user wants, or what is going wrong; trimmed, then at most 20000 characters and not blank.","type":"string","example":"Change a field on 200 contacts at once."},"consentEmail":{"description":"Whether the user agrees to emails about the status of the idea. The app does not send it, so it defaults to true.","type":"boolean","example":true},"includePage":{"description":"Whether to record the page the idea was shared from (see pagePath). The app does not send it, so it defaults to true.","type":"boolean","example":true},"pagePath":{"description":"Path of the app page the user was on, at most 2048 characters. Hosted works out the area of the app from it (Contacts, Automations, ...). Ignored when includePage is false; a value that is not a path starting with / records no page.","type":["string","null"],"example":"/app/contacts/12345"},"viewport":{"description":"Size of the browser viewport, at most 40 characters.","type":["string","null"],"example":"1440x900"},"frontendBuild":{"description":"Identifier of the frontend build the user is running, at most 120 characters. The app sends null.","type":["string","null"],"example":null}},"type":"object"},"IdeasCreatedResponse":{"description":"The idea the Ideas service recorded, as it replied.","properties":{"id":{"description":"ID of the new idea.","type":"string","example":"idea_new"},"status":{"description":"Status of the new idea.","type":"string","example":"NEW"},"statusLabel":{"description":"Display label of the status.","type":"string","example":"Received"},"createdAt":{"description":"When the idea was recorded, ISO 8601 in UTC.","type":"string","example":"2026-09-08T15:00:00.000Z"}},"type":"object"},"IdeasDeletedResponse":{"description":"The idea that was deleted.","properties":{"id":{"description":"ID of the deleted idea.","type":"string","example":"idea_1"},"deletedAt":{"description":"When it was deleted, ISO 8601 in UTC.","type":"string","example":"2026-09-08T16:00:00.000Z"}},"type":"object"},"IdeasErrorResponse":{"description":"An Ideas error.","required":["error"],"properties":{"error":{"description":"What went wrong, in English.","type":"string","example":"Not found"}},"type":"object"},"IdeasFollowRequest":{"description":"Options for following an idea.","properties":{"consentEmail":{"description":"Whether the user agrees to emails about the status of the idea.","type":"boolean","example":true}},"type":"object"},"IdeasFollowResponse":{"description":"The idea's following after the change.","properties":{"followerCount":{"description":"Number of followers now.","type":"integer","example":2},"isFollowing":{"description":"Whether the signed-in user follows the idea now.","type":"boolean","example":true},"team":{"description":"The idea's team after the change, when the Ideas service sends it.","type":"array","items":{"$ref":"#/components/schemas/IdeasTeamMember"}}},"type":"object"},"IdeasIdea":{"description":"An idea or problem someone on the account shared from the app, with the signed-in user's relationship to it. The Ideas service owns these fields; Hosted passes them through and only refreshes the people.","properties":{"id":{"description":"ID of the idea, assigned by the Ideas service. Letters, digits, underscores and hyphens.","type":"string","example":"idea_bulk_edit"},"kind":{"description":"IDEA for a suggestion, PROBLEM for something that is not working.","type":"string","enum":["IDEA","PROBLEM"],"example":"IDEA"},"title":{"description":"Title of the idea. The Ideas service writes one when the person who shared it did not.","type":"string","example":"Bulk-edit a custom field from the contact list"},"description":{"description":"What the person who shared the idea wrote.","type":"string","example":"Let me change the Region field on 200 contacts at once."},"status":{"description":"Where the idea stands. Values the app knows: NEW, REVIEWING, PLANNED, IN_PROGRESS, SHIPPED, EXISTS, DECLINED and SUPPORT.","type":"string","example":"PLANNED"},"statusLabel":{"description":"Display label of the status, from the Ideas service.","type":"string","example":"Planned"},"publicNote":{"description":"A note from ActiveCampaign to the account about the idea, or null.","type":["string","null"],"example":"On the roadmap for early next year."},"submittedBy":{"$ref":"#/components/schemas/IdeasSubmitter","description":"Who shared the idea."},"isMine":{"description":"Whether the signed-in user shared the idea. Only they may delete it.","type":"boolean","example":true},"followerCount":{"description":"Number of followers, from the Ideas service.","type":"integer","example":2},"isFollowing":{"description":"Whether the signed-in user follows the idea.","type":"boolean","example":false},"team":{"description":"Everyone on the account who wants the idea: the person who shared it first, then followers in the order they joined.","type":"array","items":{"$ref":"#/components/schemas/IdeasTeamMember"}},"page":{"description":"The page of the app the idea was shared from, or null when no page was captured.","properties":{"area":{"description":"Label of the app area the page belongs to, derived by Hosted from the path.","type":["string","null"],"example":"Contacts"},"path":{"description":"Path of the page.","type":["string","null"],"example":"/app/contacts"}},"type":["object","null"]},"createdAt":{"description":"When the idea was shared, ISO 8601 in UTC.","type":"string","example":"2026-09-01T14:12:00.000Z"},"updatedAt":{"description":"When the idea last changed, ISO 8601 in UTC.","type":"string","example":"2026-09-04T09:30:00.000Z"}},"type":"object"},"IdeasListResponse":{"description":"The account's ideas.","required":["ideas","userCount"],"properties":{"ideas":{"description":"Every idea shared from the account, newest first, as the Ideas service orders them.","type":"array","items":{"$ref":"#/components/schemas/IdeasIdea"}},"userCount":{"description":"Number of users on the account, at least 1. The app names people on ideas only when there is more than one.","type":"integer","example":3}},"type":"object"},"IdeasMalformedBodyResponse":{"description":"The request body could not be read as a JSON object.","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"HTTP status code as a string, \"400\".","type":"string","example":"400"},"detail":{"description":"Why: \"Request body is empty.\", \"Could not decode request body.\" or that it did not decode to an object.","type":"string","example":"Request body is empty."}},"type":"object"}}},"type":"object"},"IdeasSubmitter":{"description":"Who shared an idea.","properties":{"userId":{"description":"ID of the user who shared the idea.","type":"integer","example":7},"name":{"description":"The user's current first and last name. For someone no longer on the account, or whose name is now empty, the name stored when they shared the idea.","type":"string","example":"Pat Lee"},"avatarHash":{"description":"MD5 hash of the user's login email, lowercased and trimmed, for building a Gravatar URL. Null when the user is no longer on the account or has no email.","type":["string","null"],"example":"2f2d6b1e6a3b3a5c4a4d1e7f9c0b8a21"}},"type":"object"},"IdeasTeamMember":{"description":"Someone on the account who wants an idea: the person who shared it, or a follower.","properties":{"userId":{"description":"ID of the user.","type":"integer","example":8},"name":{"description":"The user's current first and last name. For someone no longer on the account, or whose name is now empty, the name the Ideas service stored.","type":"string","example":"Jo Park"},"isYou":{"description":"Whether this member is the signed-in user.","type":"boolean","example":false},"avatarHash":{"description":"MD5 hash of the user's login email, lowercased and trimmed, for building a Gravatar URL. Null when the user is no longer on the account or has no email.","type":["string","null"],"example":"c3d4a1b2e5f60718293a4b5c6d7e8f90"}},"type":"object"},"IdeasValidationErrorResponse":{"description":"The fields of the request body that were refused.","required":["errors"],"properties":{"errors":{"description":"One error per failed check.","type":"array","items":{"required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed: \"Unexpected type\" for a field of the wrong JSON type, otherwise the message of the constraint, such as \"kind must be IDEA or PROBLEM\", \"Tell us a little more\" for a blank description, or a title length message.","type":"string","example":"Tell us a little more"},"source":{"description":"The field that failed the check.","properties":{"pointer":{"description":"The field, as /data/attributes/<field>.","type":"string","example":"/data/attributes/description"}},"type":"object"}},"type":"object"}}},"type":"object"},"ImageBytesToContentManagerRequest":{"description":"An image to store in Content Manager, sent as JSON because the caller cannot send multipart, and the folder to put it in.","required":["imageBytes","mimeType","name"],"properties":{"imageBytes":{"description":"The image, base64 encoded (strict: no whitespace or invalid characters). Decodes to at most 10 MB.","type":"string","example":"iVBORw0KGgoAAAANSUhEUgAA..."},"mimeType":{"description":"Declared type of the bytes; must match what the bytes really are.","type":"string","enum":["image/png","image/jpeg","image/gif","image/webp"],"example":"image/png"},"name":{"description":"File name to store under, without path separators. Up to 255 characters.","type":"string","example":"harbour-sunset.png"},"altText":{"description":"Alt text to store on the file.","type":"string","example":"A harbour at sunset"},"tags":{"description":"Tags to store on the file.","type":"array","items":{"type":"string"},"example":["sunset","harbour"]},"folder":{"description":"Content Manager folder to store in: ai-generated or stock.","type":"string","enum":["ai-generated","stock"],"example":"ai-generated"}},"type":"object"},"ImageCompiledResponse":{"description":"A generated image, read back from the temporary store.","required":["image"],"properties":{"image":{"description":"The image bytes, base64 encoded.","type":"string","example":"iVBORw0KGgoAAAANSUhEUgAA..."}},"type":"object"},"ImageCreateWorkerRequest":{"description":"The job POST /ai/image/generate queues, one per image: the prompts as already rewritten and the record to write the result to. Sent only by Hosted's own background dispatcher.","required":["prompt","negativePrompt","style","height","width","steps","metadata","requestUuid","imageUuid"],"properties":{"prompt":{"description":"Positive prompt after sanitization.","type":"string","example":"A harbour at sunset, small fishing boats, warm light, photographic"},"negativePrompt":{"description":"Negative prompt after sanitization: what to keep out of the image.","type":"string","example":"text, watermark, blurry"},"style":{"description":"Visual style key.","type":"string","enum":["3d-model","analog-film","anime","cinematic","comic-book","digital-art","enhance","fantasy-art","isometric","line-art","low-poly","modeling-compound","neon-punk","origami","photographic","pixel-art","tile-texture"],"example":"photographic"},"height":{"description":"Height in pixels.","type":"integer","example":1024},"width":{"description":"Width in pixels.","type":"integer","example":1024},"quality":{"description":"Rendering quality passed to the model; auto lets it choose.","type":"string","enum":["low","medium","high","auto"],"example":"low"},"requestUuid":{"description":"UUID of the generation request record; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"imageUuid":{"description":"UUID of the image record under that request; must exist.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"steps":{"description":"Diffusion steps for models that take them.","type":"integer","example":30},"metadata":{"description":"Token counts of the prompt rewrite, stored with the image for reporting.","type":"object","example":{"inputTokens":412,"outputTokens":96},"additionalProperties":true},"numImages":{"description":"Images to ask the model for in this job.","type":"integer","example":1},"traceparent":{"description":"W3C traceparent of the request that queued the job, so the job rejoins its trace; the queue drops the headers.","type":["string","null"],"example":"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}},"type":"object"},"ImageEditCompiledResponse":{"description":"An edited image read back from the temporary store, with the metadata the model wrote for it.","required":["image","mimeType","fileName","altText","tags"],"properties":{"image":{"description":"The image bytes, base64 encoded.","type":"string","example":"iVBORw0KGgoAAAANSUhEUgAA..."},"mimeType":{"description":"MIME type sniffed from the bytes.","type":"string","example":"image/png"},"fileName":{"description":"File name the model proposed; null when none was generated.","type":["string","null"],"example":"sunset-over-harbour.png"},"altText":{"description":"Alt text the model wrote; null when none was generated.","type":["string","null"],"example":"A harbour at sunset with small boats"},"tags":{"description":"Tags the model proposed; empty when none were generated.","type":"array","items":{"type":"string"},"example":["sunset","harbour"]}},"type":"object"},"ImageEditImageStatus":{"description":"One image of an edit request and where it is.","required":["uuid","status","failure_code"],"properties":{"uuid":{"description":"UUID of the edited image.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"status":{"description":"pending while the job runs, complete when the image is ready to compile, failed, or saved once stored in Content Manager.","type":"string","enum":["pending","complete","failed","saved"],"example":"complete"},"failure_code":{"description":"Why the job failed; null unless status is failed.","type":["string","null"],"enum":["SOURCE_FETCH_FAILED","URL_VERIFICATION_FAILED","IMAGE_GENERATION_FAILED","CACHE_FAILED","SAFETY_CHECK_FAILED",null],"example":null}},"type":"object"},"ImageEditRequest":{"description":"What to change and, in edit mode, which image to start from: either a public image address or the UUIDs of an earlier edit result, not both. Create mode takes no source.","required":["prompt"],"properties":{"prompt":{"description":"The change to make, in plain words. Up to 32,000 characters.","type":"string","example":"Replace the sky with a clear night sky full of stars"},"imageUrl":{"description":"Address of the source image. In edit mode, required unless sourceRequestUUID and sourceImageUUID are given; sending both is refused. Must be omitted in create mode.","type":["string","null"],"example":"https://img.example-cdn.net/acct/hero.png"},"sourceRequestUUID":{"description":"UUID of an earlier edit request whose result is the source; edit mode only. Send with sourceImageUUID; the result must still be in the temporary store or the call answers 400.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"sourceImageUUID":{"description":"UUID of the image under sourceRequestUUID.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"size":{"description":"Output size as WIDTHxHEIGHT, or auto. In create mode a size other than auto is normalised to the nearest the model supports.","type":"string","example":"auto"},"quality":{"description":"Rendering quality passed to the model; auto lets it choose.","type":"string","enum":["low","medium","high","auto"],"example":"low"},"mode":{"description":"edit changes the source image; create generates a new image from the prompt alone and must not be sent with imageUrl or source UUIDs.","type":"string","enum":["edit","create"],"example":"edit"}},"type":"object"},"ImageEditSaveRequest":{"description":"Which edited image to move from the temporary store into Content Manager.","required":["requestUUID","imageUUID"],"properties":{"requestUUID":{"description":"UUID of the edit request; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"imageUUID":{"description":"UUID of the image under that request; must exist and be complete (not pending, failed or already saved).","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"ImageEditStartedResponse":{"description":"The edit request was stored and its job queued.","required":["requestUUID"],"properties":{"requestUUID":{"description":"UUID of the edit request; poll GET /ai/image/edit/poll/{requestUUID} with it and pass it to compile and save.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"ImageEditStatusResponse":{"description":"Where an edit request and its image are.","required":["status","images"],"properties":{"status":{"description":"Request record status, moving with the image: pending, complete, failed or saved.","type":"string","enum":["pending","complete","failed","saved"],"example":"pending"},"images":{"description":"The images of the request; an edit request has one.","type":"array","items":{"$ref":"#/components/schemas/ImageEditImageStatus"}}},"type":"object"},"ImageEditWorkerRequest":{"description":"The job POST /ai/image/edit/generate queues: the edit to run and the record to write the result to. Sent only by Hosted's own background dispatcher.","required":["prompt","size","quality","requestUuid","imageUuid"],"properties":{"prompt":{"description":"The change to make.","type":"string","example":"Replace the sky with a clear night sky full of stars"},"imageUrl":{"description":"Address of the source image; null when the source is an earlier edit result.","type":["string","null"],"example":"https://img.example-cdn.net/acct/hero.png"},"size":{"description":"Output size as WIDTHxHEIGHT, or auto.","type":"string","example":"auto"},"quality":{"description":"Rendering quality passed to the model; auto lets it choose.","type":"string","enum":["low","medium","high","auto"],"example":"low"},"requestUuid":{"description":"UUID of the edit request record; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"imageUuid":{"description":"UUID of the image record under that request; must exist.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"sourceRequestUuid":{"description":"UUID of the earlier edit request the source comes from, when it does.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"sourceImageUuid":{"description":"UUID of the image under sourceRequestUuid, when the source is an earlier edit.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"mode":{"description":"edit or create.","type":"string","enum":["edit","create"],"example":"edit"},"traceparent":{"description":"W3C traceparent of the request that queued the job, so the job rejoins its trace; the queue drops the headers.","type":["string","null"],"example":"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}},"type":"object"},"ImageFromBytesRequest":{"description":"An image to store in the AI Generated folder of Content Manager, sent as JSON because the caller cannot send multipart.","required":["imageBytes","mimeType","name"],"properties":{"imageBytes":{"description":"The image, base64 encoded (strict: no whitespace or invalid characters). Decodes to at most 10 MB.","type":"string","example":"iVBORw0KGgoAAAANSUhEUgAA..."},"mimeType":{"description":"Declared type of the bytes; must match what the bytes really are.","type":"string","enum":["image/png","image/jpeg","image/gif","image/webp"],"example":"image/png"},"name":{"description":"File name to store under, without path separators. Up to 255 characters.","type":"string","example":"harbour-sunset.png"},"altText":{"description":"Alt text to store on the file.","type":"string","example":"A harbour at sunset"},"tags":{"description":"Tags to store on the file.","type":"array","items":{"type":"string"},"example":["sunset","harbour"]}},"type":"object"},"ImageGenerateRequest":{"description":"What to generate: the idea, the look and the size.","required":["prompt","style"],"properties":{"prompt":{"description":"What the image should show, in plain words. Rewritten by the model into a positive and a negative prompt before generation.","type":"string","example":"A harbour at sunset with small fishing boats"},"style":{"description":"Visual style key; GET /ai/image/styles lists them with labels.","type":"string","enum":["3d-model","analog-film","anime","cinematic","comic-book","digital-art","enhance","fantasy-art","isometric","line-art","low-poly","modeling-compound","neon-punk","origami","photographic","pixel-art","tile-texture"],"example":"photographic"},"width":{"description":"Width in pixels.","type":["integer","null"],"example":1024},"height":{"description":"Height in pixels.","type":["integer","null"],"example":1024},"quality":{"description":"Rendering quality passed to the model; auto lets it choose.","type":"string","enum":["low","medium","high","auto"],"example":"low"},"brandkitUuid":{"description":"UUID of a brand kit whose colours and voice steer the prompt rewrite; must be a stored brand kit. Omitted, no brand kit is used.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"ImageGenerationConsumptionResponse":{"description":"How much of its monthly image generation allowance the account has used.","required":["limit","consumed"],"properties":{"limit":{"description":"Monthly allowance: generation requests on the legacy entitlement, credits on the advanced AI allowance.","type":"integer","example":100},"consumed":{"description":"Used this month, in the same unit as limit. A whole number on the legacy entitlement; may be fractional on the advanced AI allowance.","type":"number","example":42}},"type":"object"},"ImageGenerationImageStatus":{"description":"One image of a generation request and where it is.","required":["uuid","status"],"properties":{"uuid":{"description":"UUID of the image.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"status":{"description":"Image record status: 1 pending, 2 completed (ready to compile), 3 failed, 4 used (already saved to Content Manager).","type":"integer","enum":[1,2,3,4],"example":2}},"type":"object"},"ImageGenerationStartedResponse":{"description":"The generation request was accepted and its per-image jobs queued.","required":["uuid"],"properties":{"uuid":{"description":"UUID of the generation request; poll GET /ai/image/poll/{requestUUID} with it and pass it to compile and save.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"ImageGenerationStatusResponse":{"description":"Where a generation request and each of its images are.","required":["status","images"],"properties":{"status":{"description":"Request record status: 1 pending (an image is still generating), 2 completed (every image finished or failed), 3 failed, 4 used.","type":"integer","enum":[1,2,3,4],"example":1},"images":{"description":"One entry per image of the request.","type":"array","items":{"$ref":"#/components/schemas/ImageGenerationImageStatus"}}},"type":"object"},"ImageMetadataProcessedResponse":{"description":"The run finished. A run that failed to write metadata also answers this: the outcome is on the run's stored record, and the queue only redelivers non-2xx answers.","required":["success"],"properties":{"success":{"description":"Always true.","type":"boolean","enum":[true],"example":true}},"type":"object"},"ImageMetadataSkippedResponse":{"description":"Nothing was done: the account does not have AI image metadata generation turned on. Answered with 200 so the queue does not redeliver.","required":["status","reason"],"properties":{"status":{"description":"Always skipped.","type":"string","enum":["skipped"],"example":"skipped"},"reason":{"description":"Always feature_disabled.","type":"string","enum":["feature_disabled"],"example":"feature_disabled"}},"type":"object"},"ImageMetadataWorkerRequest":{"description":"The job the content API queues when a Content Manager image is created or updated without alt text or tags. Sent only by the queue, not by clients.","required":["fileId"],"properties":{"fileId":{"description":"Content Manager file ID of the image.","type":"integer","example":48213},"imageUrl":{"description":"Address of the image, when the message carried one; the file is looked up otherwise.","type":["string","null"],"example":"https://img.example-cdn.net/acct/hero.jpg"}},"type":"object"},"ImageSavedResponse":{"description":"The image as stored in Content Manager.","required":["imageUrl","imageId"],"properties":{"imageUrl":{"description":"CDN address of the stored file.","type":"string","example":"https://img.example-cdn.net/acct/ai-generated/sunset-7c2e4b1a.png"},"imageId":{"description":"Content Manager file ID.","type":"integer","example":48213}},"type":"object"},"ImageScrapeRequest":{"description":"The page to collect image addresses from.","required":["url"],"properties":{"url":{"description":"Address of the page to scrape.","type":"string","example":"https://www.example.com/"}},"type":"object"},"ImageScrapeResponse":{"description":"The image addresses found on a page that can be imported.","required":["images","stats"],"properties":{"images":{"description":"Absolute https addresses of the images that fetched as valid images, de-duplicated. Empty when the page had none.","type":"array","items":{"type":"string"},"example":["https://www.example.com/images/hero.jpg"]},"stats":{"$ref":"#/components/schemas/ImageScrapeStats","description":"Counts of what was found and dropped."}},"type":"object"},"ImageScrapeStats":{"description":"How many image addresses the page had and how many survived the checks.","required":["total","valid","rejected"],"properties":{"total":{"description":"Image addresses found on the page before any check.","type":"integer","example":24},"valid":{"description":"Addresses answered in images.","type":"integer","example":9},"rejected":{"description":"Addresses dropped: not a string, not https, pointing at a private network, or not fetching as a usable image.","type":"integer","example":15}},"type":"object"},"ImageStyle":{"description":"One style the generator accepts.","required":["key","label"],"properties":{"key":{"description":"Style key to send as style on the generate request.","type":"string","enum":["3d-model","analog-film","anime","cinematic","comic-book","digital-art","enhance","fantasy-art","isometric","line-art","low-poly","modeling-compound","neon-punk","origami","photographic","pixel-art","tile-texture"],"example":"photographic"},"label":{"description":"Display name in the account's language.","type":"string","example":"Photographic"}},"type":"object"},"ImageStylesResponse":{"description":"The styles the generator accepts.","required":["styles"],"properties":{"styles":{"description":"Every accepted style, in catalogue order.","type":"array","items":{"$ref":"#/components/schemas/ImageStyle"}}},"type":"object"},"ImageWorkerResponse":{"description":"Outcome of one background image job. Answered with 201 when the image was produced and 200 when it failed; the failure is recorded on the image record for the poll to report.","required":["requestUUID","imageUUID","success"],"properties":{"requestUUID":{"description":"UUID of the request the job belongs to.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"imageUUID":{"description":"UUID of the image the job produced or failed to produce.","type":"string","example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"success":{"description":"True when the image was produced (status 201), false when the model call failed (status 200).","type":"boolean","example":true}},"type":"object"},"ImportAIUploadRequest":{"description":"Where to read the file to import from.","required":["bucket","key","filename"],"properties":{"bucket":{"description":"S3 bucket the file is in: a bucket the AI agents store user files in, which Hosted can read.","type":"string","example":"my-source-bucket"},"key":{"description":"S3 key of the file in that bucket.","type":"string","example":"uploads/contacts-2024-01-15.xlsx"},"filename":{"description":"Name of the file as the user uploaded it, which decides how it is read: `.csv`, `.xlsx`, `.xls` or `.xlsm`. Must not be blank.","type":"string","example":"contacts-2024-01-15.xlsx"},"url":{"description":"URL of the page the user started the import from. Only its path and query string are kept, as the settings' `url`.","type":["string","null"],"example":"https://example.activehosted.com/app/contacts/import"}},"type":"object"},"ImportExecutionRequest":{"description":"The settings to import with.","required":["settings"],"properties":{"settings":{"$ref":"#/components/schemas/ImportSettings","description":"The complete settings, as GET /importsettings/{id} returns them with any changes made. They are validated, used for the import and stored over the saved settings."}},"type":"object"},"ImportExecutionResponse":{"description":"The outcome of a request to start an import. `processId`, `filename` and `totalContacts` are present only when the import started.","required":["success","message"],"properties":{"success":{"description":"True when the import started.","type":"boolean","example":true},"message":{"description":"What happened, for display.","type":"string","example":"The import process has been initiated."},"processId":{"description":"ID of the import process. Pass it to GET /import/status/{processId} to follow the import.","type":"integer","example":12345},"filename":{"description":"Name of the file as the user uploaded it (the settings' `displayFilename`).","type":"string","example":"contacts-2024-01-15.xlsx"},"totalContacts":{"description":"Number of data rows the import will process (the settings' `totalRows`). Left out when the file has none.","type":"integer","example":1250}},"type":"object"},"ImportInitiativeRequest":{"description":"The recipe template to import a business goal from, and where the import came from.","required":["template","source"],"properties":{"source":{"description":"How the goal is being created. prepopulated is set by the automatic setup of a new account; it also makes the goal a favorite on the Overview page and skips the import when a goal already exists for the recipe.","type":"string","enum":["manual","recipe","ai_generated","imported","prepopulated"],"example":"recipe"},"template":{"description":"Hash of the recipe template to import, as returned in the hash field of each recipe from GET /ai/initiatives/recipes. Its personalization must be done.","type":"string","example":"3KP9Mla"}},"type":"object"},"ImportMappingRequest":{"description":"The settings to analyse.","required":["importSettingsId"],"properties":{"importSettingsId":{"description":"ID of the import settings, as the upload returned it in `fileMetadata.importSettingsId`.","type":"string","example":"550e8400-e29b-41d4-a716-446655440000"}},"type":"object"},"ImportSample":{"description":"One row of the file as the import would apply it: its mapped field values after formatting, the tags and the lists the contact would get. Every list is empty when the file has no data rows.","required":["fields","tags","lists"],"properties":{"fields":{"description":"One entry per column mapped to a field other than `tags`, with the row's value after formatting.","type":"array","items":{"$ref":"#/components/schemas/ImportSampleField"}},"tags":{"description":"Tags the contact would get: those in a column mapped to `tags`, then the settings' `extraTags`, without duplicates. Extra tags are listed whether or not they are active.","type":"array","items":{"$ref":"#/components/schemas/ImportSampleTag"}},"lists":{"description":"The settings' `lists`, whether or not they are active.","type":"array","items":{"$ref":"#/components/schemas/ImportSampleList"}}},"type":"object"},"ImportSampleField":{"description":"A field value of the sample row.","required":["id","name","value","category","type","exists"],"properties":{"id":{"description":"The contact column name for a standard field, the custom field's ID for a custom field, or null for a field the import will create.","type":["string","null"],"example":"email"},"name":{"description":"Display name of the field.","type":"string","example":"Email"},"value":{"description":"The row's value for the field after the mapping's formatting.","type":"string","example":"john.doe@example.com"},"category":{"description":"`standard`, `customField` or `new`, as in the mapping.","type":"string","example":"standard"},"type":{"description":"Data type of the field, as in the mapping.","type":"string","example":"text"},"exists":{"description":"Whether the field exists already.","type":"boolean","example":true}},"type":"object"},"ImportSampleList":{"description":"A list the sample contact would be added to, removed from or excluded from.","required":["id","name","aiMapped","exists"],"properties":{"id":{"description":"ID of the list, or null for a list the import will create.","type":["integer","null"],"example":123},"name":{"description":"Name of the list.","type":"string","example":"Newsletter Subscribers"},"aiMapped":{"description":"True when AI analysis suggested the list.","type":"boolean","example":true},"exists":{"description":"Whether the list exists already.","type":"boolean","example":true}},"type":"object"},"ImportSampleTag":{"description":"A tag the sample contact would get.","required":["id","tag","aiMapped","exists"],"properties":{"id":{"description":"ID of the tag, or null for a tag that does not exist yet. Always null for a tag read from the row.","type":["integer","null"],"example":7},"tag":{"description":"The tag.","type":"string","example":"VIP"},"aiMapped":{"description":"True when AI analysis suggested the tag; false for a tag read from the row.","type":"boolean","example":false},"exists":{"description":"Whether the tag exists already. Always false for a tag read from the row.","type":"boolean","example":false}},"type":"object"},"ImportSettings":{"description":"The settings of one contact import while it is prepared: the uploaded file, how its columns map to contact fields, the lists and tags every contact gets, the import options and where the import is in its lifecycle. A response carries every key. A request must carry the required keys; the others keep their defaults.","required":["id","displayFilename","savedFilename","mappings","lists","extraTags","source","account","state","options","userId"],"properties":{"id":{"description":"ID of the settings, a UUID generated on upload. GET and PUT /importsettings/{id} and POST /import/execute address the stored settings by it.","type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"displayFilename":{"description":"Name of the file as the user uploaded it. POST /import/execute answers with it as `filename`.","type":"string","example":"contacts-2024-01-15.xlsx"},"savedFilename":{"description":"Name the uploaded file, converted to CSV, is stored under in the account's import storage: `{id}-original.csv`. PUT keeps the stored value.","type":"string","example":"550e8400-e29b-41d4-a716-446655440000-original.csv"},"mappings":{"description":"One entry per CSV column: the contact field the column is imported into, or none to skip it.","type":"array","items":{"$ref":"#/components/schemas/ImportSettingsMapping"}},"lists":{"description":"Lists every imported contact is subscribed to, unsubscribed from or excluded from, as `options.contactStatus` says. Only entries with `active` true are applied; an entry with no `id` is created as a new list when the import runs.","type":"array","items":{"$ref":"#/components/schemas/ImportSettingsList"}},"extraTags":{"description":"Tags added to every imported contact. Only entries with `active` true are applied; an entry with no `id` is a tag that does not exist yet.","type":"array","items":{"$ref":"#/components/schemas/ImportSettingsTag"}},"source":{"description":"Platform the file appears to have been exported from, detected from its contents when it is analysed; `unknown` when none matched. PUT keeps the stored value.","type":"string","enum":["Mailchimp","HubSpot","Constant Contact","Klaviyo","Keap","unknown"],"example":"unknown"},"account":{"$ref":"#/components/schemas/ImportSettingsAccount","description":"What the account already had when the file was uploaded. PUT keeps the stored value."},"state":{"$ref":"#/components/schemas/ImportSettingsState","description":"Where the import is in its lifecycle, and the import page the user is on."},"options":{"$ref":"#/components/schemas/ImportSettingsOptions","description":"How the import treats contacts when it runs."},"sessionId":{"description":"ID the AI analysis of this import is traced under, generated on upload. PUT keeps the stored value.","type":["string","null"],"example":"bd16c553-b78f-4992-b634-ccebaeb7194c"},"url":{"description":"Path, and query string if any, of the page the import was started from, or null when the upload named none. PUT keeps the stored value.","type":["string","null"],"example":"/app/contacts/import"},"totalRows":{"description":"Number of data rows in the file, not counting the header row. PUT keeps the stored value.","type":"integer","example":1250},"userId":{"description":"ID of the user who uploaded the file. GET and PUT /importsettings/{id} answer only that user; PUT keeps the stored value.","type":"integer","example":1},"processId":{"description":"ID of the import process once POST /import/execute has started it, else null. Pass it to GET /import/status/{processId}. PUT keeps the stored value.","type":["integer","null"],"example":12345},"generatedBy":{"description":"What produces the mappings: `llm` when the upload asked for AI analysis, `application` when it opted out and fuzzy matching produced them, `pending` only on settings neither has set. Read `state.process`, not this, to tell when analysis has finished. PUT keeps the stored value.","type":"string","enum":["pending","llm","application"],"example":"llm"},"listIds":{"description":"IDs of existing lists chosen when the file was uploaded (`listIds[]` on POST /import/upload). With AI analysis, `lists` is filled with these lists instead of suggestions. They are not applied by themselves: the import applies `lists`.","type":"array","items":{"type":"integer"},"example":[3,17]}},"type":"object"},"ImportSettingsAccount":{"description":"What the account already had when the file was uploaded.","required":["hasAutomations","hasWebhooks","hasContacts"],"properties":{"hasAutomations":{"description":"Whether the account had any automations.","type":"boolean","example":true},"hasWebhooks":{"description":"Whether the account had any active webhooks.","type":"boolean","example":false},"hasContacts":{"description":"Whether the account had any contacts besides the default ones.","type":"boolean","example":true}},"type":"object"},"ImportSettingsColumn":{"description":"A column of the uploaded CSV.","required":["name","id"],"properties":{"name":{"description":"The column header.","type":"string","example":"Email Address"},"id":{"description":"Zero-based position of the column in the file.","type":"integer","example":0}},"type":"object"},"ImportSettingsField":{"description":"The contact field a column is imported into.","required":["name","category"],"properties":{"exists":{"description":"True when `id` is set, so the field exists already. Computed; a request does not set it.","type":"boolean","readOnly":true,"example":true},"name":{"description":"Display name of the field: the standard field's name, the custom field's title, or the title of the custom field the import will create.","type":"string","example":"Email"},"category":{"description":"`standard` for a built-in contact field, `customField` for an existing custom field, `new` for a custom field the import creates before it runs.","type":"string","example":"standard"},"type":{"description":"Data type of the field: `text` for standard fields, the custom field's type otherwise. A new custom field is created with this type.","type":["string","null"],"example":"text"},"id":{"description":"The contact column name for a standard field (`tags` imports the column as tags separated by `||`), the custom field's ID for a custom field, or null for a field that does not exist yet.","type":["string","null"],"example":"email"}},"type":"object"},"ImportSettingsFormat":{"description":"One formatting step applied to a column's values.","required":["type"],"properties":{"type":{"description":"`e164` formats a phone number as E.164. `remove_4byte_characters` removes emoji and trims the value. `format_to_pipes` splits the value on commas, pipes and semicolons and joins the parts with `||`, the separator a multi-value field is imported from. `remove_double_quotes` reads the value as a CSV line, so quoted items lose their quotes, and joins the items with `||`.","type":"string","enum":["e164","remove_4byte_characters","format_to_pipes","remove_double_quotes"],"example":"e164"}},"type":"object"},"ImportSettingsList":{"description":"A list every imported contact is added to, removed from or excluded from.","required":["name","channel","aiMapped"],"properties":{"exists":{"description":"True when `id` is set, so the list exists already. Computed; a request does not set it.","type":"boolean","readOnly":true,"example":true},"id":{"description":"ID of the list, or null for a list the import creates when it runs.","type":["integer","null"],"example":123},"name":{"description":"Name of the list.","type":"string","example":"Newsletter Subscribers"},"channel":{"description":"Channel of the list, `email` or `sms`.","type":"string","example":"email"},"aiMapped":{"description":"True when AI analysis suggested the list.","type":"boolean","example":true},"description":{"description":"Why AI analysis suggested the list; empty otherwise.","type":"string","example":"Suggested based on CSV data"},"active":{"description":"Whether the import applies the list. An entry with `active` false is kept as a suggestion only.","type":"boolean","example":true}},"type":"object"},"ImportSettingsMapping":{"description":"How one CSV column is imported.","required":["column","sampleData","formatting","aiMapped"],"properties":{"column":{"$ref":"#/components/schemas/ImportSettingsColumn","description":"The CSV column."},"field":{"description":"The contact field the column is imported into, or null to skip the column.","oneOf":[{"$ref":"#/components/schemas/ImportSettingsField"},{"type":"null"}]},"sampleData":{"description":"A value from the column as it is in the file, before formatting, for the user to recognise the column by.","type":"string","example":"john.doe@example.com"},"formatting":{"description":"Formatting applied to the column's values before they are imported, in order.","type":"array","items":{"$ref":"#/components/schemas/ImportSettingsFormat"}},"aiMapped":{"description":"True when AI analysis chose the field; false when fuzzy matching did.","type":"boolean","example":true}},"type":"object"},"ImportSettingsOptions":{"description":"How an import treats contacts when it runs.","required":["contactStatus","updateExisting","webhooks","triggerAutomations","createFieldOptions"],"properties":{"contactStatus":{"description":"What the import does with each contact on the lists in `lists`: `subscribe`, `unsubscribe` or `exclude`.","type":"string","enum":["subscribe","unsubscribe","exclude"],"example":"subscribe"},"updateExisting":{"description":"When true, contacts that already exist are updated with the file's values.","type":"boolean","example":false},"webhooks":{"description":"Which webhooks the import sends: `all` sends every webhook, list subscription webhooks included; `none` sends none; `contact` sends contact, custom field and tag webhooks but not list subscription webhooks.","type":"string","enum":["all","none","contact"],"example":"none"},"triggerAutomations":{"description":"Whether imported contacts can start automations.","type":"boolean","example":false},"createFieldOptions":{"description":"Whether custom field values that match no existing option of a dropdown, list box, radio or checkbox field are added to it as new options.","type":"boolean","example":true}},"type":"object"},"ImportSettingsState":{"description":"Where an import is in its lifecycle.","required":["currentPage","process","tags","lists","fields"],"properties":{"currentPage":{"description":"The import page the user is on, as the app names it.","type":"string","example":"mapping"},"process":{"description":"`pending` until analysis starts, `analyzing` while it runs, `analyzed` when the mappings are ready, `submitting` while POST /import/execute claims the import, `submitted` once the import has started. Only `analyzed` settings can be executed; send back the value you read.","type":"string","enum":["pending","analyzing","analyzed","submitting","submitted"],"example":"analyzed"},"tags":{"description":"Lock state of the tags section. Reserved: nothing reads it yet.","type":"string","enum":["locked","unlocked"],"example":"unlocked"},"lists":{"description":"Lock state of the lists section. Reserved: nothing reads it yet.","type":"string","enum":["locked","unlocked"],"example":"unlocked"},"fields":{"description":"Lock state of the fields section. Reserved: nothing reads it yet.","type":"string","enum":["locked","unlocked"],"example":"unlocked"}},"type":"object"},"ImportSettingsTag":{"description":"A tag added to every imported contact.","required":["tag","aiMapped"],"properties":{"exists":{"description":"True when `id` is set, so the tag exists already. Computed; a request does not set it.","type":"boolean","readOnly":true,"example":false},"id":{"description":"ID of the tag, or null for a tag that does not exist yet.","type":["integer","null"],"example":7},"tag":{"description":"The tag.","type":"string","example":"Imported 2024-01-15"},"aiMapped":{"description":"True when AI analysis suggested the tag.","type":"boolean","example":false},"description":{"description":"Why AI analysis suggested the tag; empty otherwise.","type":"string","example":""},"active":{"description":"Whether the import applies the tag. Left out, it is false for a tag AI analysis suggested, so a suggestion has to be opted into, and true otherwise. Always present in a response.","type":"boolean","example":true}},"type":"object"},"ImportSettingsUpdateRequest":{"description":"The settings to store.","required":["settings"],"properties":{"settings":{"$ref":"#/components/schemas/ImportSettings","description":"The complete settings, as GET /importsettings/{id} returns them with any changes made. `id`, `savedFilename`, `sessionId`, `totalRows`, `source`, `account`, `url`, `processId`, `userId` and `generatedBy` keep their stored values whatever is sent; every other key replaces what is stored."}},"type":"object"},"ImportShareRequest":{"description":"The share link of the template to import.","required":["url"],"properties":{"url":{"description":"Share link of the template, as `POST /templates/{templateId}/share` returns it: `http://<share host>/<hash>`. A bare hash is refused, and the host must be the share host of this environment.","type":"string","example":"http://tplshare.com/aB3dE5g"}},"type":"object"},"ImportStatusResponse":{"description":"Progress of one background process, read from its process record.","required":["id","status","totalRows","processedRows","created"],"properties":{"id":{"description":"ID of the process.","type":"integer","example":12345},"status":{"description":"`finished` once the process has completed as many rows as it has, and has more than none; `processing` otherwise, including a process that has not counted its rows yet.","type":"string","enum":["finished","processing"],"example":"processing"},"totalRows":{"description":"Number of rows the process has to complete.","type":"integer","example":1250},"processedRows":{"description":"Number of rows the process has completed so far.","type":"integer","example":750},"created":{"description":"When the process was created, as `YYYY-MM-DD HH:MM:SS` in the account's database time.","type":"string","example":"2024-01-15 10:30:00"}},"type":"object"},"InboxConversationSummaryGenerateDispatchRequest":{"description":"The stored summary generation to run and what to generate it from. Sent only by Hosted's own background dispatcher, never by a client.","required":["conversation_id","external_identifier","messages"],"properties":{"conversation_id":{"description":"UUID of the Inbox conversation whose summary is updated.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"external_identifier":{"description":"Id of the stored generation, the requestId that update returned.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"previous_summary":{"description":"The summary to update. Leave it out for a conversation that has none.","type":["string","null"],"example":"The customer asked about order 1042."},"messages":{"description":"The messages to fold into the summary, at least one, each as \"SenderName : message content\".","type":"array","items":{"type":"string"},"minItems":1,"example":["Sam : Where is my order?","Agent : It shipped yesterday."]}},"type":"object"},"InboxConversationSummaryGenerateRequest":{"description":"The conversation whose summary to update and the messages to fold into it.","required":["conversation_id","messages"],"properties":{"conversation_id":{"description":"UUID of the Inbox conversation whose summary is updated.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"previous_summary":{"description":"The summary to update. Leave it out for a conversation that has none.","type":["string","null"],"example":"The customer asked about order 1042."},"messages":{"description":"The messages to fold into the summary, at least one, each as \"SenderName : message content\".","type":"array","items":{"type":"string"},"minItems":1,"example":["Sam : Where is my order?","Agent : It shipped yesterday."]}},"type":"object"},"InboxGenerationRequestedResponse":{"description":"The id of a generation that was queued, used to poll for its result.","required":["requestId"],"properties":{"requestId":{"description":"Id of the stored generation record. Pass it to the matching poll endpoint.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}},"type":"object"},"InboxReplyDispatchedResponse":{"description":"The reply was generated and stored.","required":["status","message"],"properties":{"status":{"description":"Always success.","type":"string","enum":["success"],"example":"success"},"message":{"description":"Always the same text.","type":"string","enum":["Inbox created successfully"],"example":"Inbox created successfully"}},"type":"object"},"InboxReplyGenerateDispatchRequest":{"description":"The stored reply generation to run and what to generate it from. Sent only by Hosted's own background dispatcher, never by a client.","required":["external_identifier","source","prompt","tone","last_message","current_history"],"properties":{"external_identifier":{"description":"Id of the stored generation, the requestId that generate returned.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"source":{"description":"Where the reply was requested from.","type":"string","example":"inbox_composer"},"prompt":{"description":"What the user wants the reply to say or do.","type":"string","example":"Tell them the order ships tomorrow"},"tone":{"description":"Tone of voice of the reply.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"last_message":{"description":"The conversation's last message, which the reply answers.","type":"string","example":"Where is my order?"},"summary":{"description":"Summary of the conversation so far.","type":"string","example":"The customer asked about order 1042."},"faq":{"description":"The account's Inbox FAQ the reply may draw on.","type":"string","example":"Orders ship within 2 business days."},"role":{"description":"The part the AI plays when writing the reply.","type":"string","default":"support_agent","enum":["copywriter","support_agent","salesperson","front_desk_greeter"],"example":"support_agent"},"brandkit_uuid":{"description":"UUID of the brand kit whose voice the reply follows.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"website_urls":{"description":"Website pages the reply may draw on, keyed by the id of their stored summary record. A page whose record is missing or not yet successful is left out.","type":"object","example":{"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11":"https://example.com/shipping"},"additionalProperties":{"type":"string"}},"current_history":{"description":"The conversation's recent messages, oldest first.","type":"array","items":{"type":"string"},"example":["Where is my order?"]}},"type":"object"},"InboxReplyGenerateRequest":{"description":"The reply to generate for a conversation. Hosted reads the conversation itself, so the body carries only the prompt and who the reply is for.","required":["prompt","source","tone","conversationUuid","senderUuid","senderType"],"properties":{"source":{"description":"Where the reply is requested from.","type":"string","example":"inbox_composer"},"prompt":{"description":"What the user wants the reply to say or do.","type":"string","example":"Tell them the order ships tomorrow"},"tone":{"description":"Tone of voice of the reply.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"conversationUuid":{"description":"UUID of the Inbox conversation to reply in. Its last message, summary, history and the account's Inbox settings are read from the Inbox service.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"senderUuid":{"description":"UUID of the sender the reply is for. Returned unchanged when the generation is polled.","type":"string","example":"7d5e2b1a-9c34-4f60-8a71-3b2c1d0e9f88"},"senderType":{"description":"Type of that sender. Returned unchanged when the generation is polled.","type":"string","example":"user"}},"type":"object"},"InboxSummaryDispatchedResponse":{"description":"The summary was generated and saved on the conversation.","required":["status","message"],"properties":{"status":{"description":"Always ok.","type":"string","enum":["ok"],"example":"ok"},"message":{"description":"Always the same text.","type":"string","enum":["Conversation summary updated successfully"],"example":"Conversation summary updated successfully"}},"type":"object"},"IndustriesResponse":{"description":"The industries a brand kit can be assigned to.","required":["industries"],"properties":{"industries":{"description":"Every industry, in catalogue order.","type":"array","items":{"$ref":"#/components/schemas/Industry"}}},"type":"object"},"Industry":{"description":"An industry and its sub-industries.","required":["slug","title","children"],"properties":{"slug":{"description":"Stable key, as stored on a brand kit.","type":"string","example":"retail"},"title":{"description":"Display name in the account's language.","type":"string","example":"Retail"},"children":{"description":"Its sub-industries; may be empty.","type":"array","items":{"$ref":"#/components/schemas/IndustryChild"}}},"type":"object"},"IndustryChild":{"description":"A sub-industry of an industry.","required":["slug","title"],"properties":{"slug":{"description":"Stable key, as stored on a brand kit.","type":"string","example":"garden-centers"},"title":{"description":"Display name in the account's language.","type":"string","example":"Garden centers"}},"type":"object"},"InitData":{"description":"Where the request was routed and where it came from, as Hosted received it. Every value comes from request headers and the client address; nothing is read from the account.","required":["environment","cell","accountId","trafficSource","isInternalIp"],"properties":{"environment":{"description":"`production` when the cell name contains `-p-`, `staging` when it contains `-s-`, otherwise the cell name itself (empty when the request carried no cell).","type":"string","example":"production"},"cell":{"description":"Name of the cell that served the request, from the `X-Hosted-Cell` request header. Empty when the header is absent.","type":"string","example":"product-aws-use1-p-1"},"accountId":{"description":"Account ID from the `X-Hosted-Account-Id` request header, as a string. Empty when the header is absent.","type":"string","example":"12345"},"trafficSource":{"description":"Value of the `X-Traffic-Source` request header with carriage returns and line feeds removed; `unknown` when the header is absent.","type":"string","example":"external"},"isInternalIp":{"description":"True when the client address Hosted resolved for the request is one of the company network egress addresses Hosted lists, or the loopback address.","type":"boolean","example":false}},"type":"object"},"InitRecipePersonalizationsDoneResponse":{"description":"Personalization was started, was already complete, or is being started by another request. Read the recipes themselves from GET /ai/initiatives/recipes.","required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"},"status":{"description":"dispatched: a queued recipe was stored for each template to personalize and one personalization request per recipe was queued (a recipe whose request could not be queued is stored as error). done: no template was missing a recipe, so nothing was started. redlocked: another request holds the personalization lock, so nothing was started; call again later.","type":"string","enum":["dispatched","done","redlocked"],"example":"dispatched"}},"type":"object"},"InitRecipePersonalizationsErrorResponse":{"description":"Personalization could not be started. The cause is only logged.","required":["message","status"],"properties":{"message":{"description":"Always error.","type":"string","enum":["error"],"example":"error"},"status":{"description":"dispatch_failed: the queued recipes could not be stored (any stored in this call were removed again). error: anything else failed, such as reading the recipe templates, the stored recipes, or deleting them for a retry.","type":"string","enum":["dispatch_failed","error"],"example":"error"}},"type":"object"},"InitRecipePersonalizationsRequest":{"description":"Options for starting goal recipe personalization. The body must be a JSON object; send {} for the defaults. Properties this schema does not list (the UI also sends templateHash) are ignored.","properties":{"retry":{"description":"true deletes every stored personalized recipe first and personalizes every active template again. false, or omitted, personalizes only the templates that have no stored recipe yet and answers status done when none is missing.","type":["boolean","null"],"example":false}},"type":"object"},"InitRequest":{"description":"What to generate: the message to start from, the instruction, and which of its components to rewrite.","required":["origMessageId","prompt","components"],"properties":{"origMessageId":{"description":"Id of the campaign message to write the new version from. Must name an existing message that has stored editor markup.","type":"integer","example":9134},"prompt":{"description":"How the new version should differ from the original, in the sender's words.","type":"string","example":"Make the tone more urgent and mention that the sale ends Friday"},"components":{"description":"Which parts of the message to rewrite. A part not listed keeps the original message's value in the poll answer.","type":"array","items":{"type":"string","enum":["content","subject","preheader"]},"example":["subject","content"]},"markup":{"description":"Ignored on input: the server loads the stored markup of origMessageId into it.","type":"object","readOnly":true}},"type":"object"},"InitiativeErrorResponse":{"description":"Error body an action builds itself: one message under error.","required":["error"],"properties":{"error":{"description":"What went wrong.","type":"string","example":"Either initiative or template must be provided"}},"type":"object"},"InitiativeResource":{"description":"A business goal, stored as an initiative. The UI calls it a folder; the API still calls folders labels, which is why its name is in label. Numeric and flag columns are returned as strings.","required":["id","label","color","isInitiative","isArchived"],"properties":{"id":{"description":"Business goal id.","type":"string","example":"12"},"groupid":{"description":"Id of the group that owns the goal.","type":"string","example":"1"},"label":{"description":"Business goal name.","type":"string","example":"Grow the newsletter list"},"color":{"description":"Color of the goal's folder, as a hex code without the leading #.","type":"string","example":"edf0f7"},"createdTimestamp":{"description":"When the goal was created, ISO 8601.","type":"string","example":"2026-01-02T10:00:00+00:00"},"updatedTimestamp":{"description":"When the goal was last updated, ISO 8601.","type":"string","example":"2026-01-03T10:00:00+00:00"},"created_by":{"description":"Id of the user who created the goal. Null when it was not created by a user.","type":["string","null"],"example":"1"},"updated_by":{"description":"Id of the user who last updated the goal. Null when it was never updated by a user.","type":["string","null"],"example":null},"description":{"description":"Business goal description.","type":"string","example":"Reach 10,000 subscribers by the end of the year."},"isInitiative":{"description":"1 when the folder is an initiative. Always 1 for goals returned here.","type":"string","enum":["0","1"],"example":"1"},"isArchived":{"description":"1 when the goal is archived, otherwise 0.","type":"string","enum":["0","1"],"example":"0"},"archivedDate":{"description":"When the goal was archived, ISO 8601. Null while it is not archived.","type":["string","null"],"example":null},"useTargetEndDate":{"description":"1 when the goal has a target end date, otherwise 0.","type":"string","enum":["0","1"],"example":"1"},"targetEndDate":{"description":"Target end date, ISO 8601. Null when none is set.","type":["string","null"],"example":"2026-12-31T00:00:00+00:00"},"source":{"description":"How the goal was created: 0 manual, 1 recipe, 2 AI generated, 3 imported, 4 prepopulated.","type":"string","enum":["0","1","2","3","4"],"example":"1"},"template":{"description":"Hash of the recipe template the goal was created from. Empty when it was not created from one.","type":"string","example":"3KP9Mla"},"is_favorite":{"description":"1 when the goal is a favorite on the Overview page, otherwise 0. Present only on the list.","type":"integer","enum":[0,1],"example":0},"automationLabelCount":{"description":"Number of automations in this folder (labeled with this goal in the API). Present only when association counts are requested.","type":"integer","example":2},"campaignLabelCount":{"description":"Number of campaigns in this folder (labeled with this goal in the API). Present only when association counts are requested.","type":"integer","example":1},"formLabelCount":{"description":"Number of forms in this folder (labeled with this goal in the API). Present only when association counts are requested.","type":"integer","example":0},"smsLabelCount":{"description":"Number of SMS broadcasts in this folder (labeled with this goal in the API). Present only when association counts are requested and the account has the SMS entitlement.","type":"integer","example":0},"conversionLabels":{"description":"The conversions linked to this goal with their goal type, value and target status. Present only when conversion labels (conversion folders in the UI) are requested.","type":"array","items":{"type":"object"}},"links":{"description":"Relative links to the goal's related collections.","type":"object","example":{"formLabels":"/formLabels","automationLabels":"/automationLabels","campaignFolders":"/campaignFolders","conversionFolders":"/conversionFolders"},"additionalProperties":{"type":"string"}}},"type":"object"},"InitiativesPerformanceSummaryGenerateRequest":{"description":"Which stored initiatives performance summary to generate, and how. Sent only by Hosted's own background dispatcher, never by a client. Send each field with the JSON type shown.","required":["summaryId","intervalDays","tone"],"properties":{"summaryId":{"description":"ID of the stored summary record to generate, as returned in id by POST /ai/initiatives/performance/summary.","type":"string","example":"ai-initiatives-performance-summary-12"},"tone":{"description":"Tone of voice of the generated summary.","type":"string","enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"intervalDays":{"description":"How many days of performance the summary analyses. Between 1 and 30.","type":"integer","maximum":30,"minimum":1,"example":7}},"type":"object"},"InlineEmailRequest":{"description":"The campaign message to compile and save, optionally with new designer markup and new subject and preheader. Every field must have the JSON type shown; a value of another type answers 422.","required":["campaignId","messageId"],"properties":{"campaignId":{"description":"ID of the campaign the message belongs to. 422 when no campaign has this ID, or when the campaign is sending, stopped, complete or awaiting approval and is not an automation or form campaign.","type":"integer","example":412},"messageId":{"description":"ID of the campaign message to compile and save. 422 when no message has this ID.","type":"integer","example":538},"html":{"description":"Designer HTML to store as the message's markup before compiling. Used only when css is also sent and both are non-empty; otherwise the markup already stored for the message is compiled.","type":["string","null"],"example":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>"},"css":{"description":"Designer CSS to store with html. Used only when html is also sent and both are non-empty.","type":["string","null"],"example":"p { color: #333333; }"},"minimize":{"description":"Whether Stripo minifies the compiled HTML.","type":"boolean","example":true},"subject":{"description":"New subject line for the message, written in the same update as the compiled HTML. Omit it to keep the current subject; an empty string is refused with 422. At most 998 characters.","type":["string","null"],"example":"Our spring collection is here"},"preHeader":{"description":"New preheader text for the message. Omit it to keep the current preheader; an empty string is refused with 422. At most 998 characters.","type":["string","null"],"example":"Fresh picks for the new season"},"versionLabel":{"description":"Name to show on the version-history entry the save records, in place of the acting user's name. Only used when html and css are sent and the message was built in the designer. Omit it to keep the user's name; an empty string is refused with 422. At most 255 characters.","type":["string","null"],"example":"Edited by the campaign assistant"}},"type":"object"},"InsightsError":{"description":"One error in an InsightsErrorResponse.","required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Invalid attribute for a request field that failed validation; otherwise the translated name of the HTTP status.","type":"string","example":"Invalid attribute"},"detail":{"description":"What went wrong. Left out when empty.","type":"string","example":"Invalid filter category: has_brand_kit"},"source":{"description":"The request field that failed validation. Only on validation errors.","required":["pointer"],"properties":{"pointer":{"description":"The field, as /data/attributes/<field name>, for query parameters too.","type":"string","example":"/data/attributes/filterCategories"}},"type":"object"}},"type":"object"},"InsightsErrorResponse":{"description":"Error body written for an AC HTTP exception: a request validation failure (422) or an AI exception such as AIInternalServerException (500).","required":["errors"],"properties":{"errors":{"description":"One error per failed validation check; exactly one error otherwise.","type":"array","items":{"$ref":"#/components/schemas/InsightsError"}}},"type":"object"},"InsightsFilterCategory":{"description":"An account filter category: a check GET /ai/insights/filters/matches can run against the account.","required":["id","label","description"],"properties":{"id":{"description":"ID of the category, as used in filterCategories.","type":"string","example":"has_brandkit"},"label":{"description":"Human-readable name of the category.","type":"string","example":"Has Brand Kit"},"description":{"description":"Which accounts the category matches.","type":"string","example":"Accounts that have set up a primary brand kit."}},"type":"object"},"InstructionGuardrailViolationResponse":{"description":"The instruction was rejected by the content guardrail.","required":["type","message"],"properties":{"type":{"description":"Always guardrail_violation.","type":"string","example":"guardrail_violation"},"message":{"description":"A message for the user, translated into their language.","type":"string","example":"This content cannot be saved."}},"type":"object"},"InstructionListResponse":{"description":"The instructions the account has given the AI agent.","required":["instructions"],"properties":{"instructions":{"description":"The account instruction, or an empty array when the account has not set one.","type":"array","items":{"$ref":"#/components/schemas/AccountInstructionRecord"}}},"type":"object"},"InstructionRequest":{"description":"The instruction to give the AI agent.","required":["content"],"properties":{"content":{"description":"The instruction the AI agent follows for everyone on the account. At most 4000 characters, without emoji.","type":"string","example":"Always write in a friendly, concise tone and sign off with the team name."}},"type":"object"},"JsonValue":{},"KafkaDeferralRequest":{"description":"A Kafka REST proxy write that was deferred, as the queue relay sends it back: the proxy request body plus the topic it was addressed to.","required":["topic","records"],"properties":{"keySchemaId":{"description":"Schema registry ID of the record keys. Accepted, also as key_schema_id, and checked to be a string or null, but not used: the records are re-published as they are. The relay sends null.","type":["string","null"],"example":null},"valueSchemaId":{"description":"Schema registry ID of the record values. Accepted, also as value_schema_id, and checked to be a string or null, but not used: each value already carries its encoded message. The relay sends null.","type":["string","null"],"example":null},"topic":{"description":"Name of the Kafka topic to publish to, without the REST proxy path prefix /topics/.","type":"string","example":"automation.fact.block-processing-log.1"},"records":{"description":"The records to publish, in order; at least one. A record may hold only key and value.","type":"array","items":{"required":["value"],"properties":{"key":{"description":"Record key, published as given. Null or absent publishes the record without a key.","type":["string","null"],"example":"12345"},"value":{"description":"The Avro-encoded message, base64-encoded. It is decoded before it is published.","type":"string","example":"AAAAAAEGZm9v"}},"type":"object"}}},"type":"object"},"KafkaIncrementDeferralRequest":{"description":"A JSON Kafka write of increment intents that was deferred, as the queue relay sends it back: the REST proxy request body plus the topic it was addressed to.","required":["topic","records"],"properties":{"topic":{"description":"Name of the Kafka topic to publish to, without the REST proxy path prefix /topics/.","type":"string","example":"hosted.fact.increment.series.0"},"records":{"description":"The records to publish, in order; at least one. A record may hold only key and value.","type":"array","items":{"required":["value"],"properties":{"key":{"description":"Record key, published as given. Null or absent publishes the record without a key.","type":["string","null"],"example":"12345-42"},"value":{"description":"The increment intent, published as JSON exactly as received. Its event_id is what lets the consumer drop a record it has already applied, so a retried request is safe.","type":"object","example":{"event_id":"6f1c2b0e-8a4d-4f3e-9b7a-2d5c1e0f9a11","account_id":12345,"table":"em_series","row_id":42,"column":"entered","delta":1,"write_path":"aggregated"}}},"type":"object"}}},"type":"object"},"Label":{"description":"A label. Automations, forms, campaigns and SMS broadcasts share one set of labels. A label upgraded to an initiative is the same record. Numbers are numeric strings.","type":"object","required":["id","label","color"],"properties":{"groupid":{"type":"string","description":"ID of the user group of the user who created the label","example":"3"},"label":{"type":"string","description":"Name of the label","example":"Spring launch"},"color":{"type":"string","description":"Color of the label as six hexadecimal digits without a leading #","example":"edf0f7"},"createdTimestamp":{"type":"string","description":"When the label was created, in ISO 8601 with a time zone offset. Reset to the upgrade time when the label is upgraded to an initiative.","example":"2026-10-15T10:52:26-05:00"},"updatedTimestamp":{"type":"string","description":"When the label was last changed, in ISO 8601 with a time zone offset","example":"2026-10-15T10:52:26-05:00"},"created_by":{"type":["string","null"],"description":"ID of the user who created the label. Reset to the upgrading user when the label is upgraded to an initiative.","example":"1"},"updated_by":{"type":["string","null"],"description":"ID of the user who last changed the label","example":"1"},"description":{"type":"string","description":"Description. Used by initiatives; empty for a plain label.","example":""},"isInitiative":{"type":"string","description":"1 when the label was upgraded to an initiative, otherwise 0.","example":"0"},"isArchived":{"type":"string","description":"1 when the initiative is archived, otherwise 0.","example":"0"},"archivedDate":{"type":["string","null"],"description":"When the initiative was archived, as YYYY-MM-DD HH:MM:SS."},"useTargetEndDate":{"type":"string","description":"1 when the initiative uses its target end date, otherwise 0.","example":"0"},"targetEndDate":{"type":["string","null"],"description":"Target end date of the initiative, in ISO 8601."},"source":{"type":"string","description":"How the label was made: 0 by hand, 1 from a recipe, 2 by AI, 3 by import, 4 prepopulated.","example":"0"},"template":{"type":"string","description":"Identifier of the recipe the label was made from, or empty.","example":""},"campaignLabelCount":{"type":"string","description":"Number of campaigns with this label. Present only on GET /labels with include_association_counts=1.","example":"2"},"formLabelCount":{"type":"string","description":"Number of forms with this label. Present only on GET /labels with include_association_counts=1.","example":"1"},"automationLabelCount":{"type":"string","description":"Number of automations with this label. Present only on GET /labels with include_association_counts=1.","example":"4"},"smsLabelCount":{"type":"string","description":"Number of SMS broadcasts with this label. Present only on GET /labels with include_association_counts=1, and only when the account has SMS. It is 0 when the SMS service does not answer.","example":"0"},"links":{"description":"URLs of the label's related reads","type":"object","properties":{"formLabels":{"type":"string","description":"URL of GET /labels/{id}/formLabels","example":"https://:account.api-us1.com/api/:version/labels/3/formLabels"},"automationLabels":{"type":"string","description":"URL of GET /labels/{id}/automationLabels","example":"https://:account.api-us1.com/api/:version/labels/3/automationLabels"},"campaignFolders":{"type":"string","description":"URL of GET /labels/{id}/campaignFolders","example":"https://:account.api-us1.com/api/:version/labels/3/campaignFolders"},"conversionFolders":{"type":"string","description":"URL of GET /labels/{id}/conversionFolders","example":"https://:account.api-us1.com/api/:version/labels/3/conversionFolders"}}},"id":{"type":"string","description":"ID of the label","example":"3"}}},"LabelInput":{"type":"object","description":"The label fields that can be set","properties":{"label":{"type":"string","maxLength":250,"description":"Name of the label, up to 250 characters. Required on create.","example":"Spring launch"},"color":{"type":"string","maxLength":6,"description":"Color as six hexadecimal digits without a leading #. The format is not checked. When empty, it is set to edf0f7.","example":"f85e4e"},"description":{"type":"string","maxLength":500,"description":"What the label is for, up to 500 characters. On update, an empty string clears it and leaving it out keeps it. Longer text is refused with a 422 pointing at /data/attributes/description.","example":"Grow sign-ups before the spring launch"}}},"LabelValidationErrors":{"type":"object","description":"Validation errors for a label","properties":{"errors":{"type":"array","description":"One entry describing the problem","items":{"type":"object","properties":{"title":{"type":"string","description":"Message for people, in the language of the user","example":"The label name is required"},"detail":{"type":"string","description":"Always empty","example":""},"code":{"type":"string","enum":["field_missing","duplicate"],"description":"field_missing when the name is missing or blank, duplicate when another label or initiative already has the name","example":"field_missing"},"error":{"type":"string","enum":["label_label_was_not_provided","label_already_exists_in_the_system"],"description":"Machine-readable reason that matches code","example":"label_label_was_not_provided"},"source":{"type":"object","description":"Where the problem is","properties":{"pointer":{"type":"string","description":"Always /data/attributes/label","example":"/data/attributes/label"}}}}}}}},"LandingPagesAccountRecord":{"type":"object","description":"One row of the platform-wide accounts table as stored, every column included, plus an empty `links`. Values are strings as the database returns them. The properties below are the ones the landing pages service is known to read, not the full list.","additionalProperties":true,"properties":{"id":{"type":["string","integer"],"description":"ID of the account."},"account":{"type":"string","description":"The account's name, which is its hostname."},"expire":{"type":"string","description":"Date the account expires, `YYYY-MM-DD`. A date before today means the account is expired."},"down4":{"type":"string","description":"Account status: `nobody` when the account is active. Any other value, such as `review` or `maint`, means it is inactive: under review, under maintenance, suspended or awaiting verification."},"links":{"type":"array","maxItems":0,"description":"Always an empty array: the account record has no related resources to link."}}},"LandingPagesAccountSummary":{"type":"object","description":"The name, expiry date and status of one ActiveCampaign account.","properties":{"id":{"type":"integer","description":"ID of the account."},"expire":{"type":"string","description":"Date the account expires, `YYYY-MM-DD`. A date before today means the account is expired."},"down4":{"type":"string","description":"Account status: `nobody` when the account is active. Any other value, such as `review` or `maint`, means it is inactive: under review, under maintenance, suspended or awaiting verification."},"accountname":{"type":"string","description":"The account's name, which is its hostname."}}},"LandingPagesMetadata":{"type":"object","required":["user","pendoConfig","branding"],"properties":{"user":{"type":"object","description":"The user named by `pagesUserId`, serialized the way GET /users/{id} returns it under `user` (password, API key and similar fields left out).","additionalProperties":true,"properties":{"id":{"type":["string","integer"],"description":"ID of the user."},"username":{"type":"string","description":"The user's login name."},"email":{"type":"string","description":"The user's email address."},"lang":{"type":"string","description":"The user's interface language, e.g. `english`."}}},"pendoConfig":{"type":"object","description":"Pendo analytics configuration for the user the request is authenticated as.","properties":{"visitor":{"type":"object","additionalProperties":true,"description":"Pendo visitor metadata: the user's Pendo ID, language, email, permission group and activity dates."},"account":{"type":"object","additionalProperties":true,"description":"Pendo account metadata: the account's Pendo ID, name, plan, limits and usage counts."},"apiKey":{"type":"string","description":"The Pendo API key."}}},"branding":{"type":"object","description":"The account's admin branding, with its admin page template split around the page content. The `site` object leaves out the Facebook and Twitter app credentials.","additionalProperties":true,"properties":{"has_header":{"type":"boolean","description":"Whether the admin template has a navigation header."},"has_footer":{"type":"boolean","description":"Whether the admin template has a footer."},"content_pre":{"type":"string","description":"Template HTML that goes before the page content, trimmed."},"content_body":{"type":"string","description":"Template HTML that goes in the body of the page, trimmed."},"content_post":{"type":"string","description":"Template HTML that goes after the page content, trimmed."}}}}},"LanguageEnum":{"enum":["af","sq","ar","az","bn","bg","ca","zh_CN","zh_HK","zh_TW","hr","cs","da","nl","en","en_GB","en_US","et","fil","fi","fr","ka","de","el","gu","ha","he","hi","hu","id","ga","it","ja","kn","kk","rw_RW","ko","ky_KG","lo","lv","lt","mk","ms","ml","mr","nb","fa","pl","pt_BR","pt_PT","pa","ro","ru","sr","sk","sl","es","es_AR","es_ES","es_MX","sw","sv","ta","te","th","tr","uk","ur","uz","vi","zu"],"type":"string","description":"* `af` - Afrikaans\n* `sq` - Albanian\n* `ar` - Arabic\n* `az` - Azerbaijani\n* `bn` - Bengali\n* `bg` - Bulgarian\n* `ca` - Catalan\n* `zh_CN` - Chinese (CHN)\n* `zh_HK` - Chinese (HKG)\n* `zh_TW` - Chinese (TAI)\n* `hr` - Croatian\n* `cs` - Czech\n* `da` - Danish\n* `nl` - Dutch\n* `en` - English\n* `en_GB` - English (UK)\n* `en_US` - English (US)\n* `et` - Estonian\n* `fil` - Filipino\n* `fi` - Finnish\n* `fr` - French\n* `ka` - Georgian\n* `de` - German\n* `el` - Greek\n* `gu` - Gujarati\n* `ha` - Hausa\n* `he` - Hebrew\n* `hi` - Hindi\n* `hu` - Hungarian\n* `id` - Indonesian\n* `ga` - Irish\n* `it` - Italian\n* `ja` - Japanese\n* `kn` - Kannada\n* `kk` - Kazakh\n* `rw_RW` - Kinyarwanda\n* `ko` - Korean\n* `ky_KG` - Kyrgyz (Kyrgyzstan)\n* `lo` - Lao\n* `lv` - Latvian\n* `lt` - Lithuanian\n* `mk` - Macedonian\n* `ms` - Malay\n* `ml` - Malayalam\n* `mr` - Marathi\n* `nb` - Norwegian\n* `fa` - Persian\n* `pl` - Polish\n* `pt_BR` - Portuguese (BR)\n* `pt_PT` - Portuguese (POR)\n* `pa` - Punjabi\n* `ro` - Romanian\n* `ru` - Russian\n* `sr` - Serbian\n* `sk` - Slovak\n* `sl` - Slovenian\n* `es` - Spanish\n* `es_AR` - Spanish (ARG)\n* `es_ES` - Spanish (SPA)\n* `es_MX` - Spanish (MEX)\n* `sw` - Swahili\n* `sv` - Swedish\n* `ta` - Tamil\n* `te` - Telugu\n* `th` - Thai\n* `tr` - Turkish\n* `uk` - Ukrainian\n* `ur` - Urdu\n* `uz` - Uzbek\n* `vi` - Vietnamese\n* `zu` - Zulu"},"LanguageMapEntry":{"description":"One value of the account's language field and the language it translates to.","required":["lang","supportedLang","code"],"properties":{"lang":{"description":"The value as it appears on the language field, or the language's own name or code. When the mapping was built from an existing field this is that field's value, which may not match supportedLang.","type":"string","example":"Spanish"},"supportedLang":{"description":"The name of the language the value translates to, as the translation service names it, or \"default\" for a value that is not translated.","type":"string","example":"Spanish"},"code":{"description":"The translation service's code for that language, or \"default\" for a value that is not translated. \"default\" goes with supportedLang \"default\" and nothing else.","type":"string","example":"es"},"needsReview":{"description":"True for a value an AI model mapped from an existing field, which a person should check. Always returned. Optional when a mapping is saved, where leaving it out means false. Saving marks the whole mapping as reviewed, so a true sent on save is stored and returned as false.","type":"boolean","default":false,"example":false}},"type":"object"},"LanguageMappingCreateRequest":{"description":"What to build the language mapping from.","properties":{"existingFieldId":{"description":"Id of a dropdown or radio contact field to build the mapping from. It must exist, and it must have at least one option or saved value. Left out, the mapping is built from the supported languages alone.","type":["integer","null"],"example":12}},"type":"object"},"LanguageMappingDeletedResponse":{"description":"The language mapping was deleted.","required":["success"],"properties":{"success":{"description":"Always true.","type":"boolean","example":true}},"type":"object"},"LanguageMappingDetails":{"description":"The account's language mapping and the contact field it was built from.","required":["mapping","existingFieldId"],"properties":{"mapping":{"description":"Every language value and the language it translates to. Null, with existingFieldId null too, only when the stored mapping data could not be decoded or the record of its field could not be read.","type":["array","null"],"items":{"$ref":"#/components/schemas/LanguageMapEntry"}},"existingFieldId":{"description":"Id of the dropdown or radio contact field the mapping was built from, or null when it was built from the supported languages alone.","type":["integer","null"],"example":12}},"type":"object"},"LanguageMappingUpdateRequest":{"description":"The language mapping to store.","required":["mapping"],"properties":{"mapping":{"description":"The whole mapping, at least one entry. Each code and supportedLang must be a pair the translation service supports, or both \"default\".","type":"array","items":{"$ref":"#/components/schemas/LanguageMapEntry"},"minItems":1},"existingFieldId":{"description":"Id of the dropdown or radio contact field the mapping was built from. It must exist. When given, it is saved with the mapping and the preferred-language automation is rebuilt from it, which needs permission to manage automations.","type":["integer","null"],"example":12}},"type":"object"},"ListGroupBulkUpdateErrors":{"type":"object","description":"Why the request was refused","properties":{"errors":{"type":"array","description":"The problems found","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code. Sent by the method and body checks."},"title":{"type":"string","description":"Short summary of the problem"},"detail":{"type":"string","description":"What is missing. Left out when there is no detail, as on a 405."},"code":{"type":"string","description":"Error code. Sent when a list id cannot be saved, for example field_missing."},"error":{"type":"string","description":"Error key. Sent when a list id cannot be saved."},"source":{"type":"object","description":"The field at fault. Sent when a list id cannot be saved.","properties":{"pointer":{"type":"string"}}}}}}}},"ListGroupBulkUpdateRecord":{"type":"object","description":"One list group record: the user group has access to the list.","properties":{"list":{"type":"string","description":"ID of the list"},"group":{"type":"string","description":"ID of the user group"},"links":{"type":"object","description":"URLs of the related list and user group","properties":{"list":{"type":"string","description":"URL of the related list"},"group":{"type":"string","description":"URL of the related user group"}}},"id":{"type":"string","description":"ID of the list group record"}},"patternProperties":{"^p_":{"type":"string","enum":["0","1"],"description":"A permission flag of the record, \"1\" or \"0\". This endpoint does not set the flags, so a new record has every flag \"0\"."}}},"ListsCleanupRequest":{"type":"object","properties":{"listIds":{"type":"array","items":{"type":"integer"},"description":"IDs of the lists to clean up. Required unless `allLists` is true. Each must be a whole number and a list that exists."},"allLists":{"type":["boolean","integer","string"],"description":"When true, every list the user can see is used and `listIds` is not read. Any value other than false, empty, 0 or \"0\" counts as true, so the string \"false\" also turns it on and cleans up every list the user can see."},"status":{"type":"integer","enum":[-1,0,1,2,3],"description":"Picks contacts by their status on the list: -1 any status, 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced. Do not send it with `emails`."},"date":{"type":"string","description":"Needed with `status`. Format Y-m-d\\TH:i:sP, for example 2026-10-01T00:00:00+00:00. The date and time are compared as written; the offset is not applied. For status -1, 0 and 1, picks contacts who joined the list on or before it. For 2, contacts who unsubscribed on or before it. For 3, contacts who bounced on or before it, or who have no bounce date. With `emails` or status 0 it is not required, and with status 0 a missing date means no contact matches. If it is sent, it must still be in the format."},"emails":{"type":"array","items":{"type":"string"},"description":"Email addresses of the contacts to remove. Spaces around each address are trimmed. Do not send it with `status`."},"preview":{"type":["boolean","integer","string"],"description":"When true, only count. Nothing changes and no job is queued. Any value other than false, empty, 0 or \"0\" counts as true, so the string \"false\" also asks for a preview."},"includeContacts":{"type":"boolean","default":true,"description":"Preview only. When false, `contactEmails` is left out of the answer."},"limit":{"type":"integer","minimum":1,"maximum":20000,"description":"Preview only. Most emails to return in `contactEmails`, ordered by contact ID. Without it, all of them are returned."},"offset":{"type":"integer","minimum":0,"description":"Preview only. Number of emails to skip. When sent without `limit`, `limit` is 100."}}},"ListsCleanupResult":{"type":"object","description":"Result of a list cleanup","properties":{"totalRemoving":{"type":"integer","description":"Number of contacts picked on the lists"},"totalDeleting":{"type":"integer","description":"Number of those contacts that are on no other list, so they are deleted"},"contactEmails":{"type":"array","items":{"type":"string"},"description":"Only on a preview, and not when `includeContacts` is false. Emails of the contacts that would be deleted."},"process":{"type":"string","description":"Not on a preview. ID of the background job.","example":"123"},"success":{"type":"integer","description":"Always 1","example":1}}},"ListsCleanupUpgrade":{"type":"object","description":"The account does not have the Campaigns feature","required":["success","message"],"properties":{"success":{"type":"integer","description":"Always 0"},"message":{"type":"string","description":"Translated text asking to upgrade"}}},"ListsExclusionBadRequest":{"description":"Why the request could not be read","required":["errors"],"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"HTTP status code as a string, always 400","type":"string","example":"400"},"detail":{"description":"What could not be read","type":"string","example":"Could not decode request body."}},"type":"object"}}},"type":"object"},"ListsExclusionErrors":{"description":"Why the request failed","required":["errors"],"properties":{"errors":{"description":"One entry per error. A validation failure lists every field that failed.","type":"array","items":{"required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":422},"title":{"description":"Short name of the error: the HTTP status name, or Invalid attribute for a validation failure","type":"string","example":"Invalid attribute"},"detail":{"description":"What went wrong. Left out when there is nothing to add to the title, as on a refused permission.","type":"string","example":"Missing ids"},"source":{"description":"The field that failed. Only on a validation failure.","required":["pointer"],"properties":{"pointer":{"description":"The field name after /data/attributes/","type":"string","example":"/data/attributes/ids"}},"type":"object"}},"type":"object"}}},"type":"object"},"ListsHttpErrors":{"type":"object","description":"Why the request was refused","required":["errors"],"properties":{"errors":{"type":"array","description":"Always one error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status"},"title":{"type":"string","description":"Short name of the error"},"detail":{"type":"string","description":"What went wrong. Left out when there is no detail, as on a 405."}}}}}},"LlmConsumptionResponse":{"description":"The account's monthly AI allowance and how much of it has been used.","required":["limit","usage","over_limit","ai_credits_unlimited"],"properties":{"limit":{"description":"AI activities the account may use this month. 0 when the account has no AI entitlement.","type":"integer","example":1000},"usage":{"description":"AI activities the account has used this month. 0 when the account has no AI entitlement.","type":"integer","example":250},"over_limit":{"description":"True once usage has reached the limit, and always true when the account has no AI entitlement.","type":"boolean","example":false},"ai_credits_unlimited":{"description":"True for resold accounts whose premium AI credits are not metered. limit, usage and over_limit still describe the activities meter.","type":"boolean","example":false},"refresh_date":{"description":"When the allowance next resets, as an ISO 8601 UTC timestamp. Omitted when the account has no refresh date.","type":"string","example":"2026-11-01T00:00:00Z"}},"type":"object"},"LocationMessage":{"type":"object","properties":{"address":{"type":"string","maxLength":500},"latitude":{"type":"number","format":"double"},"longitude":{"type":"number","format":"double"},"place_name":{"type":"string","nullable":true,"maxLength":500},"place_url":{"type":"string","format":"uri","nullable":true,"maxLength":200},"map_screenshot_url":{"type":"string","format":"uri","nullable":true,"maxLength":200}},"required":["address","latitude","longitude"]},"LookupField":{"description":"A field of a CRM object whose value a lookup field may show","required":["id","name","type","isCustom","options"],"properties":{"id":{"description":"A standard field's camelCase name, or a custom field's meta id as a string. The value a lookup field stores to name the field.","type":"string","example":"firstName"},"name":{"description":"The field label, translated for the user","type":"string","example":"First Name"},"type":{"description":"The field type. A custom field keeps its own type (text, dropdown, date...). A standard field is text, textarea, currency, dropdown, date or datetime, or user, pipeline or stage when its value is the id of a user, pipeline or deal stage.","type":"string","example":"text"},"isCustom":{"description":"True for a custom field, false for a standard one","type":"boolean","example":false},"options":{"description":"The values the field may take, for a field with a fixed list of them; empty otherwise","type":"array","items":{"properties":{"label":{"description":"The option as shown","type":"string"},"value":{"description":"The option as stored","type":"string"}},"type":"object"}}},"type":"object"},"MarkRecommendationUsedRequest":{"description":"Which stored recommendation to mark as used.","required":["assetType","initiativeId"],"properties":{"assetType":{"description":"Kind of asset the recommendation is for.","type":"string","enum":["automation","campaign"],"example":"automation"},"initiativeId":{"description":"ID of the business goal the recommendation was stored for. A recommendation made for a goal recipe template is stored under the template hash, which is accepted here too. A numeric string is accepted as well.","type":"integer","example":123}},"type":"object"},"MatchAllAttributeDO":{"title":"MatchAllAttributeDO","required":["is_ready","run_id","run_id_start","segment_id"],"type":"object","properties":{"run_id":{"type":"string","description":"The runId of the match-all request. Use this value to poll for results or lookup results at a later point in time. RunId results can be viewed for 90 days"},"run_id_start":{"type":"string","description":"ISO 8601 datetime representing when the match-all request was made","format":"date-time","example":"2020-04-12T23:20:50.523Z"},"run_id_end":{"type":"string","description":"ISO 8601 datetime representing when the match-all result-set was ready. If this date-time is present and `is_ready` is `false`, then the match-all request has ran into an error and will not finish; please try making a new match-all request or contacting support.","format":"date-time","example":"2020-04-12T23:20:50.523Z"},"is_ready":{"type":"boolean","description":"True if the result-set is ready. False otherwise"},"matches":{"maxItems":10000,"type":"array","description":"One page of the result-set of Contact Id's","items":{"type":"integer"}},"segment_id":{"type":"string"},"segment_timestamp":{"type":"string","description":"ISO 8601 datetime representing when segment was last created or modified. This timestamp can be used to look up the definition of the Segment at the time of the match-all request","format":"date-time","example":"2020-04-12T23:20:50.523Z"},"page":{"$ref":"#/components/schemas/PageDO"}},"description":"Object representing the status and result of the match all request. Note that page number and total count information refer to the results in the \"matches\" attribute."},"MatchAllDataDO":{"title":"MatchAllDataDO","type":"object","properties":{"attributes":{"$ref":"#/components/schemas/MatchAllAttributeDO"},"id":{"type":"string","description":"ID of the specific request"},"type":{"type":"string","enum":["matchAll"]}}},"MatchAllResponseRootDO":{"title":"MatchAllResponseRootDO","type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MatchAllDataDO"}}}},"MatchAttributeDO":{"type":"object","properties":{"created_timestamp":{"type":"string","format":"date-time","example":"2025-04-12T23:20:50.523Z"},"entity_id":{"type":"string","description":"The ContactId that was evaluated against the Segment","example":"132"},"match":{"type":"boolean","description":"True if the Contact matches the Segment. False otherwise"},"segment_id":{"type":"string","description":"The SegmentId that the Contact was evaluated against","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195"},"segment_timestamp":{"type":"string","format":"date-time","example":"2025-04-12T23:20:50.523Z"}},"title":"MatchAttributeDO"},"MatchDataDO":{"type":"object","properties":{"attributes":{"$ref":"#/components/schemas/MatchAttributeDO"},"id":{"type":"string","description":"Id that identifies the request. Consists of SegmentId + ContactId","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132"},"type":{"type":"string","enum":["match"]}},"title":"MatchDataDO"},"MatchResponseRootDO":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MatchDataDO"}}},"title":"MatchResponseRootDO"},"MaxWaitTimeUnitEnum":{"enum":["SECOND","MINUTE","HOUR","DAY"],"type":"string","description":"* `SECOND` - Second\n* `MINUTE` - Minute\n* `HOUR` - Hour\n* `DAY` - Day"},"McpAudienceResponse":{"description":"How a set_campaign_audience call ended.","properties":{"message":{"description":"The answer, written for the user. Relay it as it stands.","title":"Message","type":"string"},"outcome":{"$ref":"#/components/schemas/AudienceOutcome","description":"How the call ended."},"previous_list_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"default":null,"description":"The lists the campaign held before the call; null when not read.","title":"Previous List Ids"},"list_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"default":null,"description":"The lists the campaign was last read to hold; null when not read.","title":"List Ids"},"segment_id":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"The segment now narrowing the lists; null for none or when unchanged.","title":"Segment Id"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["message","outcome"],"title":"McpAudienceResponse","type":"object"},"McpCopyRequest":{"additionalProperties":false,"description":"The ``copy_campaign`` tool's input.","properties":{"campaign_id":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Numeric id of the campaign to copy, when known. Not required if `campaign_name` is given instead.","title":"Campaign ID"},"campaign_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Alternate way to address the source campaign, by name, when the id isn't known.","title":"Campaign Name"},"copy_changes":{"anyOf":[{"maxLength":20000,"type":"string"},{"type":"null"}],"default":null,"description":"Changes to apply to the copy, in the same breath as duplicating it.","examples":["Change the offer to 15% off."],"title":"Copy Changes"},"idempotency_key":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Optional idempotency key. Duplicate requests with the same key return the original run instead of creating a new one. If not provided, a key is derived from the request content and caller identity.","title":"Idempotency Key"}},"title":"McpCopyRequest","type":"object"},"McpDirectResponse":{"description":"The answer to an operation answered directly, not as a run to poll.","properties":{"message":{"description":"The answer, written for the user. Relay it as it stands.","title":"Message","type":"string"},"outcome":{"description":"How the call was served.","examples":["success","busy","not_enabled","failed","not_supported","unrecognized"],"title":"Outcome","type":"string"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["message","outcome"],"title":"McpDirectResponse","type":"object"},"McpEditRequest":{"additionalProperties":false,"description":"The ``edit_campaign`` tool's input.","properties":{"business_goal_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Business goal id to tag the campaign with.","title":"Business Goal ID"},"image_references":{"anyOf":[{"items":{"maxLength":2000,"pattern":"^[^\\x00-\\x1f\\x7f]+$","type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Content-manager image names — the `name` field of an image in the account's Content Manager, never a URL.","title":"Image References"},"image_search_terms":{"anyOf":[{"items":{"maxLength":2000,"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Keywords to search the content manager for images by.","title":"Image Search Terms"},"urls":{"anyOf":[{"items":{"maxLength":2000,"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Page URLs to write about, or link the campaign should point to.","title":"URLs"},"ai_images":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"`True` to let the engine generate images with AI.","title":"AI Images"},"language":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Explicit output language, only when the user names one outright.","examples":["English","Spanish","French"],"title":"Language"},"prompt":{"description":"Edit instruction. Pass the user's exact words verbatim.","maxLength":20000,"minLength":1,"title":"Prompt","type":"string"},"campaign_id":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Numeric id of the campaign to edit, when known. Not required if `campaign_name` is given instead.","title":"Campaign ID"},"campaign_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Alternate way to address the campaign, by name, when the id isn't known.","title":"Campaign Name"},"update_subject":{"default":false,"description":"`True` only if the user asks to change the subject line.","title":"Update Subject","type":"boolean"},"update_preheader":{"default":false,"description":"`True` only if the user asks to change the preheader.","title":"Update Preheader","type":"boolean"},"content_change":{"default":false,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. The edit's scope is derived from `prompt` itself.","title":"Content Change","type":"boolean"},"cta_button_url_change":{"default":false,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Describe the link change in `prompt` instead.","title":"CTA Button URL Change","type":"boolean"},"cta_button_text_change":{"default":false,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Describe the button-text change in `prompt` instead.","title":"CTA Button Text Change","type":"boolean"},"subject_change":{"default":false,"deprecated":true,"description":"Deprecated alias for `update_subject`.","title":"Subject Change","type":"boolean"},"preheader_change":{"default":false,"deprecated":true,"description":"Deprecated alias for `update_preheader`.","title":"Preheader Change","type":"boolean"},"images":{"anyOf":[{"items":{"$ref":"#/components/schemas/PositionedImage"},"type":"array"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Search the account's Content Manager images for one to use and pass its `name` in `image_references` instead.","title":"Images"},"brand_kit_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Brand is resolved automatically for every edit.","title":"Brand Kit ID"},"idempotency_key":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Optional idempotency key. Duplicate requests with the same key return the original run instead of creating a new one. If not provided, a key is derived from the request content and caller identity.","title":"Idempotency Key"}},"required":["prompt"],"title":"McpEditRequest","type":"object"},"McpEditStartResponse":{"description":"Handle for a started edit run. Names the affected campaign directly when it was addressed by id, so a caller doesn't have to poll just to learn which campaign the call acted on.","properties":{"request_id":{"description":"Run identifier. Pass to `poll_campaign_generation_status`.","title":"Request Id","type":"string"},"campaign_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The campaign this edit acts on, when addressed by id.","title":"Campaign Id"},"disclosures":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"default":null,"description":"What this call could not do, even though it started the run.","title":"Disclosures"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace the run's work is recorded under. Quote it when reporting a problem with this run.","title":"Trace Id"}},"required":["request_id","campaign_id"],"title":"Campaign Edit Start Result","type":"object"},"McpGenerateRequest":{"additionalProperties":false,"description":"The ``generate_campaign`` tool's input.","properties":{"business_goal_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Business goal id to tag the campaign with.","title":"Business Goal ID"},"image_references":{"anyOf":[{"items":{"maxLength":2000,"pattern":"^[^\\x00-\\x1f\\x7f]+$","type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Content-manager image names — the `name` field of an image in the account's Content Manager, never a URL.","title":"Image References"},"image_search_terms":{"anyOf":[{"items":{"maxLength":2000,"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Keywords to search the content manager for images by.","title":"Image Search Terms"},"urls":{"anyOf":[{"items":{"maxLength":2000,"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Page URLs to write about, or link the campaign should point to. Combined with the deprecated `cta_url` field at a combined max of 50 items.","title":"URLs"},"ai_images":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"`True` to let the engine generate images with AI.","title":"AI Images"},"language":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Explicit output language, only when the user names one outright.","examples":["English","Spanish","French"],"title":"Language"},"prompt":{"description":"User's exact campaign description verbatim. Required.","maxLength":20000,"minLength":1,"title":"Prompt","type":"string"},"template_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Integer template id from `list_campaign_templates`, to build into that template's design.","examples":[100067],"title":"Template ID"},"template_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"One of the account's own templates, by name, when no id is known — resolved without a prior `list_campaign_templates` call.","examples":["Newsletter Base"],"title":"Template Name"},"source_campaign_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Id of a past campaign to style this new one after.","title":"Source Campaign ID"},"source_campaign_date":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Narrows the source campaign named in `prompt` rather than numbered, when several share a name.","examples":["March"],"title":"Source Campaign Date"},"stock_template_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of an AC stock gallery template, verbatim.","title":"Stock Template Name"},"is_new_creation":{"default":false,"description":"`True` to force a fresh design even when `template_id`/`source_campaign_id` is also set.","title":"Is New Creation","type":"boolean"},"bundle_url":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"default":null,"description":"URL of a design tool's file, export, or share link (Figma, Canva, Sketch, Adobe XD, and similar) to rebuild. Not yet supported — always returns a `not_supported` outcome.","title":"Bundle URL"},"label_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"deprecated":true,"description":"Deprecated alias for `business_goal_id`.","title":"Label ID"},"images":{"anyOf":[{"items":{"$ref":"#/components/schemas/PositionedImage"},"type":"array"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Search the account's Content Manager images for one to use and pass its `name` in `image_references` instead.","title":"Images"},"cta_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Deprecated alias — merged into `urls`.","title":"CTA URL"},"brand_kit_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Brand is resolved automatically for every generation.","title":"Brand Kit ID"},"summarization_uuid":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Pass the page URL in `urls` instead.","title":"Summarization UUID"},"tone":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect. Describe the desired tone in `prompt` instead.","title":"Tone"},"series_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect.","title":"Series ID"},"is_asset_draft":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"deprecated":true,"description":"Accepted for backward compatibility; has no effect.","title":"Is Asset Draft"},"user_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"deprecated":true,"description":"Deprecated — omit. Already mirrors `prompt`.","title":"User Prompt"},"html":{"anyOf":[{"minLength":1,"type":"string"},{"type":"null"}],"default":null,"description":"A finished email's complete HTML document, `<html>` through `</html>`, to import as the campaign exactly as it stands rather than generate one. `prompt` still carries the user's request, held to a shorter bound alongside it that a refusal names. Cannot be combined with `template_id`, `template_name`, `stock_template_name`, `source_campaign_id`, `source_campaign_date`, `bundle_url`, `urls`, `cta_url`, `image_references`, `image_search_terms`, `images`, `language`.","title":"HTML"},"idempotency_key":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Optional idempotency key. Duplicate requests with the same key return the original run instead of creating a new one. If not provided, a key is derived from the request content and caller identity.","title":"Idempotency Key"}},"required":["prompt"],"title":"McpGenerateRequest","type":"object"},"McpHistoryRequest":{"description":"A campaign whose history to read, or two of its versions to compare.","properties":{"campaign_id":{"description":"Numeric id of the campaign.","exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"from_version":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Supply with `to_version` to compare two versions.","title":"From Version"},"to_version":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Supply with `from_version` to compare two versions.","title":"To Version"}},"required":["campaign_id"],"title":"McpHistoryRequest","type":"object"},"McpImportRequest":{"additionalProperties":false,"description":"The ``import_campaign_design`` tool's input.\n\nThe one request on this surface carrying a document rather than a reference: an email the\ncaller already has has no id and no URL to name it by. Deliberately narrower than the other\nstart requests — the document IS the design, so there is no template, source campaign or\nimage input to accept.","properties":{"source_html":{"description":"Complete HTML of the email to bring over, including its styles.","maxLength":1000000,"minLength":1,"title":"Source HTML","type":"string"},"notes":{"default":"","description":"Instructions to carry alongside the import, if any. The document itself is the request, so this is usually left empty.","maxLength":20000,"title":"Notes","type":"string"},"idempotency_key":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Optional idempotency key. Duplicate requests with the same key return the original run instead of creating a new one. If not provided, a key is derived from the request content and caller identity.","title":"Idempotency Key"}},"required":["source_html"],"title":"McpImportRequest","type":"object"},"McpManageTemplateRequest":{"description":"A rename, delete or duplicate of one template in the library.","properties":{"action":{"description":"Which template operation to perform.","enum":["rename","delete","duplicate"],"examples":["rename","delete","duplicate"],"title":"Action","type":"string"},"template_id":{"anyOf":[{"exclusiveMinimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Numeric id of the template.","title":"Template Id"},"template_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Exact name of the template, when no id is known. A delete requires an id or an exact name — it never resolves a near-miss, because it cannot be undone.","title":"Template Name"},"new_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Required when action is `rename`.","title":"New Name"}},"required":["action"],"title":"McpManageTemplateRequest","type":"object"},"McpPrepareResponse":{"description":"A prepared send or schedule: nothing has been sent.","properties":{"message":{"description":"The answer, written for the user. Relay it as it stands.","title":"Message","type":"string"},"outcome":{"$ref":"#/components/schemas/SendOutcome","description":"How the call ended. ready means confirmable."},"confirmation_token":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Pass to the confirm call once the user agrees; null unless outcome is ready.","title":"Confirmation Token"},"expires_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"description":"When confirmation_token stops working, in UTC.","title":"Expires At"},"summary":{"anyOf":[{"$ref":"#/components/schemas/SendSummary"},{"type":"null"}],"default":null,"description":"What the confirm will send; null unless outcome is ready."},"problems":{"description":"Why the campaign cannot go out yet; empty unless outcome is not_ready.","items":{"$ref":"#/components/schemas/ReadinessProblem"},"title":"Problems","type":"array"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["message","outcome"],"title":"McpPrepareResponse","type":"object"},"McpRedoRequest":{"description":"The campaign to step forward, and the version to step forward to.","properties":{"campaign_id":{"description":"Numeric id of the campaign.","exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"version":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"The number beside the entry in get_campaign_history's output. Omit to redo the most recently undone change.","title":"Version"}},"required":["campaign_id"],"title":"McpRedoRequest","type":"object"},"McpRestoreRequest":{"description":"The campaign to step back, and the version to step back to.","properties":{"campaign_id":{"description":"Numeric id of the campaign.","exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"version":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"The number beside the entry in get_campaign_history's output. Omit to undo the most recent change.","title":"Version"}},"required":["campaign_id"],"title":"McpRestoreRequest","type":"object"},"McpRunListEntry":{"description":"One run in the listing: enough to identify a handle without polling it.","properties":{"run_id":{"description":"Run identifier. Pass to `poll_campaign_generation_status`.","title":"Run Id","type":"string"},"operation":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Which operation this run is: create, from_source, edit, copy or import.","title":"Operation"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"description":"When the run was started.","title":"Created At"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace the run's work is recorded under. Quote it when reporting a problem with this run.","title":"Trace Id"}},"required":["run_id"],"title":"McpRunListEntry","type":"object"},"McpRunListResponse":{"description":"This account's recent campaign-generation runs, newest first.","properties":{"runs":{"description":"Runs matching this page, newest first.","items":{"$ref":"#/components/schemas/McpRunListEntry"},"title":"Runs","type":"array"},"total":{"description":"Runs the index currently holds for this account, so a caller can page without walking to the end. Bounded and expiring, so this is recent activity rather than a lifetime count.","title":"Total","type":"integer"},"offset":{"description":"Zero-based pagination offset used for this page.","title":"Offset","type":"integer"},"limit":{"description":"Maximum number of runs returned in this page.","title":"Limit","type":"integer"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["runs","total","offset","limit"],"title":"McpRunListResponse","type":"object"},"McpRunStatus":{"description":"A campaign-generation run's progress, or its finished outcome.","properties":{"request_id":{"description":"The run identifier this snapshot describes.","title":"Request Id","type":"string"},"phase":{"description":"`queued`, `running`, `complete`, or `cancelled`.","examples":["queued","running","complete","cancelled"],"title":"Phase","type":"string"},"sections_completed":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Count of rendered sections so far, while running.","title":"Sections Completed"},"elapsed_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Seconds since this run started, while it is still running; null once it has finished. An import spends most of its life inside one model call that reports nothing, so a rising `elapsed_seconds` with no `sections_completed` is a healthy run rather than a stuck one.","title":"Elapsed Seconds"},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Terminal result kind, set only when `phase` is `complete`.","examples":["success","needs_input","busy","nothing_changed","nothing_saved","not_editable","not_supported","partial_success","unconfirmed","failed","not_enabled","unrecognized","unavailable"],"title":"Outcome"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Human-readable detail for a non-`success` outcome.","title":"Message"},"campaign_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"The campaign this run produced or acted on.","title":"Campaign Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign title, when available.","title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"AI-generated summary of the campaign content.","title":"Description"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign subject line, once the run has a campaign to report.","title":"Subject"},"preheader":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign preheader, once the run has a campaign to report.","title":"Preheader"},"designer_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Hosted Designer URL for the campaign, for MCP Apps openLink.","title":"Designer Url"},"changes_description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"What an edit or copy run actually changed.","title":"Changes Description"},"disclosures":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"default":null,"description":"What the run could not do, even though it produced a campaign.","title":"Disclosures"},"retryable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"Whether re-sending the same request is worth it. `None` while the run is still going. Never `true` when a campaign already exists.","title":"Retryable"},"campaign_persisted":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"`True` when a campaign exists for this run, whatever the outcome. Never generate, edit, or copy again for this same request while this is `true` — the campaign already exists, and doing so bills the account a second time. `None` while the run is still going.","title":"Campaign Persisted"},"status":{"description":"`in_progress`, `success`, or `error` — derived from `phase`/`outcome` for callers that don't read those.","enum":["in_progress","success","error"],"title":"Status","type":"string"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Failure or cancellation detail, set only when `status` is `error`.","title":"Error"},"step":{"anyOf":[{"enum":["selecting_template","generating_content","selecting_images","finalizing"],"type":"string"},{"type":"null"}],"default":null,"description":"Pre-migration workflow-stage label for callers that don't read `sections_completed`. Always `generating_content` while `phase` is `running` — an approximation, not a real stage — and `None` otherwise.","title":"Step"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace the run's work is recorded under. Quote it when reporting a problem with this run.","title":"Trace Id"}},"required":["request_id","phase","status"],"title":"Run Status Result","type":"object"},"McpSaveTemplateRequest":{"description":"The campaign to save into the template library, and the template's name.","properties":{"campaign_id":{"description":"Numeric id of the campaign to save as a template.","exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"template_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name for the new template. Omit to keep the campaign's own name.","title":"Template Name"}},"required":["campaign_id"],"title":"McpSaveTemplateRequest","type":"object"},"McpSendResponse":{"description":"How a confirm or an unschedule ended.","properties":{"message":{"description":"The answer, written for the user. Relay it as it stands.","title":"Message","type":"string"},"outcome":{"$ref":"#/components/schemas/SendOutcome","description":"How the call ended."},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["message","outcome"],"title":"McpSendResponse","type":"object"},"McpStartResponse":{"description":"Handle for a started edit or copy run. Names the affected campaign directly, when already known, so a caller doesn't have to poll just to learn which campaign a call acted on.","properties":{"request_id":{"description":"Run identifier. Pass to `poll_campaign_generation_status`.","title":"Request Id","type":"string"},"campaign_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"The affected campaign, when already known. `null` for a copy — poll for the new campaign's id once the run finishes.","title":"Campaign Id"},"disclosures":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"default":null,"description":"What this call could not do, even though it started the run.","title":"Disclosures"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace the run's work is recorded under. Quote it when reporting a problem with this run.","title":"Trace Id"}},"required":["request_id"],"title":"Campaign Start Result","type":"object"},"MemoryBulkResponse":{"description":"The user's memories after a bulk save.","required":["memories"],"properties":{"memories":{"description":"Every memory the user now has, with the ids and timestamps the save gave them.","type":"array","items":{"$ref":"#/components/schemas/MemoryResource"}}},"type":"object"},"MemoryGuardrailViolationResponse":{"description":"The content of a memory was rejected by the content guardrail.","required":["type","message"],"properties":{"type":{"description":"Always guardrail_violation.","type":"string","example":"guardrail_violation"},"message":{"description":"A message for the user, translated into their language.","type":"string","example":"This content cannot be saved."}},"type":"object"},"MemoryItemResponse":{"description":"A single memory. It is under the memories key even though there is only one.","required":["memories"],"properties":{"memories":{"$ref":"#/components/schemas/MemoryResource","description":"The memory that was created or changed."}},"type":"object"},"MemoryLimitExceededResponse":{"description":"The user's memories would come to more than 1000 characters in total.","required":["type","message"],"properties":{"type":{"description":"Always memory_limit_exceeded.","type":"string","example":"memory_limit_exceeded"},"message":{"description":"Why the write was refused.","type":"string","example":"Total character limit for all memories exceeded. Please reduce the content of existing memories before adding new ones."}},"type":"object"},"MemoryListMeta":{"description":"Paging details for a list of memories.","required":["total"],"properties":{"total":{"description":"How many memories the user has in total, before limit and offset.","type":"integer","example":12}},"type":"object"},"MemoryListResponse":{"description":"One page of the user's memories, newest first.","required":["meta","memories"],"properties":{"meta":{"$ref":"#/components/schemas/MemoryListMeta","description":"Paging details."},"memories":{"description":"The memories on this page.","type":"array","items":{"$ref":"#/components/schemas/MemoryResource"}}},"type":"object"},"MemoryRequest":{"description":"A memory to save. Creating or updating a memory reads only content; a bulk save reads every field.","required":["content"],"properties":{"memoryId":{"description":"Id of an existing memory to keep. Read only by the bulk save; omit it to have the server match or assign one.","type":["string","null"],"example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"},"content":{"description":"The text of the memory. At most 4000 characters, without emoji. All of a user's memories together may not exceed 1000 characters.","type":"string","example":"Prefers short, friendly subject lines."},"source":{"description":"Where the memory came from, in the caller's own words. Stored as given and read only by the bulk save.","type":["string","null"],"example":"conversation"},"createdAt":{"description":"When the memory was created. Read only by the bulk save, which keeps the stored value when it is omitted.","type":"string","format":"date-time","example":"2026-10-19T14:30:00Z"},"updatedAt":{"description":"Ignored: the server sets it whenever a memory changes.","type":"string","format":"date-time","example":"2026-10-19T14:31:00Z"},"sourceConversationId":{"description":"Id of the conversation the memory was taken from. Read only by the bulk save.","type":["string","null"],"example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"}},"type":"object"},"MemoryResource":{"description":"A fact the AI agent remembers about the user.","required":["memoryId","content","source","createdAt","updatedAt","sourceConversationId"],"properties":{"memoryId":{"description":"Id of the memory, assigned when it is created.","type":"string","example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"},"content":{"description":"The text of the memory.","type":"string","example":"Prefers short, friendly subject lines."},"source":{"description":"Where the memory came from, as the caller who saved it described it. Empty or null when the caller gave none.","type":["string","null"],"example":"conversation"},"createdAt":{"description":"When the memory was created, as an ISO 8601 UTC timestamp.","type":"string","format":"date-time","example":"2026-10-19T14:30:00.000000Z"},"updatedAt":{"description":"When the memory was last changed, as an ISO 8601 UTC timestamp.","type":"string","format":"date-time","example":"2026-10-19T14:31:00.000000Z"},"sourceConversationId":{"description":"Id of the conversation the memory was taken from. Null when it was not taken from a conversation.","type":["string","null"],"example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"}},"type":"object"},"MessageBulkDeleteResult":{"description":"Outcome of a bulk message delete, reported per message id.","required":["succeeded","message","deleted","hidden","failed"],"properties":{"succeeded":{"description":"1 when the call answered 200, otherwise 0.","type":"integer"},"message":{"description":"What happened, in the language of the account.","type":"string"},"deleted":{"description":"Ids of the messages no campaign used, which were deleted together with their files.","type":"array","items":{"type":"integer"}},"hidden":{"description":"Ids of the messages a campaign uses. They are hidden rather than deleted, so the campaign keeps its history, and GET /messages no longer lists them.","type":"array","items":{"type":"integer"}},"failed":{"description":"Requested messages that were neither deleted nor hidden, each with the reason.","type":"array","items":{"required":["id","reason"],"properties":{"id":{"description":"Id of the message that was not deleted.","type":"integer"},"reason":{"description":"Why it was not deleted, in the language of the account.","type":"string"}},"type":"object"}}},"type":"object"},"MessageSourceEnum":{"enum":["INBOUND","INBOX","AUTO_RESPONSE","API","BROADCAST","FLOW"],"type":"string","description":"* `INBOUND` - Inbound\n* `INBOX` - Inbox\n* `AUTO_RESPONSE` - Auto Response\n* `API` - Api\n* `BROADCAST` - Broadcast\n* `FLOW` - Flow"},"MessageStatusEnum":{"enum":["new","retry","accepted","sending","sent","receiving","received","delivered","undelivered","failed","read","deleted"],"type":"string","description":"* `new` - New\n* `retry` - Retry\n* `accepted` - Accepted\n* `sending` - Sending\n* `sent` - Sent\n* `receiving` - Receiving\n* `received` - Received\n* `delivered` - Delivered\n* `undelivered` - Undelivered\n* `failed` - Failed\n* `read` - Read\n* `deleted` - Deleted"},"MessageTypeEnum":{"enum":["audio","voice","button","document","text","image","interactive","order","sticker","system","unknown","video","unsupported","location","contacts","template","reaction","ephemeral","request_welcome"],"type":"string","description":"* `audio` - Audio\n* `voice` - Voice\n* `button` - Button\n* `document` - Document\n* `text` - Text\n* `image` - Image\n* `interactive` - Interactive\n* `order` - Order\n* `sticker` - Sticker\n* `system` - System\n* `unknown` - Unknown\n* `video` - Video\n* `unsupported` - Unsupported\n* `location` - Location\n* `contacts` - Contacts\n* `template` - Template\n* `reaction` - Reaction\n* `ephemeral` - Ephemeral\n* `request_welcome` - Request Welcome"},"MicrosoftDynamicsConnectErrors":{"type":"object","description":"Returned with status 422.","properties":{"errors":{"type":"array","description":"One entry per missing field.","items":{"type":"string","description":"`<field> was not provided`."},"example":["external_id was not provided"]}}},"MicrosoftDynamicsConnectRequest":{"type":"object","required":["name","external_id"],"properties":{"name":{"type":"string","description":"Name to store on the connection.","example":"msd name"},"external_id":{"type":"string","description":"Identifier of the Dynamics organisation, stored as the connection's external ID.","example":"msd id"}}},"MicrosoftDynamicsConnectResult":{"type":"object","properties":{"connection":{"$ref":"#/components/schemas/MicrosoftDynamicsConnection"}}},"MicrosoftDynamicsConnection":{"type":"object","description":"The Microsoft Dynamics connection model encoded with PHP's json_encode rather than the API serializer, so the body carries the model's public properties: the row's column values under `fields`, beside internal bookkeeping properties.","properties":{"fields":{"type":"object","description":"Column values of the connection row keyed by database column name, among them `service` (`Microsoft Dynamics`), `connection_type`, `externalid`, `name`, `is_internal`, `logo_url`, `link_url` and `udate`.","additionalProperties":{"description":"A column value."}},"_original":{"description":"Column values as they were loaded, before this request changed them."},"_relationships":{"description":"Loaded relationships of the model; empty here."},"_empty_field":{"description":"Internal placeholder of the model; null."},"service_name":{"type":"string","description":"Internal property of the model; empty."}}},"MilestoneMetrics":{"description":"The account's current values for the metrics that milestones are evaluated against. One key per metric; the insights engine maps each milestone event type to one of these keys (contacts_added reads contact_count).","required":["contact_count"],"properties":{"contact_count":{"description":"The account's contact count as the subscriber limit reports it: every contact when the account is billed on all contacts or uses the engaged-contacts limit, otherwise the contacts active on at least one list. Read from the account's subscriber-count cache when it holds a value, so it can lag the database by the cache window; otherwise counted from the database and cached.","type":"integer","example":1250}},"type":"object"},"NextActionEnum":{"enum":["ANY_RESPONSE","BUTTON_RESPONSE","CONTINUE"],"type":"string","description":"* `ANY_RESPONSE` - Any Response\n* `BUTTON_RESPONSE` - Button Response\n* `CONTINUE` - Continue"},"NotFound":{"type":"object","description":"No activity recipient record has the id.","properties":{"message":{"type":"string","description":"Says that no record has the id."}}},"NullEnum":{"enum":[null]},"NylasBounceDetectedOrigin":{"description":"The email that bounced. Its fields are not validated.","required":["id"],"properties":{"id":{"description":"Nylas ID of the email that bounced, matched against the deal emails' external message IDs. When no deal email matches, only the contact's bounce is recorded.","type":"string","example":"191fba82e1219d01"},"mimeId":{"description":"Message-Id of the email that bounced. Accepted but not used.","type":"string","example":"<sent-message@example.com>"}},"type":"object"},"NylasBounceDetectedWebhook":{"description":"A bounce of an email the connected mailbox sent, as AC Nylas reports it. Keys may also be sent in snake_case (`grant_id`, `bounced_addresses`, `bounce_reason`, `mime_id`). `grantId` and `bouncedAddresses` are validated (422); a missing `code`, `origin` or `origin.id` fails with 500.","required":["grantId","bouncedAddresses","code","origin"],"properties":{"grantId":{"description":"Nylas grant of the mailbox that sent the email. Must not be blank; used only in logs.","type":"string","example":"da88e4c9-4ac0-440d-8463-c51634257883"},"bounceReason":{"description":"Why the email bounced, as the receiving server reported it. Accepted but not used.","type":"string","example":"Mailbox does not exist"},"bouncedAddresses":{"description":"The one address that bounced. Must not be blank. Its recipient rows on the bounced deal email are marked bounced, and the contact with this address gets a bounce record unless it already has one.","type":"string","example":"bounced@example.com"},"type":{"description":"Bounce type from Nylas. Accepted but not used: the bounce type comes from `code`.","type":"string","example":"hard_bounce"},"code":{"description":"SMTP status and enhanced status code, such as `550 5.1.1`. Only the enhanced code (`5.1.1`) is read. Without an enhanced code AC tracks, no contact bounce is recorded; the contact's bounce record is always stored as a hard bounce. Only a hard-bounce code on an outbound deal email (automated or direct) enters the contact into bounce-triggered automations.","type":"string","example":"550 5.1.1"},"origin":{"$ref":"#/components/schemas/NylasBounceDetectedOrigin","description":"The email that bounced."}},"type":"object"},"NylasLinkClickedWebhook":{"description":"The `data.object` of a Nylas v3 `message.link_clicked` notification for a tracked outbound email. A field sent with a JSON type other than the one listed fails the request with 422.","required":["label","link_data","recents","timestamp"],"properties":{"link_data":{"description":"The tracked links of the message with their click counts. The entry at the last `recents` item's `link_index` is the clicked link. Must not be empty.","type":"array","items":{"properties":{"url":{"description":"URL of the link, matched against the links Hosted tracked for the email.","type":"string","example":"https://example.com/pricing"},"count":{"description":"Number of times the link has been clicked.","type":"integer","example":1}},"type":"object"}},"message_id":{"description":"Nylas ID of the message the link is in. Accepted but not used: the email is identified by `label`.","type":"string","example":"191fba82e1219d01"},"object":{"description":"Nylas object type. Accepted but not used.","type":"string","example":"message"},"label":{"description":"JSON-encoded tracking label Hosted attached to the email when it sent it. It must decode to an object naming the email (`series_block_id` for an automated email, `direct_outbound_email_id` for a direct one), the contact (`subscriber_id`, `subscriber_email`, and `subscriber_series_id` for an automated email) and the tracked links (`links_with_ids`, a list of objects mapping a link ID to its URL); `ac_account_id`, when present, must be this account.","type":"string","example":"{\"open_link_id\":123,\"series_block_id\":2,\"subscriber_email\":\"jane@example.com\",\"subscriber_id\":544,\"subscriber_series_id\":223,\"ac_account_id\":5469,\"links_with_ids\":[{\"348\":\"https://example.com/pricing\"}]}"},"recents":{"description":"Most recent clicks, oldest first. The last one is recorded as the click. Must not be empty.","type":"array","items":{"properties":{"click_id":{"description":"Nylas ID of the click. Not used.","type":"integer","example":0},"ip":{"description":"IP address of the click.","type":"string","example":"3.228.136.234"},"link_index":{"description":"Position in `link_data` of the clicked link.","type":"integer","example":0},"timestamp":{"description":"Unix timestamp of the click.","type":"integer","example":1695480410},"user_agent":{"description":"User agent of the click.","type":"string","example":"Mozilla/5.0"}},"type":"object"}},"sender_app_id":{"description":"Nylas application that sent the message. Accepted but not used.","type":"string","example":"1234"},"timestamp":{"description":"Unix timestamp of the notification. Must not be 0.","type":"integer","example":1695480410}},"type":"object"},"NylasMessageBody":{"description":"The body of an email already stored as a deal email. A field sent with a JSON type other than the one listed fails the request with 422; a null or missing field keeps its empty default.","properties":{"deal_email_id":{"description":"ID of the deal email the body belongs to, as returned in `result.deal_email_id` by POST /nylas/v3/message_created. Must be a JSON integer: a numeric string fails with 422.","type":"integer","example":12},"body":{"description":"HTML body of the email. Published with the deal email for email body processing; the stored deal email is not changed.","type":"string","example":"<p>Thanks for the call today.</p>"},"thread_id":{"description":"Nylas ID of the thread the email belongs to, published with the body.","type":"string","example":"191fba82e1219d00"}},"type":"object"},"NylasMessageCreatedWebhook":{"description":"One email the connected mailbox sent or received, as a Nylas v3 message object. A field sent with a JSON type other than the one listed fails the request with 422; a null or missing field keeps its empty default.","properties":{"attachments":{"description":"Attachments of the email. Each one is stored in the deal email's files from its `id`, `filename`, `content_type` and `size`.","type":"array","items":{"properties":{"id":{"description":"Nylas ID of the attachment.","type":"string"},"filename":{"description":"File name of the attachment.","type":"string"},"content_type":{"description":"MIME type of the attachment.","type":"string"},"size":{"description":"Size of the attachment in bytes.","type":"integer"}},"type":"object"}},"bcc":{"description":"Blind-copied recipients. Their addresses are stored lowercased on the deal email.","type":"array","items":{"properties":{"email":{"description":"Email address.","type":"string","example":"jane@example.com"},"name":{"description":"Display name. Not used.","type":"string","example":"Jane Doe"}},"type":"object"}},"body":{"description":"HTML body of the email. Stored, trimmed, as the deal email's HTML and plain-text message; when it is not empty it is also published for email body processing.","type":"string","example":"<p>Thanks for the call today.</p>"},"cc":{"description":"Copied recipients. Their addresses are stored lowercased on the deal email and matched to contacts, like `to`.","type":"array","items":{"properties":{"email":{"description":"Email address.","type":"string","example":"jane@example.com"},"name":{"description":"Display name. Not used.","type":"string","example":"Jane Doe"}},"type":"object"}},"created_at":{"description":"Unix timestamp of when Nylas created the message object. Accepted but not used.","type":"integer","example":1721670510},"date":{"description":"Unix timestamp of when the email was sent, stored as the deal email's date. An email dated more than one year ago is not stored.","type":"integer","example":1721670500},"folders":{"description":"Folders or labels the email is in. The first one is stored as the deal email's folder.","type":"array","items":{"type":"string"},"example":["INBOX"]},"from":{"description":"Sender, as a one-item list. Its address, lowercased, is the deal email's sender and is matched to a contact; when it is a forward from the reply-tracking domain, the first `reply_to` address is used instead.","type":"array","items":{"properties":{"email":{"description":"Email address.","type":"string","example":"jane@example.com"},"name":{"description":"Display name. Not used.","type":"string","example":"Jane Doe"}},"type":"object"}},"grant_id":{"description":"Nylas grant of the mailbox that synced the email. It must belong to a connected email of the account, otherwise nothing is stored.","type":"string","example":"5b6e29b0-7245-47ce-be02-16c4717751de"},"id":{"description":"Nylas ID of the message, stored as the deal email's external message ID. An email already stored under this ID is skipped.","type":"string","example":"191fba82e1219d01"},"object":{"description":"Nylas object type, `message`. Accepted but not used.","type":"string","example":"message"},"reply_to":{"description":"Reply-to addresses. Read only to find the real sender of a forward from the reply-tracking domain.","type":"array","items":{"properties":{"email":{"description":"Email address.","type":"string","example":"jane@example.com"},"name":{"description":"Display name. Not used.","type":"string","example":"Jane Doe"}},"type":"object"}},"snippet":{"description":"Short plain-text preview of the email, stored as the deal email's message when `body` is empty. An email with an empty snippet and the subject `Attachment` is an attachment notification and is skipped.","type":"string","example":"Thanks for the call today."},"starred":{"description":"Whether the email is starred in the mailbox. Accepted but not used.","type":"boolean","example":false},"subject":{"description":"Subject line, stored on the deal email.","type":"string","example":"Proposal follow-up"},"thread_id":{"description":"Nylas ID of the thread the email belongs to, stored on the deal email.","type":"string","example":"191fba82e1219d00"},"to":{"description":"Recipients. Their addresses are stored lowercased on the deal email; contacts with these addresses, the `cc` addresses or the sender's address get the email on their activity stream and on their deals.","type":"array","items":{"properties":{"email":{"description":"Email address.","type":"string","example":"jane@example.com"},"name":{"description":"Display name. Not used.","type":"string","example":"Jane Doe"}},"type":"object"}},"unread":{"description":"Whether the email is unread in the mailbox. Accepted but not used.","type":"boolean","example":true},"reply_to_message_id":{"description":"Message-Id of the email this one replies to. Used to link the reply to the original email when `headers` has no `In-Reply-To`.","type":"string","example":"<original-message@example.com>"},"headers":{"description":"Email headers keyed by header name. `Message-Id` is stored as the deal email's message ID (`id` when it is missing) and an email whose `Message-Id` or `X-Inbox-Id` is already stored is skipped; `In-Reply-To` and `References` link a reply to the email it answers.","type":"object","example":{"Message-Id":"<reply-message@example.com>","In-Reply-To":"<original-message@example.com>"},"additionalProperties":{"type":"string"}}},"type":"object"},"NylasMessageOpenedWebhook":{"description":"The `data.object` of a Nylas v3 `message.opened` notification for a tracked outbound email. A field sent with a JSON type other than the one listed fails the request with 422.","required":["label","message_data","recents","timestamp"],"properties":{"message_data":{"description":"Open statistics of the message. `count`, the number of opens so far, is recorded on the email's open link. Must not be empty.","properties":{"count":{"description":"Number of times the message has been opened.","type":"integer","example":1}},"type":"object"},"message_id":{"description":"Nylas ID of the opened message. Accepted but not used: the email is identified by `label`.","type":"string","example":"191fba82e1219d01"},"object":{"description":"Nylas object type. Accepted but not used.","type":"string","example":"message"},"label":{"description":"JSON-encoded tracking label Hosted attached to the email when it sent it. It must decode to an object naming the email (`series_block_id` for an automated email, `direct_outbound_email_id` for a direct one), the contact (`subscriber_id`, `subscriber_email`, and `subscriber_series_id` for an automated email) and `open_link_id`, the open link the open is recorded on; `ac_account_id`, when present, must be this account.","type":"string","example":"{\"open_link_id\":123,\"series_block_id\":2,\"subscriber_email\":\"jane@example.com\",\"subscriber_id\":544,\"subscriber_series_id\":223,\"ac_account_id\":5469}"},"recents":{"description":"Most recent opens of the message, oldest first. The last one is recorded as the open. Must not be empty.","type":"array","items":{"properties":{"ip":{"description":"IP address of the open; of a comma-separated list, the first address is recorded.","type":"string","example":"3.228.136.234"},"user_agent":{"description":"User agent of the open.","type":"string","example":"Mozilla/5.0"},"timestamp":{"description":"Unix timestamp of the open.","type":"integer","example":1695480410}},"type":"object"}},"sender_app_id":{"description":"Nylas application that sent the message. Accepted but not used.","type":"string","example":"1234"},"timestamp":{"description":"Unix timestamp of the notification. Must not be 0.","type":"integer","example":1695480410}},"type":"object"},"NylasThreadRepliedWebhook":{"description":"The `data.object` of a Nylas v3 `thread.replied` notification: someone replied to a tracked outbound email. A field sent with a JSON type other than the one listed fails the request with 422.","required":["label","message_id","root_message_id","timestamp"],"properties":{"from_self":{"description":"True when the reply came from the connected mailbox itself; such a reply is not recorded.","type":"boolean","example":false},"label":{"description":"JSON-encoded tracking label Hosted attached to the original email when it sent it. It must decode to an object naming the email (`series_block_id` for an automated email, `direct_outbound_email_id` for a direct one) and the contact (`subscriber_id`, `subscriber_email`, and `subscriber_series_id` for an automated email); `ac_account_id`, when present, must be this account. The reply is recorded only when its sender is that contact.","type":"string","example":"{\"series_block_id\":2,\"subscriber_email\":\"jane@example.com\",\"subscriber_id\":544,\"subscriber_series_id\":223,\"ac_account_id\":5469}"},"message_id":{"description":"Nylas ID of the reply. The reply must already be stored as a deal email, synced through POST /nylas/v3/message_created, otherwise the request fails with 404.","type":"string","example":"191fba82e1219d05"},"object":{"description":"Nylas object type. Accepted but not used.","type":"string","example":"message"},"reply_data":{"description":"Nylas reply details. Accepted but not used.","type":"object"},"reply_to_message_id":{"description":"Message-Id of the email the reply answers. Either it or the label's `open_link_id` or `links_with_ids` must not be empty.","type":"string","example":"<original-message@example.com>"},"root_message_id":{"description":"Nylas ID of the first email of the thread. For an automated email it identifies the automation step the reply is recorded against.","type":"string","example":"191fba82e1219d01"},"sender_app_id":{"description":"Nylas application that sent the original email. Accepted but not used.","type":"string","example":"1234"},"thread_id":{"description":"Nylas ID of the thread. Accepted; only logged.","type":"string","example":"191fba82e1219d00"},"timestamp":{"description":"Unix timestamp of the reply, recorded as the time of the contact's reply. Must not be 0.","type":"integer","example":1695480410}},"type":"object"},"OmniChannelLinkData":{"type":"object","properties":{"id":{"type":["integer","string"]},"link_id":{"type":["integer","string"]},"message_id":{"type":["integer","string"]},"subscriber_id":{"type":["integer","string"]},"type":{"type":"string"},"event_timestamp":{"type":["string","null"]},"created_timestamp":{"type":"string"},"updated_timestamp":{"type":"string"}}},"OnboardingAsyncDoneResponse":{"description":"Acknowledgement that the worker job ran. The job outcome is not reported here: a failed selection marks the account in error and a failed personalization marks the recipe error.","required":["message"],"properties":{"message":{"description":"Always done.","type":"string","example":"done"}},"type":"object"},"OnboardingCardGenerateDispatchRequest":{"description":"Queue payload for generating one personalized onboarding card. OnboardingContentService::createDynamicCards builds it from the brand kit, the account's onboarding answers and the card template, one per template, when POST /ai/onboarding/cards/triggerGeneration runs.","required":["external_identifier","company_name","industries","brand_long_description","brand_short_description","template_slug","template_title","template_action_type","template_category"],"properties":{"external_identifier":{"description":"external_identifier of the pending card record written when the job was queued; the job overwrites it with the result. A record that no longer exists is skipped.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"company_name":{"description":"Name of the brand kit, used as the company name in the prompt.","type":"string","example":"Acme Outdoors"},"industries":{"description":"The brand kit's industries, comma-separated.","type":"string","example":"Retail, Outdoor equipment"},"brand_long_description":{"description":"The brand kit's long description.","type":"string","example":"Acme Outdoors sells camping and hiking gear to weekend adventurers across North America."},"brand_short_description":{"description":"The brand kit's short description.","type":"string","example":"Gear for weekend adventurers"},"template_slug":{"description":"Slug of the card template being generated; stored on the card.","type":"string","example":"welcome_series"},"template_title":{"description":"The template's default title, given to the model as the card's topic and stored when generation fails.","type":"string","example":"Build a welcome series"},"template_action_type":{"description":"The template's action type, stored on the card.","type":"string","enum":["prompt","link"],"example":"prompt"},"template_action_prompt":{"description":"The template's default action prompt, given to the model and stored when generation fails; null for link cards.","type":["string","null"],"example":"Build a welcome series for my new subscribers"},"template_example_email":{"description":"The template's default example email, given to the model and stored when generation fails; null when the template has none.","type":["string","null"],"example":"Welcome aboard! Here is what to expect from us."},"template_category":{"description":"The template's category; picks the system prompt and is stored on the card.","type":"string","example":"automation"},"brandkit_uuid":{"description":"UUID of the brand kit the card belongs to, stored on the card; null for the fallback set. Must name a brand kit of the account when given.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"onboarding_log_context":{"description":"The account's signup onboarding answers, as OnboardingLogContext::toArray writes them, given to the model as extra context. Every key is a string, empty when unanswered; all twelve are sent.","properties":{"info_name":{"description":"Name given at signup.","type":"string","example":"Jane Doe"},"info_business_contacts":{"description":"How many contacts the business has.","type":"string","example":"5,000 - 10,000"},"info_business_industry":{"description":"Industry of the business.","type":"string","example":"Retail"},"info_channels":{"description":"Marketing channels the business uses, comma-separated.","type":"string","example":"email-marketing,sms"},"info_country_code_region":{"description":"Region of the business.","type":"string","example":"Americas - US"},"info_country_code_country":{"description":"Country code of the business.","type":"string","example":"us"},"info_work_type":{"description":"Work type answer.","type":"string","example":"marketing"},"info_platform_intention":{"description":"What the owner means to use the platform for.","type":"string","example":"grow-audience"},"info_experience_level":{"description":"Experience level with marketing tools.","type":"string","example":"beginner"},"info_business_empcount":{"description":"Company size (employee count).","type":"string","example":"1-10"},"info_products":{"description":"Tools or products the business already uses.","type":"string","example":"Shopify"},"info_website":{"description":"Website of the business.","type":"string","example":"https://acme-outdoors.example"}},"type":"object"}},"type":"object"},"OnboardingCardGeneratedResponse":{"description":"Acknowledgement that the queued card generation ran. It says nothing about the outcome: a card the model could not write is stored as failed, which GET /ai/onboarding/cards reports.","required":["success"],"properties":{"success":{"description":"Always true.","type":"boolean","example":true}},"type":"object"},"OnboardingCardRecord":{"description":"One onboarding card: a suggested next step for the account, either hard-coded from its template or personalized from the brand kit by the model.","required":["category","slug","title","status","actionType","actionPrompt","exampleEmail","brandkitUuid","personalized"],"properties":{"category":{"description":"Template category of the card (brandkit, automation, contacts-import, campaign, insight, sms, google-ads, scheduled-task, ...). Decides which permissions the user needs to see it.","type":"string","example":"automation"},"slug":{"description":"Template slug identifying the card within the set.","type":"string","example":"welcome_series"},"title":{"description":"Card title: the template's text, or the model's when personalized.","type":"string","example":"Welcome new Acme subscribers"},"status":{"description":"Generation state. pending: a generation job is queued or running. success: the card is ready. failed: the job failed, could not be queued, or the card was stuck for more than 12 hours. stuck: pending for more than 5 minutes.","type":"string","enum":["pending","success","failed","stuck"],"example":"success"},"actionType":{"description":"What the card does when clicked, always from the live template: prompt sends actionPrompt to the AI chat, link opens a page.","type":"string","enum":["prompt","link"],"example":"prompt"},"actionPrompt":{"description":"Prompt the card sends to the AI chat, from the live template; null for link cards.","type":["string","null"],"example":"Build a welcome series for my new subscribers"},"exampleEmail":{"description":"Example email copy shown on the card, or null when the template has none.","type":["string","null"],"example":"Welcome to Acme! Here is what to expect from us."},"brandkitUuid":{"description":"UUID of the brand kit the card was generated for; null for the fallback cards generated without one.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"personalized":{"description":"True when the title, action prompt and example email were written by the model from the brand kit; false for static cards and for cards that failed before personalization.","type":"boolean","example":true}},"type":"object"},"OnboardingCardsStatusResponse":{"description":"The onboarding cards of one brand kit and where their generation stands.","required":["status","personalized","cards"],"properties":{"status":{"description":"Where generation stands for the set. not_started: no card record exists yet. in_progress: a returned card is still pending. stuck: no card is pending but one has been pending for more than 5 minutes. complete: every returned card is success or failed.","type":"string","enum":["not_started","in_progress","stuck","complete"],"example":"complete"},"personalized":{"description":"True when at least one stored card of the set was personalized by the model, counting cards left out of the list below.","type":"boolean","example":true},"cards":{"description":"The cards the user may see, in template order, at most 10. Cards whose template no longer exists, whose visibility requirement is not met or that need a permission the user lacks are left out.","type":"array","items":{"$ref":"#/components/schemas/OnboardingCardRecord"}}},"type":"object"},"OnboardingCardsTriggerGenerationRequest":{"description":"Which cards to generate and whether to keep the ones already done. The body may be empty.","properties":{"brandkitUuid":{"description":"UUID of one of the account's brand kits to generate the cards for. Omitted: the cards are generated without brand context, as the fallback set, and the in-progress check is skipped.","type":["string","null"],"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"skipExisting":{"description":"False (the default): delete every existing card of the set and regenerate all of them. True: keep the cards already generated successfully, delete only those whose template no longer exists, and generate the rest.","type":"boolean","example":false}},"type":"object"},"OnboardingCardsTriggeredResponse":{"description":"Acknowledgement that the static cards were written and a generation job queued for each personalized card. The cards themselves are not ready yet: poll GET /ai/onboarding/cards.","required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"}},"type":"object"},"OnboardingChecklistItem":{"description":"One step of the onboarding checklist and whether the account has done it.","required":["slug","category","title","subtitle","actionType","actionPrompt","checked"],"properties":{"slug":{"description":"Identifier of the step: brandkit, goal, contacts_import, campaign, automation, apps, sms_registration, sms_form_opt_in or sms_registration_error.","type":"string","example":"brandkit"},"category":{"description":"Category of the step, deciding which permissions the user needs to see it.","type":"string","example":"brandkit"},"title":{"description":"Title of the step, in the account's language.","type":"string","example":"Add Brand Kit"},"subtitle":{"description":"One-line explanation shown under the title.","type":"string","example":"Tell us your brand URL to generate personalized assets"},"actionType":{"description":"What the step does when clicked: prompt sends actionPrompt to the AI chat, link opens a page.","type":"string","enum":["prompt","link"],"example":"link"},"actionPrompt":{"description":"Prompt the step sends to the AI chat; null for link steps.","type":["string","null"],"example":"I want to import my contacts. Help me get started."},"checked":{"description":"True when the account meets the step's requirement (has a brand kit, has goals, ...). A step with no requirement is never checked.","type":"boolean","example":false}},"type":"object"},"OnboardingChecklistResponse":{"description":"The account's onboarding checklist.","required":["all_checked","items"],"properties":{"all_checked":{"description":"True when every returned item is checked; also true when no item is returned.","type":"boolean","example":false},"items":{"description":"The steps the user may see, in template order. Steps whose visibility requirement is not met or that need a permission the user lacks are left out.","type":"array","items":{"$ref":"#/components/schemas/OnboardingChecklistItem"}}},"type":"object"},"OnboardingPersonalizedRecipe":{"description":"An automation recipe selected for the account during onboarding and personalized by the AI model. hash, name and description are always present (null until personalization fills them); the other keys are left out, never null, until the step that fills them has run.","required":["hash","name","description"],"properties":{"hash":{"description":"Hash of the recipe template the recipe was selected from.","type":["string","null"],"example":"a1b2c3d4"},"name":{"description":"Recipe name rewritten for the account. Null until metadata personalization has run.","type":["string","null"],"example":"Welcome new Acme Fitness members"},"description":{"description":"Recipe description rewritten for the account. Null until metadata personalization has run.","type":["string","null"],"example":"Greet new members with a three-email welcome series introducing your classes and trainers."},"originalName":{"description":"The template's own name. Left out when empty.","type":"string","example":"Welcome series"},"originalDescription":{"description":"The template's own description. Left out when empty.","type":"string","example":"Greet new contacts with a three-email welcome series."},"touchpoints":{"description":"Number of touchpoints (messages) in the recipe, copied from the template when the recipe is stored. Left out until then.","type":"integer","example":3},"personalizationStatus":{"description":"Where personalization of this recipe stands: queued when stored, in_progress while the worker runs, done or error when it finished, used once the recipe was imported as an automation. Left out when empty.","type":"string","enum":["queued","in_progress","done","error","used"],"example":"done"},"personalizedVariables":{"description":"The template's content variables rewritten for the account, keyed as the template's metadata names them. Left out until variable personalization has run and when it produced nothing.","type":"object","example":{"email_1_subject":"Welcome to Acme Fitness"}},"seriesid":{"description":"Id of the automation the recipe was imported as. Left out until the recipe is used.","type":"integer","example":42}},"type":"object"},"OnboardingRecipeStatusResponse":{"description":"Outcome of a request to select onboarding recipes: what the server did with it.","required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","example":"done"},"status":{"description":"done: recipes are already stored for the account, nothing was started. redlocked: a selection job is already running, nothing was started. dispatched: a selection job was queued.","type":"string","enum":["done","redlocked","dispatched"],"example":"dispatched"}},"type":"object"},"OnboardingRecipesResponse":{"description":"The personalized onboarding recipes stored for the account that have not been used yet.","required":["recipes"],"properties":{"recipes":{"description":"The stored recipes not yet imported as automations. Empty once every stored recipe has been used.","type":"array","items":{"$ref":"#/components/schemas/OnboardingPersonalizedRecipe"}}},"type":"object"},"OverviewFavoriteRequest":{"description":"The goal to add to the calling user's favorites, and the favorites list it goes in.","required":["domain","section","goalId"],"properties":{"domain":{"description":"Area the favorites list belongs to. The app sends overview, the only domain DELETE /overview/favorites/{goalId} removes from.","type":"string","example":"overview"},"section":{"description":"Which favorites list within the domain. The app sends goals, the only section DELETE /overview/favorites/{goalId} removes from.","type":"string","example":"goals"},"goalId":{"description":"ID of the business goal to favorite, as a JSON number. It must be an existing label or business goal: an unknown ID answers 422, as does a string.","type":"integer","example":12}},"type":"object"},"OverviewSortOrderConfigurationRequest":{"description":"Which items the calling user pins to a section of the Overview goals dashboard, in display order.","required":["domain","section","config"],"properties":{"domain":{"description":"Area the configuration belongs to. The app sends overview.","type":"string","example":"overview"},"section":{"description":"Which section of the dashboard: initiatives for business goals, conversions for conversions.","type":"string","example":"initiatives"},"config":{"description":"The pinned items, in display order. Replaces the list saved before; an empty list unpins everything.","type":"array","items":{"required":["id"],"properties":{"id":{"description":"ID of the business goal or conversion.","type":["string","integer"],"example":"12"}},"type":"object"},"example":[{"id":"12"},{"id":"31"}]}},"type":"object"},"PageDO":{"title":"PageDO","type":"object","properties":{"current_page":{"type":"integer","format":"int32"},"last_page":{"type":"integer","description":"Last page of results","format":"int32"},"per_page":{"type":"integer","format":"int32"},"total":{"type":"integer","description":"The total number of matches","format":"int32"}}},"PaginatedConversationReadSimpleList":{"type":"object","required":["count","results"],"properties":{"count":{"type":"integer","example":123},"next":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=4"},"previous":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=2"},"results":{"type":"array","items":{"$ref":"#/components/schemas/ConversationReadSimple"}}}},"PaginatedFlowExecutionContactListSimpleList":{"type":"object","required":["count","results"],"properties":{"count":{"type":"integer","example":123},"next":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=4"},"previous":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=2"},"results":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionContactListSimple"}}}},"PaginatedFlowExecutionListList":{"type":"object","required":["count","results"],"properties":{"count":{"type":"integer","example":123},"next":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=4"},"previous":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=2"},"results":{"type":"array","items":{"$ref":"#/components/schemas/FlowExecutionList"}}}},"PaginatedWhatsAppTemplateSimpleReadList":{"type":"object","required":["count","results"],"properties":{"count":{"type":"integer","example":123},"next":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=4"},"previous":{"type":"string","nullable":true,"format":"uri","example":"http://api.example.org/accounts/?page=2"},"results":{"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateSimpleRead"}}}},"PatchedContactEdit":{"type":"object","properties":{"phone":{"type":"string","maxLength":30},"first_name":{"type":"string","nullable":true,"maxLength":100},"last_name":{"type":"string","nullable":true,"maxLength":100},"email":{"type":"string","format":"email","nullable":true,"maxLength":254},"meta":{},"external_url":{"type":"string","format":"uri","nullable":true,"maxLength":200},"is_deleted":{"type":"boolean"},"id":{"type":"string","format":"uuid"},"source":{"type":"string","default":"website"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/ContactNote"},"readOnly":true},"created_on":{"type":"string","format":"date-time","title":"Created on"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ContactTag"}},"external_id":{"type":"string","nullable":true},"native_id":{"type":"string","nullable":true},"default_assignees":{"type":"array","items":{"type":"integer"}},"contact_import":{"type":"string","format":"uuid","nullable":true},"default_channel":{"type":"integer","nullable":true},"wa_id":{"type":"string","nullable":true},"overwrite_tags":{"type":"boolean","default":false,"description":"If true, the `tags` will be overwritten with the new value. If false, the new value will be merged with the existing value. Default is false."},"overwrite_default_assignees":{"type":"boolean","default":false,"description":"If true, the `default_assignees` will be overwritten with the new value. If false, the new value will be merged with the existing value. Default is false."},"overwrite_meta":{"type":"boolean","default":false,"description":"If true, the `meta` field will be overwritten with the new value. If false, the new value will be merged with the existing value. Default is false."}}},"PatchedConversationEdit":{"type":"object","properties":{"id":{"type":"string","description":"The UUID of the Conversation."},"contact":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/ConversationStatusEnum"},"assigned":{"type":"array","items":{"$ref":"#/components/schemas/UserBasicEdit"},"description":"The Users assigned to the Conversation."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ConversationTag"},"description":"The Tags assigned to the Conversation."},"created_on":{"type":"string","format":"date-time","readOnly":true,"title":"Created on"},"source":{"allOf":[{"$ref":"#/components/schemas/ConversationSourceEnum"}],"readOnly":true},"assigned_team":{"type":"integer","description":"The ID of the Team assigned to the Conversation."},"channel":{"type":"integer","nullable":true}}},"PerformanceSummary":{"description":"The current user's stored goals performance summary and where its generation stands.","required":["userId","status","summary"],"properties":{"userId":{"description":"ID of the user the summary belongs to, as stored when the summary was requested: a number or a numeric string.","type":["integer","string"],"example":1},"status":{"description":"in_progress until generation records a result (it stays in_progress if generation stops without recording one), success once summary holds the text, error when generation recorded a failure or could not be started.","type":"string","enum":["in_progress","success","error"],"example":"success"},"summary":{"description":"The summary: one paragraph written by an AI model, which can contain HTML <strong> tags, or a fixed, translated message when no conversion is pinned or linked to a pinned goal, or when none of those conversions can be found. Null while status is in_progress or error.","type":["string","null"],"example":"There are no updates at this time. Keep doing amazing work!"}},"type":"object"},"PermissionRuleRequest":{"description":"A permission decision to save.","required":["resource","operation","verdict"],"properties":{"ruleId":{"description":"Ignored: the server derives the id from the resource and operation.","type":["string","null"],"example":"8b1a6dc4b72dba6a7a0e3b17da0bb0ed"},"resource":{"description":"The resource the rule covers, or * for every resource. At most 100 characters. Surrounding whitespace is removed.","type":"string","example":"contact"},"operation":{"description":"The class of action the rule covers: create, or update_delete for changes that overwrite or remove existing data.","type":"string","enum":["create","update_delete"],"example":"create"},"verdict":{"description":"What the agent does for this resource and operation: allow it, ask the user first, or deny it.","type":"string","enum":["allow","ask","deny"],"example":"allow"},"scope":{"description":"Who the rule applies to. Only USER is accepted, and it is the default.","type":"string","enum":["USER"],"example":"USER"},"createdAt":{"description":"Ignored: the server keeps the stored value, or sets the time of creation.","type":"string","format":"date-time","example":"2026-10-19T14:30:00Z"},"updatedAt":{"description":"Ignored: the server sets it when the verdict changes.","type":"string","format":"date-time","example":"2026-10-19T14:31:00Z"}},"type":"object"},"PermissionRuleResource":{"description":"A decision the calling user has stored about what the AI agent may do to a resource.","required":["ruleId","resource","operation","verdict","scope","createdAt","updatedAt"],"properties":{"ruleId":{"description":"Id of the rule. It is derived from the resource and operation, so there is one rule per pair and it can be addressed without looking it up.","type":"string","example":"8b1a6dc4b72dba6a7a0e3b17da0bb0ed"},"resource":{"description":"The resource the rule covers, or * for every resource. A rule for an exact resource takes precedence over *.","type":"string","example":"contact"},"operation":{"description":"The class of action the rule covers: create, or update_delete for changes that overwrite or remove existing data.","type":"string","enum":["create","update_delete"],"example":"create"},"verdict":{"description":"What the agent does for this resource and operation: allow it, ask the user first, or deny it.","type":"string","enum":["allow","ask","deny"],"example":"allow"},"scope":{"description":"Who the rule applies to. Always USER: only rules for the calling user exist today.","type":"string","enum":["USER"],"example":"USER"},"createdAt":{"description":"When the rule was created, as an ISO 8601 UTC timestamp.","type":"string","format":"date-time","example":"2026-10-19T14:30:00.000000Z"},"updatedAt":{"description":"When the rule's verdict last changed, as an ISO 8601 UTC timestamp. Saving the same verdict again leaves it as it was.","type":"string","format":"date-time","example":"2026-10-19T14:31:00.000000Z"}},"type":"object"},"PermissionRulesResponse":{"description":"The permission rules the calling user has stored.","required":["rules"],"properties":{"rules":{"description":"Every rule the user has. Empty when the user has none, in which case the agent asks before acting.","type":"array","items":{"$ref":"#/components/schemas/PermissionRuleResource"}}},"type":"object"},"PersonalizeRecipeRequest":{"description":"Which stored goal recipe to personalize. Sent only by Hosted's own background dispatcher, never by a client. Send the hash as a JSON string.","required":["hash"],"properties":{"hash":{"description":"Hash of the goal recipe template, as returned in hash by GET /ai/initiatives/recipes. A personalized recipe must already be stored for it.","type":"string","example":"3KP9Mla"}},"type":"object"},"PersonalizedInitiativeRecipe":{"description":"A goal recipe personalized for the account from one recipe template. The personalized name, description and conversionName stay null until personalization is done.","required":["hash","color","name","description","conversionName"],"properties":{"hash":{"description":"Hash of the recipe template this recipe was personalized from.","type":["string","null"],"example":"3KP9Mla"},"name":{"description":"Goal name personalized for the account. Null unless personalizationStatus is done.","type":["string","null"],"example":"Re-Engage Inactive Contacts"},"description":{"description":"Goal description personalized for the account. Null unless personalizationStatus is done.","type":["string","null"],"example":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value."},"conversionName":{"description":"Conversion name personalized for the account. Null unless personalizationStatus is done.","type":["string","null"],"example":"Has opened an email - any email"},"originalName":{"description":"The template's goal name. Left out when empty.","type":"string","example":"Re-Engage Inactive Contacts"},"originalDescription":{"description":"The template's goal description. Left out when empty.","type":"string","example":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value."},"originalConversionName":{"description":"Name of the template's conversion. Left out when empty or when the template has no conversion.","type":"string","example":"Has opened an email - any email"},"personalizationStatus":{"description":"Where personalization of this recipe stands. Left out when empty.","type":"string","enum":["queued","in_progress","done","error"],"example":"done"},"color":{"description":"Label color from the template, as a hex code without the leading #.","type":"string","example":"FEE8B5"}},"type":"object"},"PersonalizedInitiativeRecipeListResponse":{"description":"The account's personalized goal recipes.","required":["recipes"],"properties":{"recipes":{"description":"Every personalized recipe stored for the account, in storage order. A recipe may still be queued, in progress or failed: check personalizationStatus.","type":"array","items":{"$ref":"#/components/schemas/PersonalizedInitiativeRecipe"}}},"type":"object"},"Phase":{"enum":["queued","running","complete","cancelled"],"title":"Phase","type":"string"},"PlatformMaintenanceCheck":{"description":"The outcome of one maintenance readiness check.","required":["checkName","message","status","status_name","service_id","duration"],"properties":{"checkName":{"description":"Label of the check. The configured checks are `pending_campaigns` (scheduled campaigns of the single, split or text type, outside automations, due between a day ago and four hours from now) and `running_processes` (campaign, import, export and bulk-edit processes created in the last hour that still have items left). Each fails when it counts any, or when its query fails.","type":"string","example":"pending_campaigns"},"message":{"description":"What the check found, for example `Query passed: 0 returned` or `Query failed: 3 returned`.","type":"string","example":"Query passed: 0 returned"},"status":{"description":"Outcome code: 0 passed, 1 warning, 2 skipped, 3 failed.","type":"integer","enum":[0,1,2,3],"example":0},"status_name":{"description":"Name of the outcome code in `status`.","type":"string","enum":["check_result_ok","check_result_warning","check_result_skip","check_result_critical"],"example":"check_result_ok"},"service_id":{"description":"Zero-based position of the check in the run. The configured checks are registered without a name, so the runner identifies them by position.","type":"integer","example":0},"duration":{"description":"How long the check took to run, in seconds.","type":"number","format":"float","example":0.0123}},"type":"object"},"PlatformMaintenanceReport":{"description":"The outcome of every maintenance readiness check, in the order they ran, and whether all of them passed.","required":["checks","globalStatus"],"properties":{"checks":{"description":"One entry per check, in the order they ran.","type":"array","items":{"$ref":"#/components/schemas/PlatformMaintenanceCheck"}},"globalStatus":{"description":"True when every check passed or was skipped; false when any check failed or warned.","type":"boolean","example":true}},"type":"object"},"PlusAppend":{"type":"object","description":"A contact's social profile and enrichment record. A contact has at most one. Every record also carries columns from older data providers, in their stored form and not described one by one: demographic values (age, gender, children, householdIncome, maritalStatus, homeOwnerStatus, homeMarketValue, homePropertyType, lengthOfResidence, education, occupation, likelySmartphoneUser, carsInHousehold, vehicleNewOrUsedIndicator, vehicleType, hasCreditCard, hasPremiumCreditCard, hasRetailCard, highNetWorth, investedAssets, likelyToUseFinancialServices, loanToValueRatio), interest flags (artsAndCrafts, automotive, babyProductBuyer, beauty, blogging, books, business, charitableDonors, cooking, discountShopper, healthAndWellness, highEndBrandBuyer, homeAndGarden, homeImprovement, luxuryGoodsAndJewelry, magazineBuyer, newsAndCurrentEvents, outdoorAndAdventure, pets, powerShopper, sports, technology, travel), influence, and further social profile URLs (memberships_myspace, memberships_flickr, memberships_github, memberships_picasa, memberships_quora, memberships_tripadvisor, memberships_tumblr, memberships_twitpic, memberships_vimeo, memberships_yelp, memberships_amazon, memberships_etsy, memberships_foursquare, memberships_google, memberships_youtube). Numeric columns are \"0\" and text columns are empty when not set.","properties":{"contact":{"type":["string","null"],"description":"ID of the contact this record belongs to. Null when the record has no contact. A normal contact delete keeps the record, so this can be the ID of a contact that no longer exists; merging contacts removes the merged-away contact's record.","example":"3"},"imageUrl":{"type":"string","description":"URL of a photo of the contact, found by contact enrichment. Empty when none.","example":"https://example.com/avatars/sam.png"},"membershipsFacebook":{"type":"string","description":"URL of the contact's Facebook profile, found by contact enrichment. Empty when none.","example":""},"membershipsTwitter":{"type":"string","description":"URL of the contact's Twitter/X profile, found by contact enrichment. Empty when none.","example":"https://x.com/samexample"},"membershipsLinkedin":{"type":"string","description":"URL of the contact's LinkedIn profile, found by contact enrichment. Empty when none.","example":"https://www.linkedin.com/in/samexample"},"firstName":{"type":"string","description":"First name from an older data provider. Empty when not set.","example":""},"lastName":{"type":"string","description":"Last name from an older data provider. Empty when not set.","example":""},"name":{"type":"string","description":"Full name from an older data provider. Empty when not set.","example":""},"company":{"type":"string","description":"Company from an older data provider. Empty when not set.","example":""},"title":{"type":"string","description":"Job title from an older data provider. Empty when not set.","example":""},"location":{"type":"string","description":"Location text from an older data provider. Empty when not set.","example":""},"last_updated_fullcontact":{"type":["string","null"],"description":"When the record was last written through the API (a v3 create or update, or the older v2 enrichment call), in ISO 8601. Current contact enrichment does not set it. Null when never set.","example":null},"last_updated_rapleaf":{"type":["string","null"],"description":"When an older data provider last updated the record, in ISO 8601. Null when never set.","example":null},"last_updated_fliptop":{"type":["string","null"],"description":"When an older data provider last updated the record, in ISO 8601. Null when never set.","example":null},"links":{"type":"object","description":"URLs of the record's related reads.","properties":{"contact":{"type":"string","description":"URL that returns the contact, GET /plusAppends/{id}/contact.","example":"https://:account.api-us1.com/api/3/plusAppends/2/contact"}}},"id":{"type":"string","description":"ID of the record.","example":"2"}}},"PlusAppendBodyNotObjectError":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code.","example":400},"title":{"type":"string","description":"Short name of the error, in the API user's language.","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body.","example":"Request body must be a JSON object, array given."}}}}}},"PlusAppendDuplicateError":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Could not process request\".","example":"Could not process request"},"error":{"type":"string","description":"The database's duplicate-entry message.","example":"Duplicate entry '3' for key 'em_plus_append.subscriberid'"}}},"PlusAppendNotFoundError":{"type":"object","properties":{"message":{"type":"string","description":"\"No Result found for PlusAppend with id\" followed by the ID as a whole number.","example":"No Result found for PlusAppend with id 2"}}},"PlusAppendSaveError":{"type":"object","properties":{"message":{"type":"string","description":"\"Could not process request\", or the generic \"Something went wrong on our end. Please try again later\".","example":"Could not process request"},"error":{"type":"string","description":"\"Error while processing request\" when present.","example":"Error while processing request"}}},"PlusAppendSaved":{"type":"object","description":"The record as written. Values are echoed as sent; the record is not read back. An update also returns the stored fields that were not sent, as GET /plusAppends/{id} does. An empty or null value comes back as \"0\" or an empty string.","properties":{"contact":{"type":["integer","string","null"],"description":"ID of the contact, as sent. Null when the record has no contact.","example":3},"imageUrl":{"type":"string","description":"URL of a photo of the contact.","example":"https://example.com/avatars/sam.png"},"membershipsFacebook":{"type":"string","description":"URL of the contact's Facebook profile.","example":""},"membershipsTwitter":{"type":"string","description":"URL of the contact's Twitter/X profile.","example":"https://x.com/samexample"},"membershipsLinkedin":{"type":"string","description":"URL of the contact's LinkedIn profile.","example":"https://www.linkedin.com/in/samexample"},"last_updated_fullcontact":{"type":"string","description":"The time of the request, in ISO 8601.","example":"2026-10-16T09:30:00-05:00"},"links":{"type":"object","description":"URLs of the record's related reads.","properties":{"contact":{"type":"string","description":"URL that returns the contact, GET /plusAppends/{id}/contact.","example":"https://:account.api-us1.com/api/3/plusAppends/2/contact"}}},"id":{"type":"string","description":"ID of the record.","example":"2"}}},"PlusAppendWrite":{"type":"object","description":"The fields to set, by the names the reads return. Any other PlusAppend field can be set the same way. An empty or null value is stored as \"0\" or an empty string. A key that is not a field of the record fails with 500.","properties":{"contact":{"type":["integer","string","null"],"description":"ID of the contact the record belongs to. A contact can have only one record. Null or 0 is stored as 0 and comes back as null.","example":3},"imageUrl":{"type":"string","description":"URL of a photo of the contact.","example":"https://example.com/avatars/sam.png"},"membershipsFacebook":{"type":"string","description":"URL of the contact's Facebook profile.","example":""},"membershipsTwitter":{"type":"string","description":"URL of the contact's Twitter/X profile.","example":"https://x.com/samexample"},"membershipsLinkedin":{"type":"string","description":"URL of the contact's LinkedIn profile.","example":"https://www.linkedin.com/in/samexample"}}},"PollRevertRequest":{"description":"Queue payload for a revert that has to wait for a running edit. CampaignEditsService::revertRequestOrDispatch builds it.","required":["request_id"],"properties":{"request_id":{"description":"UUID of the edit request to revert.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"PositionedImage":{"description":"Accepted for backward compatibility; has no effect. Search the account's Content Manager images for one to use and pass its `name` in `image_references` instead.","properties":{"url":{"description":"Content manager image URL.","format":"uri","maxLength":2083,"minLength":1,"title":"Url","type":"string"},"position":{"default":"random","deprecated":true,"description":"Ignored — no positioning concept on this engine.","title":"Position","type":"string"},"altText":{"default":"","deprecated":true,"description":"Ignored — this engine derives alt text itself.","title":"Alttext","type":"string"}},"required":["url"],"title":"Positioned Image","type":"object"},"PostmarkHttpError":{"type":"object","description":"Error document of the API's HTTP exception handler.","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status."},"title":{"type":"string","description":"The HTTP status title."},"detail":{"type":"string","description":"Omitted: these errors carry no message."}}}}}},"PostmarkIdName":{"type":"object","properties":{"id":{"type":["integer","string"],"description":"The Postmark server ID."},"name":{"type":"string","description":"The server name."}}},"PostmarkWebhook":{"type":"object","description":"A Postmark webhook as Postmark's webhooks API represents it, passed through; properties other than those listed are Postmark's. ActiveCampaign marks the automations using a webhook with `X-Ref-<type>-Cnt` headers counting the automations per trigger or action type.","properties":{"Url":{"type":"string","description":"The ActiveCampaign endpoint Postmark calls. Always overwritten with ActiveCampaign's own on create and update."},"Integration":{"type":"string","description":"Set to `ActiveCampaignTriggers` on create and update; lookups only see webhooks with this value."},"IntegrationDescription":{"type":"string","description":"Set to `ActiveCampaign Integration` on create and update."},"HttpAuth":{"type":"object","description":"Basic auth credentials Postmark sends: the ActiveCampaign account ID as the user name and a password derived from it. Always overwritten on create and update."},"HttpHeaders":{"type":"array","description":"Headers Postmark sends: `ac_accountid` and the `X-Ref-<type>-Cnt` counters.","items":{"type":"object","properties":{"Name":{"type":"string","description":"Header name."},"Value":{"type":"string","description":"Header value."}}}}}},"PreferenceCentersListData":{"description":"A page of the account's email lists, for a Preference Center form","required":["lists","meta"],"properties":{"lists":{"description":"The lists on this page, by ascending ID","type":"array","items":{"$ref":"#/components/schemas/PreferenceCentersListItemData"}},"meta":{"description":"About this page of lists","properties":{"total":{"description":"Number of lists in this response, not the number that match across all pages","type":"integer","example":2}},"type":"object"}},"type":"object"},"PreferenceCentersListItemData":{"description":"An email list a Preference Center form can offer, with its contact counts","required":["id","name","url","description","subscriber_count","total_contacts"],"properties":{"id":{"description":"ID of the list","type":"integer","example":3},"name":{"description":"Name of the list","type":"string","example":"Newsletter"},"url":{"description":"The website URL this list is for; empty when none is set","type":"string","example":"https://www.example.com"},"description":{"description":"The list's permission reminder: why its contacts are on it and are being messaged","type":"string","example":"You signed up for our newsletter on our website."},"subscriber_count":{"description":"Number of contacts subscribed to the list, from the account's stored list counts; 0 when none are stored","type":"integer","example":120},"total_contacts":{"description":"Number of contacts on the list that are not deleted, whatever their status, from the account's stored list counts; 0 when none are stored","type":"integer","example":134}},"type":"object"},"PrepRequest":{"description":"The campaign whose email to prepare for AI edits. The server resolves the campaign's message and its editor markup from campaignId.","required":["campaignId"],"properties":{"campaignId":{"description":"Id of the campaign to edit. The campaign must exist and its message must be built in the current editor (ed_version 3).","type":"integer","example":4821},"campaign":{"description":"The campaign record. Resolved by the server from campaignId; not part of the payload.","type":"object","readOnly":true},"messageId":{"description":"Id of the campaign's message. Set by the server from the message campaignId resolves to; a value sent here is replaced.","type":["integer","null"],"example":9134},"message":{"description":"The message record. Resolved by the server from campaignId; not part of the payload.","type":"object","readOnly":true},"messageMarkup":{"description":"The editor markup of the message. Resolved by the server from the message; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"PrepareScheduleRequest":{"properties":{"campaign_id":{"description":"Id of the campaign.","examples":[42],"exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"send_at":{"description":"When the campaign sends, as an ISO 8601 time with its UTC offset, in the future.","examples":["2026-11-02T09:00:00-05:00"],"format":"date-time","title":"Send At","type":"string"},"predictive_send":{"default":false,"description":"Send to each contact at the time of that day they are most likely to engage, instead of at send_at's time. Only when the user asks for it.","title":"Predictive Send","type":"boolean"}},"required":["campaign_id","send_at"],"title":"PrepareScheduleRequest","type":"object"},"PrepareSendRequest":{"properties":{"campaign_id":{"description":"Id of the campaign.","examples":[42],"exclusiveMinimum":0,"title":"Campaign Id","type":"integer"}},"required":["campaign_id"],"title":"PrepareSendRequest","type":"object"},"PrepopulationDoneResponse":{"description":"The prepopulation run was executed. This says nothing about its outcome: a run that failed inside is recorded as status error on the prepopulation record, which GET /ai/initiatives/recipes/prepopulate reports.","required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"}},"type":"object"},"PrepopulationErrorResponse":{"description":"The prepopulation run could not start. Nothing was recorded on the prepopulation record.","required":["error"],"properties":{"error":{"description":"A fixed prefix followed by the cause. The usual cause is the prepopulation lock being held by another run; the record and the lock are left as they were.","type":"string","example":"Unable to prepopulate initiatives - Recipe prepopulation initialization is locked"}},"type":"object"},"PrepopulationStatusResponse":{"description":"Where business goal prepopulation stands for the account. The status comes from the prepopulation record, except that a done record is reported as importing until every selected recipe has its prepopulated initiative. A record in error is never returned here: it answers 500.","required":["status"],"properties":{"status":{"description":"queued: the record exists but the run has not started. selecting: the run is choosing two goal recipe templates for the account. personalizing: it is personalizing the templates that have no personalized recipe yet. importing: the imports have been queued (or the run finished but not every initiative exists yet). done: every selected recipe has its prepopulated initiative.","type":"string","enum":["queued","selecting","personalizing","importing","done"],"example":"done"},"selectedRecipes":{"description":"Template hashes of the goal recipes the run selected, one per initiative it imports. Present only once the record is done (status done or importing), never while the run is still queued, selecting or personalizing.","type":"array","items":{"type":"string"},"example":["3KP9Mla","5RN6Ztc"]}},"type":"object"},"PreviewRequest":{"description":"The prompt of an AI content automation block to preview on sample contacts.","required":["prompt"],"properties":{"prompt":{"description":"The block's prompt as the user wrote it, personalization tags included (e.g. %FIRSTNAME%). A preview needs between 1 and 3 tags; the tags are what the preview record is keyed by.","type":"string","example":"Write a one-line greeting for %FIRSTNAME% who works at %COMPANY%"}},"type":"object"},"ProblemCode":{"enum":["no_message","no_content","no_subject","no_from_name","no_from_email","from_domain_unverified","no_reply_to","reply_to_domain_unverified","send_time_in_past","not_modifiable","no_lists","no_address","split_needs_two_versions","split_winner_wait_missing","split_ratios_not_allocatable","contact_limit_reached","engaged_contacts_limit_reached"],"title":"ProblemCode","type":"string"},"ProcessContentRemappingRequest":{"description":"Which content remapping job to run. Sent only by Hosted's own queue worker, never by a client.","required":["requestId"],"properties":{"requestId":{"description":"UUID of the job to run, as returned when it was created. It must name a stored content remapping job.","type":"string","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"record":{"description":"Not sent by the caller: the server resolves the job record named by requestId into it while validating.","type":"object","readOnly":true}},"type":"object"},"ProcessRequest":{"description":"Worker payload for the processing step of an AI content automation block, dispatched by AIDynamicDataBlock::runProcessing when a contact enters the block.","required":["blockid","contactseriesid","starttime"],"properties":{"blockid":{"description":"Id of the automation block the contact entered. Must name an existing block of type aidynamicdata.","type":"integer","example":4821},"contactseriesid":{"description":"Id of the contact's entry in the automation (the contact automation record) that reached the block.","type":"integer","example":91337},"starttime":{"description":"Unix time with microseconds at which the block started processing the contact, used to report the processing time of the whole step.","type":"number","format":"double","example":1760000000.123456},"promptdata":{"description":"The prompt action's processing data, built by the block from its stored params: type (generic, summarize, analyze, translate, classify_intent, sentiment or extract; generic when absent) and the fields that action needs, such as prompt for generic or inputField, inputFieldData and length for summarize. Each action's process constraint checks only its own fields.","type":"object","example":{"type":"generic","prompt":"Write a one-line greeting for %FIRSTNAME% who works at %COMPANY%"}},"block":{"description":"Ignored on input: the server loads the block named by blockid into it.","type":"object","readOnly":true},"contactSeries":{"description":"Ignored on input: the server loads the contact automation record named by contactseriesid into it.","type":"object","readOnly":true}},"type":"object"},"ProcessTemplateToCampaignRequest":{"description":"Which stored template-to-campaign job to run. Sent only by Hosted's own queue dispatcher, never by a client; the same body serves the stock template and the account template routes.","required":["requestId"],"properties":{"requestId":{"description":"Id of the job, the requestId that create answered. It must name a stored template-to-campaign job; otherwise 422.","type":"string","format":"uuid","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"record":{"description":"Not sent by the caller: the server resolves it from requestId during validation, as the stored job record.","type":"object","readOnly":true}},"type":"object"},"PromptActionPreviewErrorResponse":{"description":"Error body with a single message.","required":["error"],"properties":{"error":{"description":"What went wrong; each operation lists its fixed messages.","type":"string","example":"No contacts found for the given segment"}},"type":"object"},"PromptActionPreviewRequest":{"description":"Which prompt action to preview and its settings.","required":["type","params"],"properties":{"type":{"description":"The prompt action to run.","type":"string","enum":["generic","summarize","analyze","translate","classify_intent","sentiment","extract"],"example":"summarize"},"params":{"description":"The action's settings as the automation builder stores them; which keys are required depends on type (a prompt for generic, a target language for translate, a segment or contact to sample, and so on).","type":"object","example":{"prompt":"Summarize the contact's last reply in one sentence","segmentId":42},"additionalProperties":true}},"type":"object"},"PromptActionPreviewResponse":{"description":"The prompt action run against a sample contact.","required":["content"],"properties":{"content":{"description":"What the action would write for the sampled contact, as text.","type":"string","example":"Thanks for your note, Ada. Your order ships on Monday."}},"type":"object"},"PromptActionPreviewStartedResponse":{"description":"A preview record exists for the prompt action.","required":["requestId"],"properties":{"requestId":{"description":"ID of the preview record; pass it to POST /ai/prompt/preview/{requestId}. A matching record from an earlier call is reused.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"PushUnregisterErrorResponse":{"description":"Body of a push unregister command that could not be published. The cause is not returned.","required":["errors"],"properties":{"errors":{"description":"One entry, an empty object","type":"array","items":{"type":"object"},"example":[{}]}},"type":"object"},"PushUnregisterRequest":{"description":"The device to stop sending push notifications to. Top-level keys, not wrapped in an object; other keys are ignored. Neither value is checked before the command is published: the reference message schema types both as strings, and a command that cannot be encoded is answered with 422.","required":["app","push_token"],"properties":{"app":{"description":"Name of the app the device registered with: the app.name sent to POST /pushRegister. Published as app.","type":"string","example":"activecampaign"},"push_token":{"description":"Push token of the device: the device.push_token sent to POST /pushRegister. Published as deviceToken.","type":"string","example":"somePushTokenUUID"}},"type":"object"},"ReadinessProblem":{"properties":{"code":{"$ref":"#/components/schemas/ProblemCode"},"message":{"description":"What must change, written for the user.","title":"Message","type":"string"}},"required":["code","message"],"title":"ReadinessProblem","type":"object"},"RecentActivityStreamEntry":{"type":"object","description":"One hour of one type of activity in the account's activity stream.","properties":{"id":{"type":"string","description":"Id of the entry.","example":"812"},"groupid":{"type":"string","description":"Id of the user group the entry belongs to.","example":"3"},"type":{"type":"string","description":"Number of the activity type: 1 subscribe, 2 twitter, 3 facebook, 4 unsubscribe, 5 open, 6 click, 7 forward, 8 update, 9 reply, 10 read.","example":"1"},"tstamp":{"type":"string","description":"Start of the hour the entry covers, as Y-m-d H:i:s in the account's time zone.","example":"2026-10-20 09:00:00"},"amount":{"type":"string","description":"Number of times the activity happened in the hour.","example":"2"},"minute":{"type":"string","description":"Minute of the hour of the latest activity in the entry.","example":"14"},"items":{"type":["array","object"],"description":"What the entry is about. For the open type, an object: arr holds 60 counts, one for each minute of the hour, and str holds the same counts joined with commas. For every other type, a list of up to 25 contacts or posts. A contact has id, email, tstamp (when it happened), screenshot (an avatar URL) and type, plus fields that depend on the type. With expanded, contacts also carry their contact card.","additionalProperties":true,"items":{"type":"object","additionalProperties":true}},"minid":{"type":"string","description":"Lowest source record id in the entry.","example":"5010"},"maxid":{"type":"string","description":"Highest source record id in the entry.","example":"5011"},"realtstamp":{"type":"string","description":"Same value as tstamp.","example":"2026-10-20 09:00:00"},"typestr":{"type":"string","description":"Name of the activity type, such as subscribe or open.","example":"subscribe"},"options":{"type":"object","description":"How the overview shows this type: id (the type number, as an integer), color (always unused), class (a CSS class), text (the label, in the user's language), fade (1 for unsubscribe, else 0), url (the type's report), icon and icon_bgcolor (hex without #).","additionalProperties":true},"last":{"type":"string","description":"Time of the latest activity in the entry, as Y-m-d H:i:00.","example":"2026-10-20 09:14:00"},"isnew":{"type":"boolean","description":"True only when offset is 0 and last is later than the time this session last loaded the overview activity stream. Otherwise false.","example":false},"iscurrent":{"type":"boolean","description":"True when last is less than an hour ago.","example":true},"timeago":{"type":"string","description":"How long ago last was, in words, in the user's language.","example":"20 minutes ago"}}},"RecentCampaignSummary":{"description":"A recent campaign, summarized for background context.","properties":{"id":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"Numeric ID of the campaign.","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign name.","title":"Name"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign type.","title":"Type"},"status":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"Campaign status code.","title":"Status"},"sdate":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Scheduled send date, when set.","title":"Sdate"}},"title":"Recent Campaign Summary","type":"object"},"Recipient":{"properties":{"id":{"description":"ID of the contact.","type":"integer"},"sendId":{"description":"ID of the send of the message to this contact.","type":["integer","null"]},"email":{"description":"Email address of the contact, null when it has none.","type":["string","null"]},"name":{"description":"First and last name of the contact.","type":["string","null"]},"phoneNumber":{"description":"Phone number the message was sent to.","type":["string","null"]},"sentDate":{"description":"When the message was sent, as \"Y-m-d H:i:s\" in Central time (America/Chicago).","type":"string","example":"2026-10-01 14:30:00"},"clicks":{"description":"Number of clicks by this contact on links in the message.","type":"integer"},"deliverability":{"description":"Whether the message was delivered or failed.","type":"string","enum":["delivered","failed"]},"replies":{"description":"Replies the contact sent to the message, empty when there are none.","type":"array","items":{"properties":{"message":{"description":"Text of the reply.","type":"string"},"date":{"description":"When the reply was received, as \"Y-m-d H:i:s\" in Central time (America/Chicago).","type":"string","example":"2026-10-01 14:35:00"}},"type":"object"}},"optOut":{"description":"Whether the contact opted out after the message.","type":"string","enum":["yes","no"]},"details":{"description":"Why the message failed, null when it did not fail.","properties":{"errorCode":{"description":"The error code of the failure.","type":"string"},"errorSource":{"description":"Where the error code comes from: \"ac\" for ActiveCampaign or \"twilio\" for Twilio.","type":"string","enum":["ac","twilio"]}},"type":["object","null"]}},"type":"object"},"RecipientsResponse":{"properties":{"recipients":{"description":"This page of recipients.","type":"array","items":{"$ref":"#/components/schemas/Recipient"}},"meta":{"description":"Paging information.","properties":{"total":{"description":"Number of recipients that match the filters, across all pages.","type":"integer"},"limit":{"description":"Page size used, at most 100.","type":"integer"},"offset":{"description":"Number of recipients skipped.","type":"integer"}},"type":"object"}},"type":"object"},"RecommendationDispatchedResponse":{"description":"Selection of a recommended asset was started in the background.","required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"},"status":{"description":"Always dispatched.","type":"string","enum":["dispatched"],"example":"dispatched"}},"type":"object"},"RedriveDeadLetterQueueRequest":{"description":"Which source queue's dead letter queue to redrive and how much of it. Send each field with the JSON type shown, or leave it out; a field sent as JSON null makes the call fail with a generic 500.","required":["sourceQueueUrl"],"properties":{"sourceQueueUrl":{"description":"URL of the source SQS queue to send messages back to; its dead letter queue is read from its redrive policy. Unlike dead-letter-queue/delete, this is not checked against the Generative Marketing queues Hosted is configured with: any syntactically valid URL is used, and the call acts on that queue and the dead letter queue its redrive policy names, limited only by what Hosted's AWS role is allowed to do on them.","type":["string","null"],"example":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives"},"maxReceiveCount":{"description":"Most messages to take from the dead letter queue, 1 to 100. Defaults to 10. Messages are received in batches of up to 10 with a one-second wait each, so fewer can come back than asked for.","type":["integer","null"],"maximum":100,"minimum":1,"example":10},"isDryRun":{"description":"When true, count the messages a real run would redrive without sending or removing any, so the call can be previewed. The messages it received stay invisible for the queue's visibility timeout. Defaults to false.","type":["boolean","null"],"example":true},"messageId":{"description":"Only act on the message with this SQS MessageId. The call keeps receiving batches from the dead letter queue until it finds this message or the queue returns no more messages; maxReceiveCount does not limit that scan. Every other message it received is left in place but stays invisible for the queue's visibility timeout.","type":["string","null"],"example":"e5f6a7b8-1234-4c3d-9e8f-0a1b2c3d4e5f"}},"type":"object"},"ReportTrendsActivityResponseResource":{"description":"Contact Trends totals for one date window. Counts come from current list-membership rows, not an event log.","properties":{"period":{"description":"Number of days in the window, including both ends.","type":"integer","example":31},"range_values":{"description":"One number per day, in the same order as dates. For new_contacts each number is that day's joins. For every other graph each number is a running total through that day: contact stock for the default, active_contacts and total_contacts graphs, and a running unsubscribe count for unsubscribes.","type":"array","items":{"type":"integer"},"example":[4,4,5]},"dates":{"description":"Each day in the window, as YYYY-MM-DD, from the start date through the end date.","type":"array","items":{"type":"string"},"example":["2026-01-01","2026-01-02","2026-01-03"]},"series":{"description":"A short label for each day in dates, for a chart axis.","type":"array","items":{"type":"string"},"example":["Jan 1","Jan 2","Jan 3"]},"unsubscribe_total":{"description":"Memberships that are still unsubscribed (status 2) and whose unsubscribe date falls in the window. A contact who unsubscribed and later resubscribed is not included. With no list_id, a contact who is still active on another list is not included. One contact unsubscribed from two lists counts twice.","type":"integer","example":12},"unsubscribe_average":{"description":"unsubscribe_total divided by period.","type":"number","format":"float","example":0.3870967741935484},"starting_total":{"description":"Count at the start of the window, before the first day is applied. For new_contacts this stays 0. For a single list, active_contacts counts only memberships that are still active now, so someone who was active on the start date and later unsubscribed is missing from this number.","type":"integer","example":100},"ending_total":{"description":"The last value in range_values. For new_contacts this is the sum of joins in the window.","type":"integer","example":105},"change":{"description":"ending_total minus starting_total. For new_contacts this is the same sum as ending_total.","type":"integer","example":5},"subscribe_average":{"description":"change divided by period.","type":"number","format":"float","example":0.16129032258064516},"change_percentage":{"description":"change as a percentage of the starting total, formatted for display. A starting total of 0 is treated as 1. When the percentage is over 9000 the value is capped, for example \"> 9,000\".","type":"string","example":"5.00"},"succeeded":{"description":"1 when the totals were calculated.","type":"integer","example":1},"message":{"description":"A short status message. It is translated and is not a count.","type":"string","example":"Change calculated"}},"type":"object"},"ReportTrendsActivityValidationErrorResource":{"description":"One query-parameter validation failure.","properties":{"status":{"description":"HTTP status of this failure. The same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the failure.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the parameter was rejected.","type":"string","example":"This value should not be blank."},"source":{"$ref":"#/components/schemas/ReportTrendsActivityValidationErrorSourceResource","description":"Where the failure is."}},"type":"object"},"ReportTrendsActivityValidationErrorResponse":{"description":"The query parameters were rejected and no totals were calculated.","properties":{"errors":{"description":"One entry per validation failure.","type":"array","items":{"$ref":"#/components/schemas/ReportTrendsActivityValidationErrorResource"}}},"type":"object"},"ReportTrendsActivityValidationErrorSourceResource":{"description":"Which query parameter a validation failure refers to.","properties":{"pointer":{"description":"The rejected query parameter, as a JSON pointer under /data/attributes.","type":"string","example":"/data/attributes/from"}},"type":"object"},"RequestValidationError":{"description":"One field of the request body that failed validation.","required":["status","title"],"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the field was refused. Unexpected type when the value has the wrong JSON type.","type":"string","example":"assetType is required"},"source":{"description":"The field that failed. Left out when the error is not about one field.","required":["pointer"],"properties":{"pointer":{"description":"The field, as /data/attributes/<field name>.","type":"string","example":"/data/attributes/assetType"}},"type":"object"}},"type":"object"},"RequestValidationErrorResponse":{"description":"Error body for a request body that fails validation (HTTP 422).","required":["errors"],"properties":{"errors":{"description":"One error per failed check. A field can appear more than once.","type":"array","items":{"$ref":"#/components/schemas/RequestValidationError"}}},"type":"object"},"RestoreVersionRequest":{"description":"The version to restore and the campaign message to restore it into.","required":["campaignId","patchId"],"properties":{"campaignId":{"description":"ID of the campaign. It must exist, be a campaign the user can access, and still be modifiable: a draft, scheduled, paused or disabled campaign, or the campaign of an automation.","type":["integer","null"],"example":174},"messageId":{"description":"ID of the message of the campaign to restore. Left out, the first message of the campaign is used. It must be a message of campaignId.","type":["integer","null"],"example":180},"patchId":{"description":"Which version to restore: the id of an entry returned by GET /stripo/versions for the same campaign and message, sent as a JSON string.","type":["string","null"]}},"type":"object"},"RootDO":{"title":"RootDO","type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentDataDO"}},"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetailDO"}}}},"RootErrorDO":{"title":"RootErrorDO","type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetailDO"}}}},"RootSuccessDO":{"title":"RootSuccessDO","type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentDataDO"}}}},"RunListEntry":{"description":"One run in the listing: enough to identify a handle without polling it.","properties":{"request_id":{"title":"Request Id","type":"string"},"operation":{"anyOf":[{"enum":["create","edit"],"type":"string"},{"type":"null"}],"default":null,"title":"Operation"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"}},"required":["request_id"],"title":"RunListEntry","type":"object"},"RunStatusResponse":{"properties":{"request_id":{"title":"Request Id","type":"string"},"phase":{"$ref":"#/components/schemas/Phase","default":"queued"},"step":{"anyOf":[{"$ref":"#/components/schemas/AutomationStep"},{"type":"null"}],"default":null},"outcome":{"anyOf":[{"$ref":"#/components/schemas/AutomationOutcome"},{"type":"null"}],"default":null},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Reason"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Message"},"automation":{"anyOf":[{"$ref":"#/components/schemas/AutomationSummary"},{"type":"null"}],"default":null},"disclosures":{"anyOf":[{"items":{"$ref":"#/components/schemas/Disclosure"},"type":"array"},{"type":"null"}],"default":null,"title":"Disclosures"},"email_progress":{"anyOf":[{"$ref":"#/components/schemas/EmailsProgress"},{"type":"null"}],"default":null},"retryable":{"default":false,"title":"Retryable","type":"boolean"},"automation_persisted":{"default":false,"title":"Automation Persisted","type":"boolean"}},"required":["request_id"],"title":"RunStatusResponse","type":"object"},"RunSyncJobRequest":{"description":"How to run the sync. Send `{}` for a normal run.","properties":{"test":{"description":"Run as a test: every row is checked and reported as a real run would, but no contact is written, no autoresponder or campaign is sent and `deleteAll` is not applied. A test run also checks that the table still exists.","type":"boolean","example":false}},"type":"object"},"SalesforceAccountCustomFieldValue":{"type":"object","description":"One account custom field value as sent by Salesforce.","required":["id"],"properties":{"id":{"type":["integer","string"],"description":"ID of the account custom field (the field definition, not a stored value).","example":"7"},"fieldValue":{"description":"The value. Salesforce sometimes wraps a scalar in a single-element array; for every field type except checkbox and multiselect the array is flattened into a comma-separated string before saving.","example":"0015g00000ABCdEAAX"},"fieldCurrency":{"type":"string","description":"Currency code, used by currency fields only.","example":"USD"}}},"SalesforceConnectionParameters":{"type":"object","description":"Identifies the Salesforce org and the installed ActiveCampaign managed package.","required":["isSandbox","orgInstance","namespace","orgId"],"properties":{"isSandbox":{"type":"boolean","description":"Whether the org is a Salesforce sandbox. A sandbox connection is stored with `sandbox.` prefixed to its external ID and name.","example":true},"orgInstance":{"type":"string","description":"The Salesforce instance the org runs on. The stored connection name is `<namespace>.<orgInstance>`.","example":"NA91"},"namespace":{"type":"string","description":"Namespace of the installed managed package.","example":"ActiveCamp"},"orgId":{"type":"string","description":"The Salesforce org ID, stored as the connection's external ID.","example":"00D2E0000013vPH"}}},"SalesforceContactIds":{"type":"object","required":["activecampaign_ids"],"properties":{"activecampaign_ids":{"type":"array","description":"IDs of the ActiveCampaign contacts to act on.","items":{"type":["integer","string"],"description":"A contact ID."},"example":[339,539,540]}}},"SalesforceContactIdsInvalid":{"type":"object","description":"Returned with status 422 when the contact ID array is missing or is not an array.","properties":{"errors":{"type":"string","description":"What was missing.","example":"Invalid or missing activecampaign_ids"}}},"SalesforceExceptionError":{"type":"object","description":"Error body built from a caught exception. It exposes the server-side stack trace and source line.","properties":{"error":{"type":"string","description":"The exception message."},"stackTrace":{"type":"string","description":"The PHP stack trace of the exception."},"line":{"type":"integer","description":"The source line the exception was thrown from."}}},"SalesforceRequiredFieldErrors":{"type":"object","description":"Returned with status 422.","properties":{"errors":{"type":["array","string"],"description":"Either one entry per missing required field, or the response body DeepData sent back when it refused the call. Each missing-field entry is the literal text `$key was not provided`: the field name is not substituted into it.","items":{"type":"string","description":"The literal text `$key was not provided`."}}}},"SalesforceSavedAccount":{"type":"object","description":"The saved account, serialized the way the accounts API serializes it.","properties":{"account":{"type":"object","properties":{"id":{"type":"string","description":"ID of the account.","example":"12"},"name":{"type":"string","description":"Name of the account.","example":"Acme Inc"},"accountUrl":{"type":["string","null"],"description":"The account's website URL."},"owner":{"type":["integer","string","null"],"description":"ID of the user who owns the account."},"createdTimestamp":{"type":["string","null"],"description":"When the account was created."},"updatedTimestamp":{"type":["string","null"],"description":"When the account was last updated."},"fields":{"type":"array","description":"The custom field values sent with the account. Present after an upsert.","items":{"type":"object","description":"One custom field value: `customFieldId`, `fieldValue` and, for currency fields, `fieldCurrency`."}},"links":{"description":"Relationship links of the account."}}}}},"SalesforceSyncAccount":{"type":"object","description":"An account shaped for the Salesforce managed package: the account, its custom field values and the IDs of its contacts in one object.","properties":{"id":{"type":"string","description":"ID of the account.","example":"12"},"name":{"type":"string","description":"Name of the account.","example":"Acme Inc"},"accountUrl":{"type":["string","null"],"description":"The account's website URL.","example":"https://www.example.com"},"owner":{"type":["integer","string","null"],"description":"ID of the user who owns the account; null when it has no owner.","example":"1"},"createdTimestamp":{"type":["string","null"],"format":"date-time","description":"When the account was created, as an ISO 8601 timestamp with offset; null when unset.","example":"2020-06-23T14:31:30-05:00"},"updatedTimestamp":{"type":["string","null"],"format":"date-time","description":"When the account was last updated, as an ISO 8601 timestamp with offset; null when unset.","example":"2020-06-24T09:02:11-05:00"},"matchingEnabled":{"type":["integer","string"],"description":"The account's matching flag. Present only when the requesting tenant is ActiveCampaign's own account."},"accountCustomFieldData":{"type":"array","description":"The account's stored custom field values.","items":{"type":"object","properties":{"fieldValue":{"type":["string","null"],"description":"The value as a string: the first non-empty of the text, long text, date, number and currency columns; null when all are empty."},"id":{"type":["integer","string"],"description":"ID of the stored value."},"fieldCurrency":{"type":["string","null"],"description":"Currency code of a currency value."},"metaId":{"type":["integer","string"],"description":"ID of the account custom field the value belongs to."}}}},"accountContacts":{"type":"array","description":"IDs of the contacts associated with the account.","items":{"type":"string","description":"A contact ID."}}}},"SalesforceSyncAccountMeta":{"type":"object","description":"Paging of the response.","properties":{"total":{"type":"integer","description":"Number of matching records."},"limit":{"type":["integer","string"],"description":"The page size used: the `limit` query parameter as sent, or 100."},"offset":{"type":["integer","string"],"description":"The offset used: the `offset` query parameter as sent, or 0."}}},"SalesforceSyncCallbackInvalid":{"type":"object","description":"Returned with status 422 when `ids` is missing or is not an array.","properties":{"errors":{"type":"string","description":"Always `Invalid ids array in body`.","example":"Invalid ids array in body"}}},"SaveSyncJobRequest":{"description":"A database sync: where it reads from, which list it writes to, how source columns map to contact fields, and its options. An update replaces every field, so send the whole sync; only an omitted `password` or `sentResponders` keeps what is stored. A sync reads either a table (`table`, optionally narrowed by `rules`) or a custom SELECT `query` when `table` is empty.","required":["name","listId","fields","host","database","username"],"type":"object","allOf":[{"$ref":"#/components/schemas/SourceConnectionRequest"},{"properties":{"name":{"description":"Name of the sync, shown on the Database Sync page. Leading and trailing spaces are trimmed.","type":"string","example":"Nightly CRM import"},"listId":{"description":"ID of the list the sync writes contacts to. The user must be able to access it, or the call answers 403.","type":"integer","minimum":1,"example":3},"destination":{"description":"Status the run gives the contacts on the list: `1` (active, the default) unless another positive status is sent. `3` adds the rows to the exclusion list instead of the list.","type":"integer","minimum":1,"example":1},"table":{"description":"Source table to read. Leave it empty to read `query` instead.","type":"string","example":"customers"},"query":{"description":"Custom SELECT query to read when `table` is empty; it must contain `SELECT`. Ignored when `table` is set. `%SYNC_LASTRUN_DATETIME%` in it is replaced with the time of the last run (`1970-01-01 00:00:00` before the first).","type":"string","example":"SELECT email, fname FROM customers WHERE updated_at > '%SYNC_LASTRUN_DATETIME%'"},"rules":{"description":"SQL conditions a table sync selects rows by; a run reads the rows that match all of them. Empty strings are dropped. Ignored when the sync reads a custom query. `%SYNC_LASTRUN_DATETIME%` in a condition is replaced with the time of the last run.","type":"array","items":{"type":"string"},"example":["status = 1"]},"fields":{"description":"Which source column fills each contact field: the key is the ActiveCampaign field and the value the source column or expression, as POST /syncs/fields names it. Keys are the ids GET /syncs/contact-fields lists, or `_f<id>` for a custom field GET /syncs/custom-fields lists. A value of `DNI` (do not import) or an empty one leaves the field unmapped. At least one field must be mapped.","minProperties":1,"type":"object","example":{"email":"email_address","first_name":"fname","_f12":"company"},"additionalProperties":{"type":"string"}},"deleteAll":{"description":"After each run that is not a test, remove from the list every contact with the `destination` status that the run did not sync.","type":"boolean","example":false},"updateExisting":{"description":"Update contacts that already exist from the source row. When false they are left as they are. GET /syncs/options offers it checked.","type":"boolean","example":true},"sendLastMessage":{"description":"Send the list's last broadcast campaign to each contact the run subscribes as active. GET /syncs/options says whether the account can offer it.","type":"boolean","example":false},"sendResponder":{"description":"Enter the contacts the run subscribes as active into the list's autoresponders. The ones in `sentResponders` are recorded as already sent to them.","type":"boolean","example":false},"instantResponder":{"description":"Stored with the sync and handed to each run with the other autoresponder options.","type":"boolean","example":false},"optIn":{"description":"Stored with the sync and handed to each run as its opt-in option.","type":"boolean","example":false},"sentResponders":{"description":"IDs of the autoresponder campaigns earlier runs already sent, which `sendResponder` records as sent instead of sending again. GET /syncs/{id} returns the stored list, for an edit to send back. Omit it to keep what is stored; ids that are not positive are dropped.","type":["array","null"],"items":{"type":"integer"},"example":[3,5]}},"type":"object"}]},"SavedAreacode":{"description":"An area code for the account's 10DLC phone number and the state it is labelled with.","required":["state","areacode"],"properties":{"state":{"description":"The saved state, the region of the brand form's address, or `IL` for the Illinois fallback. A suggestion found by the country-wide search keeps the brand form's region, so the area code may not be in it. Null when the brand form has no region.","type":["string","null"],"example":"TX"},"areacode":{"description":"Three-digit North American area code.","type":"integer","example":512}},"type":"object"},"SavedAreacodeErrorResponse":{"description":"Why no area code could be returned.","required":["error"],"properties":{"error":{"description":"What went wrong.","type":"string","enum":["Brand location data not found","Area code not found based on brand location data","Area code not found based on brand location data or Illinois fallback","Internal server error when looking up area codes"],"example":"Brand location data not found"}},"type":"object"},"SavedAreacodeResponse":{"description":"The area code saved or suggested for the account's 10DLC registration.","required":["areacode"],"properties":{"areacode":{"$ref":"#/components/schemas/SavedAreacode","description":"The saved or suggested area code."}},"type":"object"},"ScopeAssessmentResponse":{"description":"The campaign elements the model identified as targets of the requested edit.","required":["elements","summary","totalElements","isAmbiguous","latencyMs"],"properties":{"elements":{"description":"The elements to edit, only those whose id the campaign markup really contains. Empty when the request was too vague to point at specific elements.","type":"array","items":{"required":["id","type","description","confidence"],"properties":{"id":{"description":"Id of the element in the campaign's XML representation.","type":"string","example":"s1_c1_b1"},"type":{"description":"Kind of element: text, image, button, divider, social or menu.","type":"string","example":"button"},"description":{"description":"What the element is and why it matches the request, in the model's words.","type":"string","example":"Primary call-to-action button below the hero"},"confidence":{"description":"How well the element matches the request, 0 to 100.","type":"integer","example":92},"xmlSnippet":{"description":"The element's XML, when it was captured.","type":"string","example":"<button id=\"s1_c1_b1\">Shop now</button>"}},"type":"object"}},"summary":{"description":"How many of the identified elements there are of each type, keyed by type name.","type":"object","example":{"text":0,"image":0,"button":1,"divider":0,"social":0,"menu":0},"additionalProperties":{"type":"integer"}},"totalElements":{"description":"Number of entries in elements.","type":"integer","example":1},"isAmbiguous":{"description":"True when the model judged the request unclear or applicable to many elements.","type":"boolean","example":false},"latencyMs":{"description":"How long the assessment took, in milliseconds with two decimals.","type":"number","format":"float","example":1843.27},"message":{"description":"Only present when elements is empty: a fixed hint to refine the request. Never null.","type":"string","example":"No elements identified for editing. Please refine your request."}},"type":"object"},"ScribeConfigRequest":{"description":"The calling user's complete Scribe configuration. Replaces what is stored.","required":["enabled"],"properties":{"enabled":{"description":"Master switch: when false, Scribe is off for the user regardless of the per-source settings.","type":"boolean","example":true},"calendar":{"description":"Calendar sources: google_calendar, outlook_calendar.","type":"object"},"callRecordings":{"description":"Call recording sources: gong.","type":"object"},"email":{"description":"Email sources: gmail, outlook. Each lists the deal connection ids Scribe reads.","type":"object"}},"type":"object"},"SeedDataExecuteParams":{"description":"The request as the run used it, with window renamed window_days.","required":["domain","state","window_days","inside","outside","performance"],"properties":{"domain":{"description":"The domain that was seeded.","type":"string","example":"campaigns"},"state":{"description":"The state that was applied.","type":"string","example":"active"},"window_days":{"description":"The window, in days.","type":"integer","example":30},"inside":{"description":"Requested count inside the window.","type":"integer","example":8},"outside":{"description":"Requested count outside the window.","type":"integer","example":42},"performance":{"description":"The performance profile that was applied.","type":"string","example":"steady_good"}},"type":"object"},"SeedDataExecuteReport":{"description":"What the run did. For state empty only domain and actions are present.","required":["domain","actions"],"properties":{"domain":{"description":"The domain the report is about, the same as params.domain.","type":"string","example":"campaigns"},"inside":{"description":"Requested count inside the window. Left out for state empty.","type":"integer","example":8},"outside":{"description":"Requested count outside the window. Left out for state empty.","type":"integer","example":42},"actions":{"description":"One sentence per step the run took, in order: records deleted or seeded to reach the total, dates placed inside and outside the window, performance applied. Fixed English wording with the counts filled in.","type":"array","items":{"type":"string"},"example":["Seeded 50 campaigns (0 → 50)","Placed 8 campaigns inside 30d window","Remaining campaigns moved outside 30d window","Updated 50 campaigns to steady_good performance"]},"contacts_cascade":{"description":"Present only when seeding campaigns, automations or deals found fewer than 2000 active contacts and created the missing ones.","type":"string","example":"Seeded 1500 contacts (500 → 2000)"}},"type":"object"},"SeedDataExecuteResponse":{"description":"The seed run finished.","required":["success","params","report"],"properties":{"success":{"description":"Always true: a run that fails answers 400 or 503 instead.","type":"boolean","example":true},"params":{"$ref":"#/components/schemas/SeedDataExecuteParams"},"report":{"$ref":"#/components/schemas/SeedDataExecuteReport"}},"type":"object"},"SeedDataExecutionFailedResponse":{"description":"The run stopped on a RuntimeException from the seeding SQL, for example no user on the account to own the seeded records, or an INSERT that returned no id. The cause is only logged; part of the data may already have been changed.","required":["error"],"properties":{"error":{"description":"Always this fixed sentence.","type":"string","enum":["Seed data execution failed"],"example":"Seed data execution failed"}},"type":"object"},"SeedDataHttpError":{"description":"One error in a SeedDataHttpErrorResponse.","required":["status","detail"],"properties":{"status":{"description":"HTTP status code as a string, the same as the response status.","type":"string","example":"403"},"detail":{"description":"Account not in allowlist for a 403; Failed to execute seed data operation for a 503.","type":"string","example":"Account not in allowlist"}},"type":"object"},"SeedDataHttpErrorResponse":{"description":"Error body for 403 (the account is not on the seed-data allowlist, or this is not a staging environment) and 503 (the run failed with something other than a RuntimeException).","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"$ref":"#/components/schemas/SeedDataHttpError"}}},"type":"object"},"SeedDataPrepareRequest":{"description":"What to seed: one data domain, the state to leave it in, and how many records to place inside and outside the reporting window. Every field is a JSON string or number of the type shown; a value of another JSON type answers 422 with Unexpected type.","required":["domain","state","performance"],"properties":{"domain":{"description":"The data domain to seed. automations are campaigns flagged as automation sends.","type":"string","enum":["contacts","campaigns","automations","deals"],"example":"campaigns"},"state":{"description":"active or dormant seed the domain to the requested counts and place dates inside and outside the window; both behave the same today. empty deletes every record of the domain instead and ignores window, inside, outside and performance (deleting contacts also deletes campaigns, automations and deals).","type":"string","enum":["active","dormant","empty"],"example":"active"},"window":{"description":"Reporting window in days, 3 to 365. Records counted as inside are dated within this many days before now; the rest are dated earlier.","type":"integer","maximum":365,"minimum":3,"example":30},"inside":{"description":"How many records of the domain to date inside the window, 0 to 500.","type":"integer","maximum":500,"minimum":0,"example":8},"outside":{"description":"How many records of the domain to date outside the window, 0 to 500. inside plus outside is the total the domain is brought to: extra records are deleted, missing ones are created.","type":"integer","maximum":500,"minimum":0,"example":42},"performance":{"description":"Engagement profile for the seeded records: steady_good and steady_bad set uniformly good or bad rates (or deal values), trending_up and trending_down grade them across the window, alternating mixes them. Ignored for contacts beyond spreading their dates.","type":"string","enum":["steady_good","steady_bad","alternating","trending_down","trending_up"],"example":"steady_good"}},"type":"object"},"SeedDataStatusDistribution":{"description":"How many records of a domain fall inside and outside the window.","required":["inside","outside","total"],"properties":{"inside":{"description":"Records dated inside the window. Contacts count once however many lists they are on; deals are open deals modified in the window.","type":"integer","example":8},"outside":{"description":"Records outside the window: total minus inside, never below 0.","type":"integer","example":42},"total":{"description":"All records of the domain that count: active contacts, sent campaigns, automation campaigns, or open deals.","type":"integer","example":50}},"type":"object"},"SeedDataStatusFilterResult":{"description":"Whether the account passes one insight account filter, and why.","required":["pass","detail"],"properties":{"pass":{"description":"True when the account currently satisfies the filter.","type":"boolean","example":true},"detail":{"description":"The count or fact the result is based on, in fixed English wording.","type":"string","example":"1200 active contacts"}},"type":"object"},"SeedDataStatusResponse":{"description":"The account's seed-data state for the requested domains.","required":["success","window","domains","filters","distributions","scenarios"],"properties":{"success":{"description":"Always true: a failure answers 503 instead.","type":"boolean","example":true},"window":{"description":"The window in days the results were computed for. The window query parameter, or 30 when it is below 3.","type":"integer","example":30},"domains":{"description":"The domains reported on: the requested one, or all four for all.","type":"array","items":{"type":"string","enum":["contacts","campaigns","automations","deals"]},"example":["contacts","campaigns","automations","deals"]},"filters":{"description":"For each reported domain, the insight account filters it feeds and whether the account passes each. The filter names are fixed per domain, with the window in days in some names, such as campaigns_30d.","type":"object","example":{"contacts":{"has_100_contacts":{"pass":true,"detail":"1200 active contacts"}}},"additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SeedDataStatusFilterResult"}}},"distributions":{"description":"For each reported domain, how many records fall inside and outside the window.","type":"object","example":{"campaigns":{"inside":8,"outside":42,"total":50}},"additionalProperties":{"$ref":"#/components/schemas/SeedDataStatusDistribution"}},"scenarios":{"description":"Suggested seed setups. The same fixed list on every call, whatever the domain.","type":"array","items":{"$ref":"#/components/schemas/SeedDataStatusScenario"}}},"type":"object"},"SeedDataStatusScenario":{"description":"A suggested seed setup, ready to send to POST /ai/insights/seed-data/execute.","required":["label","inside","outside","state","performance"],"properties":{"label":{"description":"Plain-language name of the account situation.","type":"string","example":"Healthy active with history"},"inside":{"description":"Records to place inside the window.","type":"integer","example":25},"outside":{"description":"Records to place outside the window.","type":"integer","example":50},"state":{"description":"The state to seed.","type":"string","enum":["empty","active","dormant"],"example":"active"},"performance":{"description":"The performance profile to apply.","type":"string","example":"steady_good"}},"type":"object"},"SeedDataValidationError":{"description":"One field of the request body that failed validation.","required":["status","title","detail","source"],"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed, in the fixed wording of the request's validation rules; Unexpected type when the value has the wrong JSON type.","type":"string","example":"The \"domain\" parameter is required."},"source":{"description":"The field that failed.","required":["pointer"],"properties":{"pointer":{"description":"The field, as /data/attributes/<field name>.","type":"string","example":"/data/attributes/domain"}},"type":"object"}},"type":"object"},"SeedDataValidationErrorResponse":{"description":"Error body for a request body that fails validation.","required":["errors"],"properties":{"errors":{"description":"One error per failed check. A field can appear more than once, for example an omitted domain fails both the required and the allowed-values checks.","type":"array","items":{"$ref":"#/components/schemas/SeedDataValidationError"}}},"type":"object"},"SegmentCatalogAllowedStrategy":{"description":"A fetch strategy the catalog key accepts, as configured in segment_catalog_rules.json. limit and order are not listed here.","required":["type"],"properties":{"type":{"description":"Strategy type the key accepts. A request of the same type with another argument (recent:3 when recent:100 is listed) is accepted too.","type":"string","enum":["all","recent","recent_days","search"],"example":"recent"},"args":{"description":"Configured argument: N for recent, days for recent_days. Omitted for all and search.","type":["integer","string"],"example":100}},"type":"object"},"SegmentCatalogEntry":{"description":"One catalog key (tag, list, contactCustomField, emailCampaign, automatedEmail, customObject or automation): how many records the account has, the slice returned and the strategies the key accepts.","required":["count","fetchStrategy","allowedStrategies","slice"],"properties":{"count":{"description":"Total records of this kind in the account, before any limit. 0 when the account lacks the entitlement the key needs (campaigns for emailCampaign).","type":"integer","example":2500},"maxLimit":{"description":"Ceiling for a client limit on this key, from segment_catalog_rules.json. Omitted for keys without one (emailCampaign, automatedEmail, customObject), whose client limit is ignored.","type":"integer","example":2000},"fetchStrategy":{"oneOf":[{"$ref":"#/components/schemas/SegmentCatalogFetchStrategy","description":"The strategy the slice was selected with. null when the entry is empty because the account lacks the entitlement the key needs."},{"type":"null"}],"description":"The strategy the slice was selected with. null when the entry is empty because the account lacks the entitlement the key needs."},"allowedStrategies":{"description":"The strategies POST /ai/segment/catalog accepts for this key.","type":"array","items":{"$ref":"#/components/schemas/SegmentCatalogAllowedStrategy"}},"slice":{"$ref":"#/components/schemas/SegmentCatalogSlice","description":"The records selected."},"standardFields":{"description":"The built-in contact fields. Only on the contactCustomField key, and left out when its slice is a search result.","type":"array","items":{"$ref":"#/components/schemas/SegmentCatalogStandardField"}}},"type":"object"},"SegmentCatalogFetchStrategy":{"description":"The fetch strategy applied to a catalog entry: how its slice was selected, how many rows it was allowed and in which id order.","required":["type","order"],"properties":{"type":{"description":"Strategy type. all: the full set up to limit; recent: the N newest; recent_days: those created in the last N days; search: those whose name or label matches args.","type":"string","enum":["all","recent","recent_days","search"],"example":"recent"},"args":{"description":"Strategy argument. N for recent, the number of days for recent_days, the search phrase for search (a|b matches either). Omitted for all.","type":["integer","string"],"example":100},"limit":{"description":"Row ceiling the slice applied: the client limit for all and search when the key has a maxLimit, clamped to it; N for recent, clamped to 1000 (or maxLimit); 100 for recent_days; 500 otherwise. Omitted when the strategy carries no limit.","type":"integer","example":100},"order":{"description":"Id order of the slice. Always desc for recent and recent_days; asc unless requested otherwise for all and search.","type":"string","enum":["asc","desc"],"example":"desc"}},"type":"object"},"SegmentCatalogSlice":{"description":"The records selected for a catalog key.","required":["type","items"],"properties":{"type":{"description":"search when the slice is the result of a search strategy, catalog otherwise.","type":"string","enum":["catalog","search"],"example":"catalog"},"items":{"description":"The records, each with at least id and label. list records carry channel (email or sms); contactCustomField records may carry type, perstag and options. A search with no match falls back to the key's first non-search allowed strategy, so items can be non-empty for a search that matched nothing.","type":"array","items":{"type":"object","additionalProperties":true},"example":[{"id":12,"label":"VIP customers"}]}},"type":"object"},"SegmentCatalogStandardField":{"description":"A built-in contact field (name, email, phone, ...), as the automation builder defines it.","required":["id","label","type","perstag"],"properties":{"id":{"description":"Field key as the automation builder names it.","type":"string","example":"first_name"},"label":{"description":"Translation key of the field title, not the translated text.","type":"string","example":"fields:contacts:standard:first-name"},"type":{"description":"Field type; text for every standard field.","type":"string","example":"text"},"perstag":{"description":"Personalization tag of the field, without the % signs.","type":"string","example":"FIRSTNAME"}},"type":"object"},"SegmentConversionTriggerMessage":{"description":"Flat shape produced by SegmentConversionTriggerSQSMessage::jsonSerialize(). May arrive wrapped as {\"data\": {...}} when relayed through the queue-http-service -- see the oneOf on the containing requestBody schema.","required":["triggerId","contactId","timestamp"],"properties":{"triggerId":{"description":"ConversionTrigger id.","type":"integer"},"contactId":{"description":"Subscriber (contact) id.","type":"integer"},"timestamp":{"description":"Queue timestamp in Y-m-d H:i:s format, e.g. '2026-10-05 16:43:06' -- not RFC 3339 date-time. Grounded against ConversionSegmentationWorker's Carbon::now()->format('Y-m-d H:i:s') and SegmentConversionTriggerSQSMessage's constructor doc.","type":"string"}},"type":"object"},"SegmentDO":{"title":"SegmentDO","type":"object","required":["segment_conditions","segment_condition_groups","segment_condition_group_operator"],"properties":{"created_date":{"type":"string","format":"date-time","example":"2024-01-30T14:56:02.952Z"},"meta":{"type":"object","additionalProperties":{"type":"string"}},"segment_condition_group_operator":{"type":"string","description":"The operator that combines the condition groups","enum":["and","or"],"example":"and"},"segment_condition_groups":{"type":"array","items":{"$ref":"#/components/schemas/ConditionGroupDO"}},"segment_conditions":{"type":"array","items":{"$ref":"#/components/schemas/ConditionDO"}},"segment_hash":{"type":"string","readOnly":true},"segment_id":{"type":"string","readOnly":true},"user_id":{"type":"string","description":"The user that created this version of the segment","readOnly":true},"name":{"type":"string","description":"Optional. Segments with this attribute are Saved Segments and will show up on the /app/audiences page. Value must be unique. Can be defined at creation time, but cannot be added to a Segment during an update operation"},"description":{"type":"string","maxLength":1000,"description":"Optional for Saved Segments"},"category":{"type":"string","enum":["AUDIENCE"],"readOnly":true}}},"SegmentDataDO":{"title":"SegmentDataDO","type":"object","properties":{"attributes":{"$ref":"#/components/schemas/SegmentDO"},"id":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195","readOnly":true},"type":{"type":"string","readOnly":true,"example":"Segment.v2"}}},"SegmentErrorResponse":{"description":"One error message.","required":["error"],"properties":{"error":{"description":"What went wrong. The exception message for a 500; the raw upstream body when the Segment On Demand service failed without a JSON errors list.","type":"string","example":"fieldId is required and must be a positive integer."}},"type":"object"},"SegmentFieldValuesResponse":{"description":"The distinct values stored for one contact custom field.","required":["fieldId","type","source","count","maxLimit","limit","values"],"properties":{"fieldId":{"description":"Id of the contact custom field, as requested.","type":"integer","example":7},"type":{"description":"Type of the field as stored (text, textarea, dropdown, listbox, checkbox, radio, date, ...).","type":"string","example":"text"},"source":{"description":"Where the values come from: options for dropdown, listbox, checkbox and radio fields (their configured options), contactValues for every other type (the distinct values contacts hold).","type":"string","enum":["options","contactValues"],"example":"contactValues"},"count":{"description":"Number of values returned.","type":"integer","example":2},"maxLimit":{"description":"Always 2000: the most values one response can carry.","type":"integer","example":2000},"limit":{"description":"The limit applied: the requested limit clamped to maxLimit, or 500 when none was given.","type":"integer","example":500},"values":{"description":"The distinct values, at most limit of them.","type":"array","items":{"type":"string"},"example":["Harbor Point","Fells Point"]}},"type":"object"},"SegmentMatchDetail":{"type":"object","title":"SegmentMatchDetail","properties":{"contact_id":{"type":["integer","string"],"description":"The contact id from the request: a number when it is numeric, otherwise the identifier as given","example":3},"segment_id":{"type":"string","description":"The segment's UUID","example":"5d5a257a-b9c8-44c1-9709-724d3829a334"},"timestamp":{"type":"string","format":"date-time","description":"When the match was evaluated, in UTC","example":"2026-10-09T16:11:19.239Z"},"contact_matches_segment":{"type":"boolean","description":"Whether the contact matches the whole segment"},"groups":{"$ref":"#/components/schemas/SegmentMatchDetailGroups"}}},"SegmentMatchDetailCondition":{"type":"object","title":"SegmentMatchDetailCondition","properties":{"translation":{"type":"string","description":"The condition in plain language. Left out when the segment could not be translated.","example":"Has opened any email"},"contact_matches":{"type":"boolean","description":"Whether the contact matches this condition"}}},"SegmentMatchDetailError":{"type":"object","title":"SegmentMatchDetailError","properties":{"status":{"type":"string","example":"404 NOT_FOUND"},"title":{"type":"string","example":"The contact was not found"}}},"SegmentMatchDetailErrorResponse":{"type":"object","title":"SegmentMatchDetailErrorResponse","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/SegmentMatchDetailError"}}}},"SegmentMatchDetailGroup":{"type":"object","title":"SegmentMatchDetailGroup","properties":{"contact_matches_group":{"type":"boolean","description":"Whether the contact matches this group. Left out when a condition whose result is unknown would decide it."},"operator":{"type":"string","description":"How the group's conditions are joined, as shown to the user","example":"And"},"conditions":{"type":"object","description":"Each of the group's conditions, keyed by its condition id","additionalProperties":{"$ref":"#/components/schemas/SegmentMatchDetailCondition"}}}},"SegmentMatchDetailGroups":{"type":"object","title":"SegmentMatchDetailGroups","description":"The operator that joins the segment's groups, and each group keyed by its group id","properties":{"operator":{"type":"string","description":"How the groups are joined, as shown to the user","example":"Or"}},"additionalProperties":{"$ref":"#/components/schemas/SegmentMatchDetailGroup"}},"SegmentMatchDetailResponse":{"type":"object","title":"SegmentMatchDetailResponse","properties":{"data":{"$ref":"#/components/schemas/SegmentMatchDetail"}}},"SegmentServiceErrorsResponse":{"description":"The Segment On Demand service's errors, forwarded with its status code.","required":["errors"],"properties":{"errors":{"description":"The errors as the service sent them, minus each error's code. Typically status and title.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the service response, as text.","type":"string","example":"422 UNPROCESSABLE_ENTITY"},"title":{"description":"What the service refused.","type":"string","example":"This segment scenario is not supported"}},"type":"object","additionalProperties":true},"example":[{"status":"422 UNPROCESSABLE_ENTITY","title":"This segment scenario is not supported"}]}},"type":"object"},"SegmentSummaryCountDO":{"title":"Segment counts totals object","type":"object","properties":{"count":{"type":"number","readOnly":false,"example":1500},"last_total_updated":{"type":"string","readOnly":false,"description":"Time that this last total count was requested to be updated","format":"date-time","example":"2024-01-30T14:56:02.952Z"},"run_id":{"type":"string","readOnly":false,"example":"744390a5-208e-4c3d-b709-b3c3ea6e5948"},"run_id_start":{"type":"string","readOnly":false,"description":"Time that this start time of the last run in UTC","format":"date-time","example":"2024-01-30T15:56:02.952Z"},"run_id_end":{"type":"string","readOnly":false,"description":"Time that this end time of the last run in UTC","format":"date-time","example":"2024-01-30T15:56:04.952Z"}}},"SegmentSummaryCountsDO":{"title":"Segment summary counts object containing all counts","type":"object","properties":{"last_total":{"$ref":"#/components/schemas/SegmentSummaryCountDO"},"last_active_total":{"$ref":"#/components/schemas/SegmentSummaryCountDO"}}},"SegmentSummaryDO":{"title":"Segment SummaryDO","type":"object","properties":{"segment_id":{"type":"string","readOnly":true,"example":"d2c5a14a-771d-4cc0-a126-3513a5201940"},"category":{"type":"string","enum":["audience"],"readOnly":true},"name":{"type":"string","description":"Name of the audience segment","readOnly":true},"counts":{"$ref":"#/components/schemas/SegmentSummaryCountsDO"},"created_date":{"type":"string","readOnly":true,"format":"date-time","example":"2024-01-30T14:56:02.952Z"},"updated_date":{"type":"string","readOnly":true,"format":"date-time","example":"2024-03-12T14:56:02.952Z"},"last_used_date":{"type":"string","readOnly":true,"format":"date-time","example":"2025-07-13T14:56:02.952Z"}}},"SegmentSummaryDataDO":{"title":"Segment Summary DataDO","type":"object","properties":{"attributes":{"$ref":"#/components/schemas/SegmentSummaryDO"},"id":{"type":"string"},"type":{"type":"string"}}},"SegmentSummaryErrorRootDO":{"title":"Segment Summary RootDO","type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetailDO"}}}},"SegmentSummarySuccessRootDO":{"title":"Segment Summary RootDO","type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentSummaryDataDO"}}}},"SegmentTranslationDO":{"type":"object","title":"SegmentTranslationDO","description":"Translated segment with natural language text","properties":{"text":{"type":"string","description":"Complete human-readable description of the segment"},"operator":{"type":"string","description":"Top-level logical operator (and/or)","enum":["and","or"]},"groups":{"type":"object","description":"Map of group IDs to their translations","additionalProperties":{"$ref":"#/components/schemas/GroupTranslationDO"}}}},"SegmentTranslationResponseDO":{"type":"object","title":"SegmentTranslationResponseDO","description":"Response containing translated segment text or errors","properties":{"data":{"$ref":"#/components/schemas/SegmentTranslationDO"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetailDO"}}}},"SegmentcomContactError":{"type":"object","description":"Why the event was not applied.","properties":{"errors":{"description":"An object with message when neither user_id nor anonymous_id is at the top level of the body; otherwise the list of errors the contact save produced.","oneOf":[{"type":"object","properties":{"message":{"type":"string","description":"What is missing.","example":"user_id or anonymous_id is required"}}},{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Short title of the error.","example":"Required field missing"},"detail":{"type":"string","description":"Which field is missing.","example":"Test Field is required"},"code":{"type":"string","description":"field_missing. followed by the field name.","example":"field_missing.Test_Field"},"field":{"type":"string","description":"Id of the missing field.","example":"1"},"error":{"type":"string","description":"Always required_field_was_not_provided.","example":"required_field_was_not_provided"}}}}]}}},"SegmentcomContactEvent":{"type":"object","description":"A Segment event. Members not listed here are ignored.","properties":{"type":{"type":"string","description":"The Segment event type, such as identify, track or page. track and page need an email, from the body or from the contact that is found. Left out, the event is treated as neither track nor page.","example":"identify"},"user_id":{"type":"string","description":"The Segment user id. This or anonymous_id must be at the top level of the body. Stored as the contact's Segment id unless it contains @, in which case it is used as the email.","example":"test_id"},"anonymous_id":{"type":"string","description":"The Segment anonymous id. Matched against the stored Segment id or the email address; stored as the Segment id when there is no user_id.","example":"8c6c0a3a-1f5e-4b4f-9a43-2d9f1b6f7e21"},"email":{"type":"string","description":"Email address of the contact. Also read from traits and properties.","example":"jane@example.com"},"traits":{"$ref":"#/components/schemas/SegmentcomContactTraits"},"properties":{"type":"object","description":"Event properties. Only user_id, anonymous_id and email are read from them, when they are not at the top level or in traits.","properties":{"user_id":{"type":"string","description":"The Segment user id."},"anonymous_id":{"type":"string","description":"The Segment anonymous id."},"email":{"type":"string","description":"Email address of the contact."}}}},"example":{"type":"identify","user_id":"test_id","traits":{"email":"jane@example.com","firstName":"Jane","lists":[{"id":12,"status":"active"}],"tags":["VIP"]}}},"SegmentcomContactResult":{"type":"object","required":["contact"],"description":"The outcome for the contact.","properties":{"contact":{"description":"The contact that was saved, or the list [\"email is required\"] when a track or page event had no email to use and nothing was saved.","oneOf":[{"type":"object","description":"The contact that was saved.","properties":{"id":{"type":"string","description":"Id of the contact.","example":"2"},"email":{"type":"string","description":"Email address of the contact.","example":"jane@example.com"}}},{"type":"array","description":"Always the single item email is required.","items":{"type":"string"},"example":["email is required"]}]}}},"SegmentcomContactTraits":{"type":"object","description":"Traits of the contact. Any other trait whose lower-cased name equals the personalization tag of a custom field sets that field: a date field takes the date part of the value (null or NULL clears it, a value that is not a date is skipped); a checkbox or listbox field needs a list whose items are all existing options, or the trait is skipped; true and false on a text field are stored as the words true and false.","additionalProperties":true,"properties":{"email":{"type":"string","description":"Email address of the contact.","example":"jane@example.com"},"first_name":{"type":"string","description":"First name. firstName and firstname are read too.","example":"Jane"},"firstName":{"type":"string","description":"First name.","example":"Jane"},"firstname":{"type":"string","description":"First name.","example":"Jane"},"last_name":{"type":"string","description":"Last name. lastName and lastname are read too.","example":"Doe"},"lastName":{"type":"string","description":"Last name.","example":"Doe"},"lastname":{"type":"string","description":"Last name.","example":"Doe"},"name":{"type":"string","description":"Full name, used only when no first or last name trait is sent: split at the first space into first and last name.","example":"Jane Doe"},"phone":{"type":"string","description":"Phone number.","example":"555-555-5555"},"lists":{"type":"array","description":"List subscriptions to set. A list the contact is already on is set to the given status; a list the contact is not on yet is always subscribed, whatever the status.","items":{"type":"object","required":["id","status"],"properties":{"id":{"type":"integer","description":"Id of the list.","example":12},"status":{"type":"string","description":"active subscribes; any other value unsubscribes.","example":"active"}}}},"tags":{"type":"array","description":"Names of tags to add to the contact.","items":{"type":"string"},"example":["VIP"]},"tags_reset":{"type":"integer","description":"The number 1 removes every tag from the contact before tags are added. Any other value, including \"1\" or true, is ignored.","example":1}}},"SegmentcomOutboundContext":{"type":"object","description":"What the outbound service needs to send the events to Segment.","required":["account_id","segmentio_apikey_outgoing","items"],"properties":{"account_id":{"type":"integer","description":"Id of the account.","example":1234},"segmentio_apikey_outgoing":{"type":"string","description":"The account's outgoing Segment write key."},"items":{"type":"array","description":"One resolved identity per item.","items":{"type":"object","properties":{"contact_db_id":{"type":["integer","null"],"description":"Id of the contact found, or null when there is none.","example":2},"contact_item_id":{"type":["integer","null"],"description":"The item's contact.id, or null when it had none.","example":2},"contact_item_email":{"type":["string","null"],"description":"The item's contact.email. When the item has none and the contact has no stored Segment id, the contact's own email address; otherwise null.","example":"jane@example.com"},"user_id":{"type":["string","null"],"description":"The contact's stored Segment id, when it has one without a hyphen.","example":"test_id"},"anonymous_id":{"type":["string","null"],"description":"The contact's stored Segment id when it contains a hyphen; otherwise, when the contact has no stored Segment id, the email in contact_item_email.","example":null}}}}}},"SegmentcomOutboundContextRequest":{"type":"object","description":"One event, or items, a list of events.","properties":{"account_id":{"type":"integer","description":"Id of the account the event belongs to. Only the first item's value is checked.","example":1234},"contact":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the contact.","example":2},"email":{"type":"string","description":"Email address of the contact.","example":"jane@example.com"}},"description":"The contact the event is about: id is used for the lookup, email when the contact has no stored Segment id."},"items":{"type":"array","description":"The events to resolve. When present, the members at the top level are not used.","items":{"type":"object","description":"One event to resolve.","properties":{"account_id":{"type":"integer","description":"Id of the account the event belongs to. Only the first item's value is checked.","example":1234},"contact":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the contact.","example":2},"email":{"type":"string","description":"Email address of the contact.","example":"jane@example.com"}},"description":"The contact the event is about: id is used for the lookup, email when the contact has no stored Segment id."}}}}},"example":{"items":[{"account_id":1234,"contact":{"id":2,"email":"jane@example.com"}}]}},"SelectRecommendationRequest":{"description":"The stored recommendation to run asset selection for. Sent only by Hosted's own background dispatcher.","required":["assetType","externalId"],"properties":{"assetType":{"description":"Kind of asset to select.","type":"string","enum":["automation","campaign"],"example":"automation"},"externalId":{"description":"What the recommendation was stored for: the business goal id, or the goal recipe template hash for a template recommendation.","type":["integer","string"],"example":123},"startTime":{"description":"When the selection was first requested, as a Unix timestamp with microseconds. Used only to time the whole selection; left out or null it is not used.","type":["number","null"],"example":1792070000.123456}},"type":"object"},"SelectRequest":{"description":"What to generate: the brief, where the request comes from and what to style and source it with. Starts a generation whose progress is polled by requestId.","required":["prompt","source"],"properties":{"prompt":{"description":"The brief the campaign is written from.","type":"string","example":"Announce our October arrivals to newsletter subscribers"},"source":{"description":"Where the request comes from; agent and initiatives-detail also file the campaign in that source's folder.","type":"string","example":"agent"},"brandkitUuid":{"description":"UUID of a brand kit of the account to style the email with, or null for none.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"brandkitRecord":{"description":"The stored brand kit, from brandkitUuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"summarizationUuid":{"description":"UUID of a finished content summarization of the account to draw the copy from, or null for none. Refused with 409 while the summarization is in progress and 422 when it errored.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"summarizationRecord":{"description":"The stored summarization, from summarizationUuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"useSummarizationLink":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"template":{"description":"Key of the layout to generate on. Omitted, the server picks one for the prompt and brand kit.","type":["string","null"],"enum":["promote","welcome","monthly","whatsnew","announcement","letsmove","clean","producthighlight","flashsale","chillvibes","boldheader","colorblocks","fashioneditorial","flashsalecountdown","freetrialcountdown","elegantambiance"],"example":"promote"},"campaignName":{"description":"Name for the campaign. Omitted, a placeholder is used until the model names it.","type":["string","null"],"example":"October newsletter"},"seriesId":{"description":"Id of an automation of the account to create the campaign for, or null for a standalone campaign.","type":["integer","null"],"example":12},"tone":{"description":"Tone of voice for the copy, or null to leave it to the model.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"subject":{"description":"Subject line to keep. Null lets the model write one.","type":["string","null"],"example":"Your October picks are here"},"preHeader":{"description":"Preheader text to keep. Null lets the model write one.","type":["string","null"],"example":"New arrivals, member offers and more"},"lang":{"description":"Language to write in. Omitted, the calling user's language is used.","type":["string","null"],"example":"en"},"labelId":{"description":"Id of a campaign folder (label) of the account to file the campaign under, or null.","type":["integer","null"],"example":3},"campaignId":{"description":"Id of an existing campaign of the account to write the content into instead of creating one; its generation record, if any, is reused. Null creates a campaign.","type":["integer","null"],"example":4821},"messageId":{"description":"Id of the existing message to write into when campaignId is given. It must not already have editor markup. Null creates a message.","type":["integer","null"],"example":9134},"sessionId":{"description":"Caller's session id, carried through the queue for tracing.","type":["string","null"],"example":"sess_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"ctaUrl":{"description":"URL for the primary button. Omitted or blank, the summarization's URL is used when one is linked.","type":["string","null"],"example":"https://example.com/october"},"isAssetDraft":{"description":"True to write the result as an asset draft instead of a live campaign. Honoured only when asset-draft creation is enabled for the account.","type":["boolean","null"],"example":false},"images":{"description":"Images to place in the email, at most 7, each with its http or https URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image, at most 2048 characters.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}},"externalContent":{"description":"Up to 4000 characters of reference text for the model to draw on, or null.","type":["string","null"],"example":"Our October arrivals include the Autumn coat in three colours and the Harvest candle set."}},"type":"object"},"SendOutcome":{"description":"How a prepare, confirm or unschedule ended.","enum":["ready","not_ready","success","not_supported","not_permitted","not_found","changed","expired","confirmation_mismatch","send_time_passed","not_scheduled","not_modifiable","refused","submitted_for_approval","unconfirmed"],"title":"SendOutcome","type":"string"},"SendSummary":{"description":"What the confirm will send, frozen when it was prepared.","properties":{"campaign_id":{"title":"Campaign Id","type":"integer"},"campaign_name":{"title":"Campaign Name","type":"string"},"campaign_type":{"description":"single, or split for an A/B test.","title":"Campaign Type","type":"string"},"send_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"description":"When it sends, in UTC; null for a send now.","title":"Send At"},"predictive_send":{"title":"Predictive Send","type":"boolean"},"lists":{"items":{"$ref":"#/components/schemas/SendSummaryList"},"title":"Lists","type":"array"},"segment_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The segment narrowing the lists; null when there is none.","title":"Segment Id"},"recipient_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Contacts it would reach as configured now; null when it could not be counted.","title":"Recipient Count"},"emails":{"items":{"$ref":"#/components/schemas/SendSummaryEmail"},"title":"Emails","type":"array"},"content_hash":{"description":"A digest of every email's content; a confirm sends only this content.","title":"Content Hash","type":"string"}},"required":["campaign_id","campaign_name","campaign_type","send_at","predictive_send","lists","segment_id","recipient_count","emails","content_hash"],"title":"SendSummary","type":"object"},"SendSummaryEmail":{"description":"One email the campaign sends: one, or one per version of an A/B test.","properties":{"message_id":{"title":"Message Id","type":"integer"},"subject":{"title":"Subject","type":"string"},"preheader":{"description":"Preview text shown after the subject; may be empty.","title":"Preheader","type":"string"},"from_name":{"title":"From Name","type":"string"},"from_email":{"title":"From Email","type":"string"},"reply_to":{"title":"Reply To","type":"string"}},"required":["message_id","subject","preheader","from_name","from_email","reply_to"],"title":"SendSummaryEmail","type":"object"},"SendSummaryList":{"properties":{"list_id":{"title":"List Id","type":"integer"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The list's name; null when it could not be read.","title":"Name"}},"required":["list_id"],"title":"SendSummaryList","type":"object"},"ServerErrorResponse":{"description":"Error body the API writes when an action fails with an exception it does not handle itself.","required":["message"],"properties":{"message":{"description":"A fixed message. The cause is only logged.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"},"SetAudienceRequest":{"properties":{"campaign_id":{"description":"Id of the campaign.","examples":[42],"exclusiveMinimum":0,"title":"Campaign Id","type":"integer"},"list_ids":{"description":"Every list the campaign should send to. Replaces the lists it holds now: a list left out is removed.","examples":[[5,6]],"items":{"exclusiveMinimum":0,"type":"integer"},"minItems":1,"title":"List Ids","type":"array"},"segment_id":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"default":null,"description":"Segment narrowing those lists: a classic numeric id or an audience UUID from this account. Null clears any segment.","title":"Segment Id"}},"required":["campaign_id","list_ids"],"title":"SetAudienceRequest","type":"object"},"SettingsHttpErrorResponse":{"type":"object","description":"Error body for a request refused with an HTTP error status.","required":["errors"],"properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","required":["status"],"properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status.","example":403},"title":{"type":"string","description":"Translated name of the HTTP status."},"detail":{"type":"string","description":"What was refused. Left out when the refusal gives no message."}}}}}},"SettingsServerErrorResponse":{"type":"object","description":"Error body the API writes when the request fails with an exception the endpoint does not handle.","required":["message"],"properties":{"message":{"type":"string","description":"A fixed message. The cause is only logged.","example":"Something went wrong on our end. Please try again later"}}},"SideloadedAccounts":{"type":"array","description":"The linked account, as returned by the accounts API (its fields are documented under GET /accounts/{id}).","items":{"type":"object","properties":{"id":{"description":"ID of the account.","type":"string","examples":["2"]},"name":{"description":"The account's name.","type":"string","examples":["Example Account"]},"accountUrl":{"description":"The account's website URL. Null when none is set.","type":["string","null"],"examples":["https://www.example.com"]},"owner":{"description":"ID of the user who owns the account. Null when it has no owner.","type":["string","null"],"examples":["1"]},"contactCount":{"description":"How many contacts are associated with the account.","type":"string","examples":["1"]},"dealCount":{"description":"How many deals the account has.","type":"string","examples":["0"]},"createdTimestamp":{"description":"When the account was created, in ISO 8601 format.","type":"string","examples":["2019-05-15T15:58:16-05:00"]},"updatedTimestamp":{"description":"When the account was last changed, in ISO 8601 format.","type":"string","examples":["2019-05-15T15:58:16-05:00"]},"links":{"description":"URLs of the account's related records.","type":"object","properties":{"notes":{"type":"string"},"accountCustomFieldData":{"type":"string"},"accountContacts":{"type":"string"},"emailActivities":{"type":"string"},"contactEmails":{"type":"string"},"owner":{"type":"string"}}}}}},"SimpleChannel":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"channel_type":{"$ref":"#/components/schemas/ChannelTypeEnum"},"name":{"type":"string","maxLength":100},"channel_id":{"type":"string","maxLength":100},"status":{"$ref":"#/components/schemas/ChannelStatusEnum"},"created_on":{"type":"string","format":"date-time","title":"Created on"},"channel_provider":{"$ref":"#/components/schemas/ChannelProviderEnum"},"is_sandbox":{"type":"boolean"}},"required":["channel_id","id"]},"SimpleUser":{"type":"object","properties":{"first_name":{"type":"string","maxLength":150},"last_name":{"type":"string","maxLength":150},"email":{"type":"string","format":"email","maxLength":254},"id":{"type":"integer","readOnly":true},"profile_image":{"type":"string","format":"uri","nullable":true},"role":{"type":"integer","nullable":true}},"required":["email","id"]},"SiteMessageAttribute":{"type":"object","properties":{"title":{"type":"string","description":"Translated label the picker shows."},"attribute":{"type":"string","description":"The personalization tag without its `%` delimiters, e.g. `FIRSTNAME` or `EVENT:signup`."}}},"SiteMessageAttributeGroup":{"type":"object","description":"One group of the picker. In order: personal info (email, name and phone, the contact's custom fields, job title when the account has the Accounts feature, one `EVENT:<name>` per tracked event, social data fields, geolocation, subscription date, time and IP, list name and contact ID); Accounts, only when the account has the Accounts feature (the account's standard and custom field tags); and date (`TODAY`).","properties":{"name":{"type":"string","description":"Translated name of the group."},"attributes":{"type":"array","description":"The tags in the group.","items":{"$ref":"#/components/schemas/SiteMessageAttribute"}}}},"SiteMessageCompileJob":{"type":"object","required":["messageid"],"properties":{"messageid":{"type":["integer","string"],"description":"ID of the site message to compile."},"id":{"type":["integer","string"],"description":"Sent by Hosted with the same value as `messageid`. Not read."}}},"SiteMessageEmoji":{"type":"object","properties":{"code":{"type":"string","description":"The emoji character.","example":"😀"},"text":{"type":"string","description":"Short name of the emoji.","example":"grinning"},"category":{"type":"string","description":"Picker category.","enum":["people","nature","food","activity","travel","objects","symbols"]}}},"SiteMessageFieldChangesJob":{"type":"object","required":["subscriberid","fields"],"properties":{"subscriberid":{"type":["integer","string"],"description":"ID of the contact whose fields changed."},"fields":{"type":"object","description":"The fields that changed. Both lists are read; send an empty list rather than leaving one out.","properties":{"default":{"type":"array","description":"Personalization tag names of standard contact fields, upper case and without `%`. Hosted sends `FULLNAME`, `FIRSTNAME`, `LASTNAME`, `ORGANIZATION` and `PHONE`.","items":{"type":"string"}},"custom":{"type":"array","description":"IDs of custom contact fields. Each field's title, upper-cased, is the tag name used.","items":{"type":["integer","string"]}}}}}},"SiteMessagePosition":{"type":"object","properties":{"position":{"type":"string","description":"Where site messages appear: the value as saved, `bottom-right` when none is. The app offers `top-left`, `top-right`, `bottom-left` and `bottom-right`.","example":"bottom-right"}}},"SiteMessageQueueJob":{"type":"object","required":["subscriberid","messageid","blockid"],"properties":{"subscriberid":{"type":["integer","string"],"description":"ID of the contact to queue the message for."},"messageid":{"type":["integer","string"],"description":"ID of the site message."},"blockid":{"type":["integer","string"],"description":"ID of the automation block that queued the message. 0 or a non-numeric value does nothing."}}},"SnapshotResponse":{"properties":{"snapshot":{"description":"Totals across the broadcasts in the request.","properties":{"campaigns":{"description":"Number of broadcasts counted.","type":"integer"},"sends":{"description":"Number of messages sent.","type":"integer"},"deliveries":{"description":"Number of those messages that were delivered.","type":"integer"},"clicks":{"description":"Number of clicks on links in the messages.","type":"integer"},"replies":{"description":"Number of replies received.","type":"integer"},"failures":{"description":"Number of messages that failed to send.","type":"integer"},"optOuts":{"description":"Number of recipients who opted out.","type":"integer"},"revenue":{"description":"Revenue attributed to the broadcasts in the requested currency. Present only when SMS attribution is enabled for the account, and 0 unless currency is given.","type":"number","format":"float"},"credits":{"description":"Always 0 for broadcast snapshots; credits are not calculated for them.","type":"integer"}},"type":"object"}},"type":"object"},"SourceConnectionRequest":{"description":"Credentials of the customer owned MySQL database a database sync reads from.","required":["host","database","username"],"properties":{"syncId":{"description":"ID of the sync being edited, `0` (the default) for none. When `password` is omitted, the password stored on this sync is used, but only if `host`, `database` and `username` are the ones stored on it; any other connection is tried with an empty password. A sync that does not exist, or writes to a list the user cannot access, answers 404 (POST /syncs/connection looks it up only when `password` is omitted).","type":"integer","minimum":0,"example":0},"host":{"description":"Host name or address of the MySQL server. Leading and trailing spaces are trimmed. `localhost` is refused.","type":"string","example":"db.example.com"},"database":{"description":"Name of the database to read from.","type":"string","example":"crm"},"username":{"description":"Database user to connect as. Reading a table needs the SELECT (or ALL) privilege on it.","type":"string","example":"reader"},"password":{"description":"Password of `username`. An empty string is a valid password. Omit it, or send null, to use the password stored on the sync named by `syncId`.","type":["string","null"],"example":"s3cr3t"},"type":{"description":"Database type. MySQL is the only source supported.","type":"string","enum":["mysql"],"example":"mysql"},"charset":{"description":"Character set of the source data, for example `latin1`. When set, the connection uses it and the contact names, phone, tags and account name read are converted from it to UTF-8. Empty leaves the server default.","type":"string","example":"utf8"}},"type":"object"},"SplitCampaignMessageResponse":{"description":"The generated split campaign message. Each component that was requested (content, subject, preheader) carries the generated value; every other field carries the original message's value.","required":["messageId","subject","replyToEmail","fromName","fromEmail","preHeader","markupHtml","markupCss","messageHtml"],"properties":{"messageId":{"description":"Id of the original message the request was started from.","type":"integer","example":9134},"subject":{"description":"Subject line: the generated one when subject was requested, else the original message's.","type":"string","example":"Last chance: the autumn sale ends Friday"},"replyToEmail":{"description":"Reply-to address of the original message.","type":"string","example":"hello@acme.com"},"fromName":{"description":"From name of the original message.","type":"string","example":"Acme"},"fromEmail":{"description":"From address of the original message.","type":"string","example":"news@acme.com"},"preHeader":{"description":"Preheader text: the generated one when preheader was requested, else the original message's.","type":"string","example":"Three days left to save 30%"},"markupHtml":{"description":"Editor markup of the message: the generated markup when content was requested, else the original's stored markup.","type":"string","example":"<html><body><p>Our autumn sale ends Friday.</p></body></html>"},"markupCss":{"description":"Stylesheet of the original message's stored markup; it is not regenerated.","type":"string","example":".body { font-family: Arial; }"},"messageHtml":{"description":"The message HTML compiled from markupHtml and markupCss, ready to display.","type":"string","example":"<html><head><style>.body { font-family: Arial; }</style></head><body><p>Our autumn sale ends Friday.</p></body></html>"}},"type":"object"},"SplitCampaignRequestIdResponse":{"description":"Acknowledgement of one step of a split campaign message generation: the id the request is tracked under.","required":["requestId"],"properties":{"requestId":{"description":"External identifier of the split message request record, a UUID. Poll GET /ai/campaigns/split/{requestId} with it.","type":"string","example":"7c9e6679-7425-40de-944b-e07fc1f90ae7"}},"type":"object"},"SplitSeriesCampaignSaveRequest":{"description":"The variations (tabs) of an automation split campaign to save, and the messages to remove.","required":["tabs","deletedTabs"],"properties":{"tabs":{"description":"Every variation to keep, in order, at most 5. The first must carry the messageId of an existing message.","type":"array","items":{"required":["subject","replyToEmail","fromName","fromEmail","preHeader","percentage"],"properties":{"messageId":{"description":"ID of the variation's message. Leave out for a new variation: a message is copied from the first tab's message.","type":"integer","example":7},"subject":{"description":"Subject of the variation.","type":"string","example":"Spring sale"},"replyToEmail":{"description":"Reply-to address of the variation.","type":"string","example":"help@example.com"},"fromName":{"description":"From name of the variation.","type":"string","example":"Example Store"},"fromEmail":{"description":"From address of the variation.","type":"string","example":"news@example.com"},"preHeader":{"description":"Preheader text of the variation.","type":"string","example":"Up to 30% off"},"percentage":{"description":"Share of the split audience the variation is sent to, as a percentage.","type":"integer","example":50},"markupHtml":{"description":"Editor source HTML to save on the variation's message. Saved only together with markupCss.","type":["string","null"]},"markupCss":{"description":"Editor source CSS to save on the variation's message. Saved only together with markupHtml.","type":["string","null"]}},"type":"object"}},"deletedTabs":{"description":"IDs of the variation messages to remove from the campaign. May be empty; may not include the first tab's message.","type":"array","items":{"type":"integer"},"example":[9]}},"type":"object"},"StartRunResponse":{"properties":{"request_id":{"title":"Request Id","type":"string"}},"required":["request_id"],"title":"StartRunResponse","type":"object"},"StatsActivityItem":{"type":"object","additionalProperties":true,"description":"One recent contact activity. Columns beyond those listed depend on the activity type.","properties":{"id":{"type":["integer","string"]},"email":{"type":"string"},"hash":{"type":"string"},"gravatar":{"type":["integer","string"]},"emailhash":{"type":"string"},"screenshot":{"type":"string","description":"Avatar URL."},"tstamp":{"type":"string"},"tstamp_iso":{"type":"string","format":"date-time","description":"`tstamp` as ISO-8601; present when `tstamp` is set."},"type":{"type":["integer","string"],"description":"Numeric activity type."},"typestr":{"type":"string","description":"Activity type name (not set on automation entries)."}}},"StepConditionalCondition":{"type":"object","properties":{"field":{"type":"string","maxLength":255},"comparison":{"$ref":"#/components/schemas/ComparisonEnum"},"value":{"type":"string","maxLength":255},"id":{"type":"integer","readOnly":true}},"required":["comparison","field","id","value"]},"StepConditionalMultilpePath":{"type":"object","properties":{"conditions":{"type":"array","items":{"$ref":"#/components/schemas/StepConditionalCondition"}}},"required":["conditions"]},"StockImagePhoto":{"description":"One stock photo, as the stock image provider describes it.","required":["id","url","src","alt","name","originalSrc","width","height","originalWidth","originalHeight"],"properties":{"id":{"description":"Provider ID of the photo.","type":"integer","example":3573351},"url":{"description":"Address of the photo's page on the provider.","type":"string","example":"https://www.pexels.com/photo/3573351/"},"src":{"description":"Address of a resized rendition suited to an email, served by the provider.","type":"string","example":"https://images.pexels.com/photos/3573351/pexels-photo-3573351.jpeg?w=800&h=600"},"alt":{"description":"Provider's alt text for the photo.","type":"string","example":"Brown wooden table near window"},"name":{"description":"Name the photo would be saved under.","type":"string","example":"brown-wooden-table-near-window"},"originalSrc":{"description":"Address of the original, full-size file.","type":"string","example":"https://images.pexels.com/photos/3573351/pexels-photo-3573351.jpeg"},"width":{"description":"Width of the rendition at src, in pixels; null when unknown.","type":["integer","null"],"example":800},"height":{"description":"Height of the rendition at src, in pixels; null when unknown.","type":["integer","null"],"example":600},"originalWidth":{"description":"Width of the original file, in pixels; null when unknown.","type":["integer","null"],"example":4000},"originalHeight":{"description":"Height of the original file, in pixels; null when unknown.","type":["integer","null"],"example":3000}},"type":"object"},"StockImageSearchRequest":{"description":"What the picture should show and how many to answer.","required":["prompt"],"properties":{"prompt":{"description":"What the picture should show; the model turns it into search terms, in the brand kit's voice when one is given.","type":"string","example":"Spring sale on garden tools"},"brandkitUuid":{"description":"UUID of a brand kit to colour the search terms with; must be a stored brand kit.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"page":{"description":"Result page at the provider.","type":"integer","example":1},"perPage":{"description":"Photos to answer, 1 to 10.","type":"integer","example":10},"orientation":{"description":"Restrict to one orientation.","type":["string","null"],"enum":["portrait","landscape","square"],"example":"landscape"}},"type":"object"},"StockImageSearchResponse":{"description":"Stock photos matching the search terms the model derived from the prompt.","required":["photos","total"],"properties":{"photos":{"description":"At most perPage photos, after the provider's blocklist and deny terms were applied.","type":"array","items":{"$ref":"#/components/schemas/StockImagePhoto"}},"total":{"description":"Number of entries in photos (not the provider's total).","type":"integer","example":10}},"type":"object"},"StoreConversationRequest":{"description":"A summary of a file uploaded in an AI conversation.","required":["original_file_name","stored_file_path","conversation_id","summary"],"properties":{"original_file_name":{"description":"The name of the file as the user knows it. At most 2500 characters.","type":"string","example":"brand-guidelines.pdf"},"stored_file_path":{"description":"Where the file itself is stored. At most 2500 characters.","type":"string","example":"s3://example-bucket/ac-agents/uploads/account_id=12345/user_id=7/conversation_id=c8d1e5f2/3a9f1b"},"conversation_id":{"description":"Id of the conversation the file was uploaded in. At most 2500 characters.","type":"string","example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"},"summary":{"description":"The summary of the file's content.","type":"string","example":"A six-page guide to the company brand."},"mime_type":{"description":"The MIME type of the file. At most 250 characters. An empty string counts as none.","type":"string","example":"application/pdf"},"description":{"description":"A short description of the file. An empty string counts as none.","type":"string","example":"Our brand colours, fonts and tone of voice."}},"type":"object"},"StoreResourceFromConversationRequest":{"description":"A file uploaded in an AI conversation to save as a resource.","required":["conversation_id","file_id"],"properties":{"conversation_id":{"description":"Id of the conversation the file was uploaded in. At most 2500 characters, using only letters, digits, hyphens, underscores and dots.","type":"string","example":"c8d1e5f2-6a7b-4c3d-9e0f-1a2b3c4d5e6f"},"file_id":{"description":"Id of the upload within the conversation. At most 2500 characters, using the same characters as conversation_id.","type":"string","example":"3a9f1b"},"original_file_name":{"description":"The name to give the resource. At most 2500 characters. Required unless the upload was already summarised in the conversation or already saved as a resource; in those cases the existing name is kept and this is ignored.","type":"string","example":"brand-guidelines.pdf"}},"type":"object"},"SubscriberConversionTriggerMessage":{"type":"object","properties":{"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"conversion_id":{"type":"integer"},"conversion_value":{"oneOf":[{"type":"integer"},{"type":"string"}],"description":"Conversion::queueTrigger() passes conversion value through as-is -- ConversionTest::testQueueTrigger() sends a PHP int (1000000000) and json_encode()s it as a bare number, not a quoted string."},"currency_override":{"type":"string","nullable":true},"url":{"type":"string"},"event":{"type":"string"},"tstamp":{"type":"string","description":"Server timestamp in Y-m-d H:i:s format, e.g. '2026-10-05 16:43:06' -- not RFC 3339 date-time. Grounded against SubscriberConversionSQSMessage's Carbon::format('Y-m-d H:i:s')."},"conversionTriggerOriginator":{"type":"object","properties":{"modelName":{"type":"string","nullable":true},"id":{"type":"integer","nullable":true}},"additionalProperties":false}},"description":"At least one of email or phone is required, and exactly one of conversion_id, url, or event. Shape not fully confirmed for every field -- grounded against SubscriberConversionSQSMessage::fromArray().","additionalProperties":false},"SubscriberSeriesEnd":{"description":"How a run ended.","type":"object","properties":{"subscriber_series_id":{"description":"Id of the run that ended.","type":"string","example":"2"},"cause":{"description":"What ended the run, as a code such as api_cancel_automation (ended by hand, for example through PUT /contactAutomations/{id} with completed true), series_completed or series_block_process_end.","type":"string","example":"api_cancel_automation"},"context":{"description":"Extra detail about the end, as a JSON-encoded string. \"null\" when there is none.","type":["string","null"],"example":"null"},"created_timestamp":{"description":"When the end was recorded, as YYYY-MM-DD HH:MM:SS.","type":"string","example":"2018-09-19 10:02:11"},"id":{"description":"Id of the end record.","type":"string","example":"7"},"subscriberSeries":{"description":"Id of the run. The same value as subscriber_series_id.","type":"string","example":"2"},"links":{"description":"URL of the run.","type":"object","properties":{"subscriberSeries":{"type":"string","description":"URL of the run."}}}}},"SwapTemplateDispatchRequest":{"description":"Queue payload for swapping the email onto a new layout. CampaignEditsService::dispatchTemplateSwap builds it from PUT /ai/campaigns/edit/{requestId}/swap-template; the server resolves the stored request, campaign, message and markup from request_id.","required":["request_id","html","css"],"properties":{"request_id":{"description":"UUID of the edit request. Must name a stored edit request that is past pending and not in error.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"record":{"description":"The stored edit request. Resolved by the server from request_id; not part of the payload.","type":"object","readOnly":true},"emailEditRequest":{"description":"The edit request decoded from the stored record. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"html":{"description":"HTML of the new layout, as read from the chosen template or message.","type":"string","example":"<html><body><table class=\"esd-block-text\">...</table></body></html>"},"css":{"description":"CSS of the new layout, saved on the message markup with the swapped HTML.","type":"string","example":".esd-block-text { font-family: Arial; }"},"campaign":{"description":"The campaign under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"message":{"description":"The message under edit. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true},"messageMarkup":{"description":"The editor markup of the message. Resolved by the server from the stored request; not part of the payload.","type":"object","readOnly":true}},"type":"object"},"SwapTemplateRequest":{"description":"Where the new layout comes from. Exactly one of messageId, templateId, stockTemplateId or purchasedTemplateId must be set; none or more than one is refused with 422. The server reads the html and css of the chosen source.","properties":{"messageId":{"description":"Id of another campaign message of the account to take the layout from. Its message must be built in the current editor (ed_version 3).","type":["integer","null"],"example":9134},"templateId":{"description":"Id of a saved template of the account to take the layout from. Must be a current editor template (ed_version 3).","type":["integer","null"],"example":57},"stockTemplateId":{"description":"Name hash of a stock template to take the layout from, 40 characters.","type":["string","null"],"example":"2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a"},"purchasedTemplateId":{"description":"Name hash of a template the account purchased from the marketplace, to take the layout from.","type":["string","null"],"example":"9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f"},"html":{"description":"HTML of the chosen source. Filled by the server from the id given; a value sent here is replaced.","type":["string","null"],"readOnly":true},"css":{"description":"CSS of the chosen source. Filled by the server from the id given; a value sent here is replaced.","type":["string","null"],"readOnly":true}},"type":"object"},"SyncApiError":{"description":"One error in a SyncApiErrorResponse.","required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the error: the HTTP status text, such as `Forbidden`, or `Invalid attribute` for a field that failed validation.","type":"string","example":"Invalid attribute"},"detail":{"description":"What went wrong. Left out when there is nothing to add to `title`.","type":"string","example":"name can not be blank"},"source":{"description":"The request field the error is about. Present on validation errors only.","properties":{"pointer":{"description":"`/data/attributes/` followed by the field name.","type":"string","example":"/data/attributes/name"}},"type":"object"}},"type":"object"},"SyncApiErrorResponse":{"description":"Error body of a request the Database Sync endpoints refuse for permission (403) or because the request body failed validation (422).","required":["errors"],"properties":{"errors":{"description":"One error, or one per field that failed validation.","type":"array","items":{"$ref":"#/components/schemas/SyncApiError"}}},"type":"object"},"SyncConnectionTestResult":{"description":"Whether the source database could be reached, and the tables a sync can read from it.","properties":{"connected":{"description":"True when the connection opened, the database was selected and at least one table was found.","type":"boolean","example":true},"message":{"description":"What happened, in the user's language: that the connection succeeded, or why it failed (the server could not be reached as that user, the database could not be selected, `localhost` was given, or no tables were found).","type":"string","example":"Connection successful"},"tables":{"description":"Names of the tables in the database, as the server lists them. Empty when `connected` is false.","type":"array","items":{"type":"string"},"example":["customers","orders"]}},"type":"object"},"SyncContactField":{"description":"A contact field a sync can map a source column to.","properties":{"id":{"description":"The key that maps a source column to this field in the sync `fields`. `customer_acct_name` (account name) and `job_title` are listed only when the account has the Accounts feature.","type":"string","enum":["email","first_name","last_name","phone","tags","sdate","ip","ua","customer_acct_name","job_title"],"example":"email"},"name":{"description":"Label of the field, in the user's language.","type":"string","example":"Email Address"},"required":{"description":"True when every sync must map this field. Only `email` can be, and it is not when the account may store contacts without an email address.","type":"boolean","example":true}},"type":"object"},"SyncCustomField":{"description":"A contact custom field a sync can map a source column to.","properties":{"id":{"description":"ID of the custom field. A sync maps a column to it in `fields` under the key `_f<id>`.","type":"string","example":"12"},"title":{"description":"Title of the custom field.","type":"string","example":"Company"}},"type":"object"},"SyncFieldDiscoveryResult":{"description":"The columns of a source table or custom query that a sync can map to contact fields.","properties":{"succeeded":{"description":"True when the columns could be read.","type":"boolean","example":true},"message":{"description":"How many columns were found, in the user's language, or why they could not be read: the connection failed, the table is not in the database, the query is not a SELECT or returned no rows, the user lacks the SELECT privilege, or the error the server gave.","type":"string","example":"Found 3 columns"},"fields":{"description":"The columns, in source order, followed by any expressions derived from them. Empty when `succeeded` is false.","type":"array","items":{"$ref":"#/components/schemas/SyncSourceField"}},"rules":{"description":"The `rules` stored on the sync named by `syncId`, echoed back for the wizard. Empty without a `syncId`, for a sync that reads a custom query, or when `succeeded` is false.","type":"array","items":{"type":"string"},"example":["status = 1"]},"isCustomQuery":{"description":"True when the columns were read from `query`, false when from `table`.","type":"boolean","example":false}},"type":"object"},"SyncHttpError":{"description":"One error in a SyncHttpErrorResponse.","required":["status","detail"],"properties":{"status":{"description":"HTTP status code, the same as the response status, as a string.","type":"string","example":"404"},"detail":{"description":"What went wrong.","type":"string","example":"Sync job not found [id=7]"}},"type":"object"},"SyncHttpErrorResponse":{"description":"Error body of a request the Database Sync endpoints refuse with a 400, 404 or 422 of their own.","required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"$ref":"#/components/schemas/SyncHttpError"}}},"type":"object"},"SyncJob":{"description":"A database sync: a saved job that reads rows from a customer owned MySQL database and imports them as contacts of one list. The source password is never returned.","properties":{"id":{"description":"ID of the sync.","type":"string","example":"7"},"name":{"description":"Name of the sync.","type":"string","example":"Nightly CRM import"},"listId":{"description":"ID of the list the sync writes contacts to.","type":"string","example":"3"},"destination":{"description":"Status the sync gives the contacts on the list; `1` is active, `3` the exclusion list.","type":"string","example":"1"},"host":{"description":"Host of the source MySQL server.","type":"string","example":"db.example.com"},"database":{"description":"Name of the source database.","type":"string","example":"crm"},"username":{"description":"Database user the sync connects as.","type":"string","example":"reader"},"hasPassword":{"description":"True when a non-empty source password is stored. The password itself is never returned.","type":"boolean","example":true},"type":{"description":"Database type, always `mysql`.","type":"string","example":"mysql"},"charset":{"description":"Character set of the source data; empty for the server default.","type":"string","example":"utf8"},"table":{"description":"Source table; empty when the sync reads a custom query.","type":"string","example":"customers"},"query":{"description":"Custom SELECT query the sync reads; empty when it reads a table.","type":"string","example":""},"rules":{"description":"SQL conditions a table sync selects rows by. Empty for a sync that reads a custom query.","type":"array","items":{"type":"string"},"example":["status = 1"]},"fields":{"description":"Contact field => source column the sync maps, keyed as on save (`_f<id>` for a custom field).","type":"object","example":{"email":"email_address","first_name":"fname"},"additionalProperties":{"type":"string"}},"deleteAll":{"description":"Whether each run removes from the list the contacts with the `destination` status that it did not sync.","type":"boolean","example":false},"updateExisting":{"description":"Whether runs update contacts that already exist.","type":"boolean","example":true},"sendLastMessage":{"description":"Whether runs send the list's last broadcast campaign to the contacts they subscribe.","type":"boolean","example":false},"sendResponder":{"description":"Whether runs enter the contacts they subscribe into the list's autoresponders.","type":"boolean","example":false},"instantResponder":{"description":"The stored instant autoresponder option.","type":"boolean","example":false},"optIn":{"description":"The stored opt-in option.","type":"boolean","example":false},"sentResponders":{"description":"IDs of the autoresponder campaigns earlier runs already sent. An edit sends them back so they are not sent again.","type":"array","items":{"type":"integer"},"example":[3,5]},"lastRun":{"description":"When the sync last ran, `Y-m-d H:i:s`; null if it never has.","type":["string","null"],"example":"2026-10-01 04:00:00"}},"type":"object"},"SyncOption":{"description":"An option the Database Sync wizard may offer, and whether to offer it set.","properties":{"id":{"description":"The field of the sync payload the option sets.","type":"string","enum":["updateExisting","sendLastMessage"],"example":"updateExisting"},"checked":{"description":"Whether the wizard offers the option already set: true for `updateExisting`, false for `sendLastMessage`.","type":"boolean","example":true},"available":{"description":"Whether the account can be offered the option. `sendLastMessage` is available once the account has sent a campaign; `updateExisting` always is.","type":"boolean","example":true}},"type":"object"},"SyncRunProgress":{"description":"How far a run of a sync has got.","properties":{"processId":{"description":"ID of the run.","type":"integer","example":812},"total":{"description":"Number of source rows the run processes.","type":"integer","example":1500},"completed":{"description":"Number of rows processed so far.","type":"integer","example":600},"percentage":{"description":"Share of the rows processed, from 0 to 100.","type":"number","format":"float","example":40},"finished":{"description":"True once `percentage` reaches 100. A run that stops updating is marked 100 when the sync is next started, 20 minutes after its last update at the earliest.","type":"boolean","example":false}},"type":"object"},"SyncRunReport":{"description":"The rows a run of a sync could not import, grouped by why.","properties":{"processId":{"description":"ID of the run.","type":"integer","example":812},"rows":{"description":"The rows that were not imported, by group: `bounced` (code 4), `duplicated` (code 8), `unsubscribed` (code 16), `excluded` (code 30), and `failed` for any other code. Only groups with rows appear. When no row failed the value is an empty JSON array, `[]`, not an object.","oneOf":[{"type":"object","additionalProperties":{"type":"array","items":{"properties":{"email":{"description":"Email address of the row.","type":"string","example":"jane@example.com"},"code":{"description":"Result code of the row, which decides its group.","type":"integer","example":4},"message":{"description":"Why the row was not imported, in the language of the user who ran the sync.","type":"string","example":"This contact has been removed in the past due to numerous bounces."},"tstamp":{"description":"When the row was processed, `Y-m-d H:i:s`.","type":["string","null"],"example":"2026-10-01 04:00:12"}},"type":"object"}}},{"type":"array","items":{},"maxItems":0}]},"counts":{"description":"Number of rows in each group of `rows`, under the same keys. An empty JSON array, `[]`, when no row failed.","oneOf":[{"type":"object","example":{"bounced":1,"failed":1},"additionalProperties":{"type":"integer"}},{"type":"array","items":{},"maxItems":0}]},"total":{"description":"Number of rows the run could not import, the sum of `counts`. It is not the number of rows the run processed.","type":"integer","example":2}},"type":"object"},"SyncRunResult":{"description":"Whether a run of a sync was started, and which run to follow.","properties":{"started":{"description":"True when a run was started, a run of the sync was already going (`alreadyRunning`), or the source had no rows to sync. False when the run could not start.","type":"boolean","example":true},"message":{"description":"What happened, in the user's language: the run was started, one was already in progress, no rows were fetched, or why it could not start (the connection failed, a test run found the table gone, or the rows could not be counted).","type":"string","example":"Synchronization process initiated"},"processId":{"description":"ID of the run to follow with GET /syncs/processes/{processId}: the new run, or the one already going. `0` when no run was created.","type":"integer","example":812},"total":{"description":"Number of source rows the run processes. `0` when no run was created.","type":"integer","example":1500},"alreadyRunning":{"description":"True when an unfinished run of this sync was updated in the last 20 minutes. Nothing new was started and `processId` is that run. An unfinished run idle for longer is marked finished and a new run starts.","type":"boolean","example":false}},"type":"object"},"SyncSourceField":{"description":"A source column, or an SQL expression over columns, that a sync can map to a contact field.","properties":{"name":{"description":"What to put in the sync `fields` to read this value: the column name, or an expression. A custom-query column whose first value is a 10-digit number is also offered as `FROM_UNIXTIME(<column>)`, and a date column and a time column together as `CONCAT(<date>, ' ', <time>)`.","type":"string","example":"email_address"},"type":{"description":"The column type the server reports for a table column, for example `varchar(255)`. A custom-query column is `string`. A `FROM_UNIXTIME` expression carries a translated \"unix timestamp\" label and a `CONCAT` expression `<date column> + <time column>`.","type":"string","example":"varchar(255)"}},"type":"object"},"TemplateAnalysisCompletedResponse":{"description":"The analysis finished: the semantic HTML the model produced is ready.","required":["status","analyzedHtml","failedImages","completedAt"],"properties":{"status":{"description":"Always completed.","type":"string","enum":["completed"],"example":"completed"},"analyzedHtml":{"description":"The HTML the model produced from the submitted template: semantic markup with a loose Stripo-like structure, padding normalized, and image URLs rewritten to the account's CDN where the download succeeded. null for a record written without it.","type":["string","null"],"example":"<table class=\"es-content\">...</table>"},"failedImages":{"description":"Image URLs from the template that could not be downloaded and re-hosted; they are left as they were in analyzedHtml.","type":"array","items":{"type":"string"},"example":["https://cdn.example.com/hero.png"]},"completedAt":{"description":"When the analysis finished, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:11:40"}},"type":"object"},"TemplateAnalysisProcessRequest":{"description":"The job POST /ai/template/analysis/create queues: which stored analysis request to run.","required":["requestId","rawHtml","templateName"],"properties":{"requestId":{"description":"ID of the request record the create call stored; must name a stored request of this import kind.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"rawHtml":{"description":"The HTML as sent to the create call. Carried in the job for tracing; the worker reads the copy stored on the request record.","type":"string","example":"<html><body><table width=\"600\">...</table></body></html>"},"templateName":{"description":"The template name as sent to the create call. Carried in the job; the worker reads the stored copy.","type":"string","example":"Spring newsletter"}},"type":"object"},"TemplateCreateWorkerRequest":{"description":"The job POST /ai/templates/generate queues, one per selected base template. Sent only by Hosted's own background dispatcher.","required":["template_request_uuid","prompt","lang"],"properties":{"template_request_uuid":{"description":"UUID of the per-template request record created by the generate call; must exist.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"prompt":{"description":"What the template should be for.","type":"string","example":"A spring sale on garden tools for returning customers"},"lang":{"description":"Language to write the content in.","type":"string","example":"en"},"tone":{"description":"Voice to write in.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"brandkit_uuid":{"description":"UUID of the brand kit to apply; must be a stored brand kit.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}},"type":"object"},"TemplateDesignerWriteResponse":{"type":"object","description":"What the version 3 template create and update answer with: only `meta`.","required":["meta"],"properties":{"meta":{"type":"object","description":"The template that was written.","required":["code","id","url"],"properties":{"code":{"type":"integer","enum":[200,201],"description":"201 after a create, 200 after an update. Informational only: the HTTP status is 200 either way.","example":201},"id":{"type":"integer","description":"ID of the template.","example":12},"url":{"type":"string","description":"Link to the template in the app.","example":"https://youraccountname.activehosted.com/campaign/template/?tid=12"}}}}},"TemplateFromCampaignRequest":{"description":"Options for saving a campaign into the template library. Every field is optional.","properties":{"name":{"description":"Name for the new template, at most 500 characters. Omitted or empty, the source campaign's name is kept.","type":["string","null"],"example":"October newsletter"}},"type":"object"},"TemplateFromCampaignResponse":{"description":"The template the campaign was saved as.","required":["template"],"properties":{"template":{"$ref":"#/components/schemas/TemplateFromCampaignTemplate","description":"The new em_template row."}},"type":"object"},"TemplateFromCampaignTemplate":{"description":"The template created from the campaign.","required":["id","name","url"],"properties":{"id":{"description":"Id of the new template.","type":"integer","example":777},"name":{"description":"Name of the template: the name in the request when one was given, else the source campaign's name.","type":"string","example":"October newsletter"},"url":{"description":"Absolute URL, on the account's own domain, that opens the template in the designer.","type":"string","example":"https://acct.activehosted.com/campaign/template/?tid=777"}},"type":"object"},"TemplateGenerateRequest":{"description":"What the templates are for and how many to make.","required":["prompt"],"properties":{"prompt":{"description":"What the email templates should be for, in plain words; the model picks the base templates that fit.","type":"string","example":"A spring sale on garden tools for returning customers"},"num":{"description":"How many base templates to generate, 1 to the number available (16).","type":"integer","example":3},"brandkitUuid":{"description":"UUID of a brand kit whose colours and voice to apply; must be a stored brand kit.","type":["string","null"],"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"},"tone":{"description":"Voice to write in, one of the template content tones.","type":["string","null"],"enum":["encouraging","persuasive","thoughtful","personal","witty","funny","empathetic","informative","professional","friendly","casual","enthusiastic","bold"],"example":"friendly"},"lang":{"description":"Language to write the content in, as a supported output language code. Omitted, the user's language.","type":["string","null"],"example":"en"}},"type":"object"},"TemplateGenerationResultResponse":{"description":"The templates a finished generation request produced.","required":["templates"],"properties":{"templates":{"description":"Keyed by base template name (welcome, promote, ...), one pair per template the request selected.","type":"object","additionalProperties":{"$ref":"#/components/schemas/GeneratedTemplatePair"}}},"type":"object"},"TemplateGenerationStartedResponse":{"description":"A template generation request exists and its jobs are queued.","required":["requestId"],"properties":{"requestId":{"description":"From POST /ai/templates/generate: the request to poll with GET /ai/templates/{requestId}. From the create worker: the template request the job filled.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"TemplateImportCompletedResponse":{"description":"The import finished and the template is saved.","required":["status","result","completedAt"],"properties":{"status":{"description":"Always completed.","type":"string","enum":["completed"],"example":"completed"},"result":{"oneOf":[{"$ref":"#/components/schemas/TemplateImportResult","description":"The imported template; null for a record written without it."},{"type":"null"}],"description":"The imported template; null for a record written without it."},"completedAt":{"description":"When the import finished, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:11:40"}},"type":"object"},"TemplateImportCreateRequest":{"description":"The email HTML to import and what to call the template.","required":["rawHtml","templateName"],"properties":{"rawHtml":{"description":"The email's HTML as exported from the other tool, 10 to 1,000,000 characters, external image URLs included.","type":"string","example":"<html><body><table width=\"600\">...</table></body></html>"},"templateName":{"description":"Name for the template the import saves, at most 200 characters.","type":"string","example":"Spring newsletter"},"hidden":{"description":"True to save the template hidden from the template list. Honoured by the deterministic import only; the analysis and LLM import ignore it.","type":"boolean","example":false}},"type":"object"},"TemplateImportErrorResponse":{"description":"Error body with a single message. The message never carries the underlying failure: that is logged, not answered.","required":["error"],"properties":{"error":{"description":"What went wrong, as a fixed sentence; each operation lists the ones it answers.","type":"string","example":"Processing failed."}},"type":"object"},"TemplateImportFailedResponse":{"description":"The job failed. The status code says how: 504 when the model timed out, 413 when the content was too large for it, 500 otherwise.","required":["status","error","errorCode","completedAt"],"properties":{"status":{"description":"Always failed.","type":"string","enum":["failed"],"example":"failed"},"error":{"description":"Always this fixed sentence; the underlying error is logged, never answered.","type":"string","enum":["Processing failed."],"example":"Processing failed."},"errorCode":{"description":"Why the model call failed, when that is known: timeout (the call exceeded its time limit, answered 504) or content_too_large (the model's output was truncated, answered 413). null for any other failure, answered 500.","type":["string","null"],"enum":["timeout","content_too_large",null],"example":"timeout"},"completedAt":{"description":"When the job failed, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:11:40"}},"type":"object"},"TemplateImportInProgressResponse":{"description":"The request exists but its job has not finished; poll again.","required":["status","message","createdAt"],"properties":{"status":{"description":"pending: the job is queued and has not started. processing: a worker has picked it up.","type":"string","enum":["pending","processing"],"example":"processing"},"message":{"description":"Always this fixed sentence.","type":"string","enum":["Request is still being processed"],"example":"Request is still being processed"},"createdAt":{"description":"When the request was created, Y-m-d H:i:s; null for a record written without it.","type":["string","null"],"example":"2026-10-23 14:02:11"}},"type":"object"},"TemplateImportProcessRequest":{"description":"The job POST /ai/template/import/create queues: which stored import request to run.","required":["requestId","rawHtml","templateName"],"properties":{"requestId":{"description":"ID of the request record the create call stored; must name a stored request of this import kind.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"rawHtml":{"description":"The HTML as sent to the create call. Carried in the job for tracing; the worker reads the copy stored on the request record.","type":"string","example":"<html><body><table width=\"600\">...</table></body></html>"},"templateName":{"description":"The template name as sent to the create call. Carried in the job; the worker reads the stored copy.","type":"string","example":"Spring newsletter"}},"type":"object"},"TemplateImportProcessedResponse":{"description":"The job ran to completion and the request record now holds the result.","required":["status","requestId"],"properties":{"status":{"description":"Always completed. A failed job does not answer this body: it is a 500.","type":"string","enum":["completed"],"example":"completed"},"requestId":{"description":"ID of the request that was processed.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}},"type":"object"},"TemplateImportRequestCreatedResponse":{"description":"The request record was stored and its processing job queued.","required":["requestId","status"],"properties":{"requestId":{"description":"ID of the request, a new UUID. Poll the matching status operation with it.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"status":{"description":"Always pending: the job has been queued but has not started.","type":"string","enum":["pending"],"example":"pending"}},"type":"object"},"TemplateImportResult":{"description":"The imported template.","required":["stripoCompatibleHtml","templateName","templateId"],"properties":{"stripoCompatibleHtml":{"description":"The Stripo-compatible HTML the model produced, which is also the html of the saved template's content.","type":"string","example":"<table class=\"es-content\">...</table>"},"templateName":{"description":"Name of the saved template, as sent when the request was created.","type":"string","example":"Spring newsletter"},"templateId":{"description":"ID of the template saved to the account (editor version 3, source ai_template_import); the one to open or to build a campaign from.","type":"integer","example":4821}},"type":"object"},"TemplateImportUnknownStatusResponse":{"description":"The stored record carries a status the action does not know, or none (reported as unknown).","required":["error","status"],"properties":{"error":{"description":"Always this fixed sentence.","type":"string","enum":["Unknown status encountered"],"example":"Unknown status encountered"},"status":{"description":"The status as stored, or unknown when the record has none.","type":"string","example":"unknown"}},"type":"object"},"TemplateItem":{"description":"An email template.","properties":{"id":{"description":"ID of the template.","type":"string","example":"12"},"userid":{"description":"ID of the user who owns the template.","type":"string","example":"1"},"ed_instanceid":{"description":"ID of the classic designer instance of the template, `0` when it has none.","type":"string","example":"0"},"ed_version":{"description":"Designer version of the template: `1` legacy, `2` classic designer, `3` version 3 designer (Stripo).","type":"string","example":"3"},"name":{"description":"Name of the template.","type":["string","null"],"example":"Welcome email"},"subject":{"description":"Default subject line of campaigns built from the template.","type":["string","null"],"example":"Welcome!"},"content":{"description":"Markup of the template. For a version 3 template it is a JSON string holding `html` and `css`.","type":["string","null"]},"categoryid":{"description":"ID of the template category.","type":"string","example":"1"},"used":{"description":"How many times the template has been used.","type":"string","example":"1"},"waitpreview":{"description":"`1` while the template waits for a new screenshot; cleared once the screenshot is taken.","type":"string","example":"0"},"importnum":{"description":"Import sequence number given to a template imported through the legacy import, otherwise `0`.","type":"string","example":"0"},"mdate":{"description":"When the template was last modified, as an ISO 8601 date-time.","type":["string","null"],"format":"date-time","example":"2026-08-23T10:04:11-05:00"},"preview_content":{"description":"Ready-to-send HTML of the template, with the styles inlined. Null until it has been compiled.","type":["string","null"]},"modified":{"description":"Legacy flag the app sets to `1` when it creates, copies or imports a template.","type":"string","example":"1"},"hidden":{"description":"Whether the template is hidden from the template library. A string from the database, or the number 0 or 1 when the request just set it.","type":["string","integer"],"example":"0"},"source":{"description":"Where the template came from: `0` created by a user or unknown, `1` AI generated.","type":"string","example":"0"},"read_only":{"description":"Read-only flag of the template. Updating the template does not check it.","type":"string","example":"0"},"additional_data":{"description":"Free-form JSON metadata used to generate or update the template, or null when there is none.","type":["object","null"]},"screenshot":{"description":"URL of the screenshot of the template.","type":"string","example":"https://youraccountname.api-us1.com/tplimages/template-12.png"},"links":{"$ref":"#/components/schemas/TemplateItemLinks","description":"API URLs of the related records of the template."}},"type":"object"},"TemplateItemLinks":{"description":"API URLs of the related records of a template.","required":["templateLists","templateTags"],"properties":{"templateLists":{"description":"URL of the lists the template is available to.","type":"string","example":"https://youraccountname.api-us1.com/api/3/templates/12/templateLists"},"templateTags":{"description":"URL of the tags of the template.","type":"string","example":"https://youraccountname.api-us1.com/api/3/templates/12/templateTags"}},"type":"object"},"TemplateItemResponse":{"description":"A template, wrapped in `template`.","required":["template"],"properties":{"template":{"$ref":"#/components/schemas/TemplateItem","description":"The template as it is stored after the write."}},"type":"object"},"TemplateListResponse":{"description":"Campaign templates matching a search, or the most recently modified ones.","properties":{"data":{"$ref":"#/components/schemas/TemplateSearchData"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The trace this call's work is recorded under. Quote it when reporting a problem with this call.","title":"Trace Id"}},"required":["data"],"title":"Campaign Template List Result","type":"object"},"TemplatePatchFields":{"description":"The fields of a template update. Every other key is ignored, including `content`, `subject`, `categoryid` and `userid`.","properties":{"name":{"description":"New name of the template. Anything other than a string is refused with 400 before anything changes. An empty string leaves the name as it is. Applied after a reseed, so it wins over the name the source brings.","type":"string","example":"Welcome email (revised)"},"hidden":{"description":"Whether the template is hidden from the template library. `true`, `1`, `\"true\"`, `\"on\"` and `\"yes\"` hide it (stored as 1); any other value shows it (stored as 0).","type":["boolean","integer","string"],"example":false},"basecampaignid":{"description":"Reseed the template's name, subject and content from the message of this campaign. The caller must be able to read the campaign. Wins over `basetemplateid` when both are sent.","type":"integer","example":34},"basetemplateid":{"description":"Reseed the template's content from another template. A numeric value is the ID of one of the account's templates, which the caller must be able to modify; any other value is the hash of a stock template from `GET /templates/stock`. The design of the source is carried over with the markup.","type":["string","integer"],"example":"18"}},"type":"object"},"TemplatePatchRequest":{"description":"The changes to make to a template, wrapped in `template`.","required":["template"],"properties":{"template":{"$ref":"#/components/schemas/TemplatePatchFields","description":"The changes. Leaving it out is answered with 500."}},"type":"object"},"TemplateSearchData":{"description":"Template-search results and their total count.","properties":{"total_count":{"description":"Total matching templates.","title":"Total Count","type":"integer"},"results":{"additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"description":"Template id string to template object. Each has at least `id` (int) and `name`; pass a result's `id` to generate_campaign as template_id.","title":"Results","type":"object"}},"required":["total_count","results"],"title":"Campaign Template Search Data","type":"object"},"TemplateSearchPage":{"description":"A page of template search results, with the search as the server applied it.","required":["search_query","total_count","limit","offset","modifiedAfter","modifiedBefore","results"],"properties":{"search_query":{"description":"The `q` that was searched, trimmed. Empty when no `q` was sent.","type":"string","example":"welcome"},"total_count":{"description":"Number of templates that match the search, across every page.","type":"integer","example":3},"limit":{"description":"The `limit` of the request.","type":"integer","example":10},"offset":{"description":"The `offset` of the request.","type":"integer","example":0},"modifiedAfter":{"description":"The `modifiedAfter` of the request as `Y-m-d`, or null when it was not sent.","type":["string","null"],"example":"2026-01-01"},"modifiedBefore":{"description":"The `modifiedBefore` of the request as `Y-m-d`, or null when it was not sent.","type":["string","null"],"example":null},"results":{"description":"The matching templates on this page. A name that equals the whole search comes first, then the most recently modified.","type":"array","items":{"$ref":"#/components/schemas/TemplateSearchResult"}}},"type":"object"},"TemplateSearchResponse":{"description":"One page of templates that match a search.","required":["success","data"],"properties":{"success":{"description":"Always true. A refused search answers with an error status instead.","type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TemplateSearchPage","description":"The page of results and the search that produced it."}},"type":"object"},"TemplateSearchResult":{"description":"A template that matched a search.","required":["asset_type","id","name","subject","content","template_type","match_location","category_id","usage_count","modified_date","editor_version","url"],"properties":{"asset_type":{"description":"Always `template`.","type":"string","enum":["template"],"example":"template"},"id":{"description":"ID of the template.","type":"integer","example":12},"name":{"description":"Name of the template.","type":["string","null"],"example":"Welcome email"},"subject":{"description":"Default subject line of the template.","type":["string","null"],"example":"Welcome!"},"content":{"description":"Always null: the search does not return markup. Read it from `GET /templates/{id}`.","type":"null"},"template_type":{"description":"`basic` for a template with no designer instance (`ed_instanceid` 0), otherwise `designed`.","type":"string","enum":["basic","designed"],"example":"basic"},"match_location":{"description":"Which fields matched a search term, comma-separated in the order `id`, `name`: `id`, `name` or `id, name`. `unknown` when no `q` was sent or no term matched either field.","type":"string","example":"name"},"category_id":{"description":"ID of the template category.","type":"integer","example":1},"usage_count":{"description":"How many times the template has been used. The counter goes up each time it is used.","type":"integer","example":1},"modified_date":{"description":"When the template was last modified, as stored (`Y-m-d H:i:s`).","type":["string","null"],"example":"2026-08-23 10:04:11"},"editor_version":{"description":"Designer version of the template: `1` legacy, `2` classic designer, `3` version 3 designer (Stripo).","type":"integer","example":3},"url":{"description":"Link to the template in the app.","type":"string","example":"https://youraccountname.activehosted.com/campaign/template/?tid=12"}},"type":"object"},"TemplateStockItem":{"description":"A stock template from the shared catalog every account can start a template from.","required":["id","name","screenshot","mdate","cdate","tags","ed_version"],"properties":{"id":{"description":"Hash that identifies the stock template in the catalog. It is what `basetemplateid` takes to copy the template, and the `hash` of `GET /templates/stock/{hash}/markup`.","type":"string"},"name":{"description":"Name of the stock template.","type":"string"},"screenshot":{"description":"Preview image of the stock template, as the catalog stores it.","type":"string"},"mdate":{"description":"When the catalog entry was last modified, as the catalog stores it (`Y-m-d H:i:s`).","type":"string"},"cdate":{"description":"When the catalog entry was created, as the catalog stores it (`Y-m-d H:i:s`).","type":"string"},"tags":{"description":"Tags of the stock template, including the marker tags that make it a version 3 designer template (`v3 template`, `v3 basic template`, `V3 layout template`).","type":"array","items":{"type":"string"}},"ed_version":{"description":"Designer version of the template: `3` when it carries one of the version 3 marker tags, otherwise `2`.","type":"integer","enum":[2,3],"example":3}},"type":"object"},"TemplateStockList":{"description":"One page of the stock template catalog. Empty when the account may not use stock templates: its reseller removed them, or it is the template-catalog account itself.","required":["templates","total"],"properties":{"templates":{"description":"The stock templates on this page, most recently modified first unless `orders` is sent.","type":"array","items":{"$ref":"#/components/schemas/TemplateStockItem"}},"total":{"description":"Number of stock templates that match the filters, across every page.","type":"integer","example":48}},"type":"object"},"TemplateStockMarkup":{"description":"The editable markup of a stock template, decoded from its catalog archive.","required":["html","css"],"properties":{"html":{"description":"HTML of the template as the version 3 designer (Stripo) edits it. Never empty.","type":"string"},"css":{"description":"CSS of the template as the version 3 designer (Stripo) edits it. May be empty.","type":"string"}},"type":"object"},"TemplateToCampaignJobResultResponse":{"description":"The outcome of a completed template-to-campaign job.","required":["status","requestId","changesSummary","hasChanges"],"properties":{"status":{"description":"Always success: a failed run is answered with an error status instead.","type":"string","enum":["success"],"example":"success"},"requestId":{"description":"Id of the job that ran, as sent in the request.","type":"string","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"changesSummary":{"description":"The model's summary of what it changed in the body, subject and preheader; null when it reported no changes.","type":["string","null"],"example":"Rewrote the hero copy for the spring sale and updated the subject line."},"hasChanges":{"description":"True when the body, subject or preheader differs from the template after the run.","type":"boolean","example":true}},"type":"object"},"TemplateToCampaignJobStartedResponse":{"description":"The campaign that was created and the background job that is rewriting its content.","required":["requestId","campaignId","status"],"properties":{"requestId":{"description":"Id of the background job, a UUID. Poll the job by it, or receive the result through the campaign edit completed event.","type":"string","example":"a1b2c3d4-e5f6-4789-abcd-ef0123456789"},"campaignId":{"description":"Id of the campaign that was created from the template. Its content is still the template's until the job completes.","type":"integer","example":4821},"status":{"description":"Always in_progress: the job was queued but has not run yet.","type":"string","enum":["in_progress"],"example":"in_progress"}},"type":"object"},"TimeWindowTypeEnum":{"enum":["IN_WORKING_HOURS","CUSTOM"],"type":"string","description":"* `IN_WORKING_HOURS` - In Working Hours\n* `CUSTOM` - Custom"},"TranslationChecklist":{"description":"Whether each thing a campaign needs before it can be translated is in place. true means the check passes.","required":["language_field","subject_line","design","segment_list","preferred_language_set","variations_exist","valid_source"],"properties":{"language_field":{"description":"The account has a field that holds contacts' preferred language.","type":"boolean","example":true},"subject_line":{"description":"The message has a subject line.","type":"boolean","example":true},"design":{"description":"The message has a design.","type":"boolean","example":true},"segment_list":{"description":"The campaign sends to at least one list or a segment.","type":"boolean","example":true},"preferred_language_set":{"description":"Recipients have a preferred language set.","type":"boolean","example":true},"variations_exist":{"description":"At least one recipient prefers a language the message can be translated into.","type":"boolean","example":true},"valid_source":{"description":"The language the message is written in could be determined.","type":"boolean","example":true}},"type":"object"},"TranslationGenerateRequest":{"description":"One language version of a campaign's message to translate. Sent only by Hosted's own background dispatcher, never by a client.","required":["campaignid","messageid","status_requestid","source_code","target_code"],"properties":{"campaignid":{"description":"Id of the campaign. It must exist.","type":"integer","example":42},"messageid":{"description":"Id of the message to translate from. It must exist and have a design.","type":"integer","example":4821},"status_requestid":{"description":"Id of the stored status record of this language version, the id the translation request holds for it. It must exist and still be in progress.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"source_code":{"description":"Code of the language the message is in.","type":"string","example":"en"},"target_code":{"description":"Code of the language to translate it into.","type":"string","example":"es"},"target_languages":{"description":"Codes of the languages still to translate into, when this job translates a message that is not in English to English first. A job for each is queued when this one finishes.","type":"array","items":{"type":"string"},"default":[],"example":["es","fr"]},"traceparent":{"description":"W3C trace context of the translation this job belongs to, so its work is traced under it.","type":["string","null"],"example":"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01"}},"type":"object"},"TranslationInitializeRequest":{"description":"The campaign to translate.","required":["campaignid"],"properties":{"campaignid":{"description":"Id of the campaign. It must exist and have lists or a segment, a message and a message design.","type":"integer","example":42}},"type":"object"},"TranslationLanguage":{"description":"A language content can be translated into.","required":["code","label","isAccount"],"properties":{"code":{"description":"Language code as the translation service names it, or preferred for the contact-preferred-language entry.","type":"string","example":"fr"},"label":{"description":"Display name.","type":"string","example":"French"},"isAccount":{"description":"True for the account's own language, which is listed first.","type":"boolean","example":false}},"type":"object"},"TranslationLanguagesResponse":{"description":"The languages available for translation.","required":["languages"],"properties":{"languages":{"description":"The account language first, then, when the account has a preferred-language contact field, the preferred entry, then the rest.","type":"array","items":{"$ref":"#/components/schemas/TranslationLanguage"}}},"type":"object"},"TranslationMessageResponse":{"description":"A one-line message saying what a background translation job did.","required":["message"],"properties":{"message":{"description":"Says what happened. The text is fixed for each outcome but is not a contract.","type":"string","example":"generated translation for es"}},"type":"object"},"TranslationRequestedResponse":{"description":"The translation that was started, used to poll for it.","required":["requestId"],"properties":{"requestId":{"description":"Id of the stored translation request for the campaign.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}},"type":"object"},"TranslationRetryRequest":{"description":"The language version to translate again.","required":["campaignid","targetLanguage"],"properties":{"campaignid":{"description":"Id of the campaign. It must have a translation request that did not fail as a whole.","type":"integer","example":42},"targetLanguage":{"description":"The code of the language to translate again. It cannot be en, and the campaign must have a language version for it that is not completed or in progress.","type":"string","example":"es"}},"type":"object"},"TranslationSegmentCountRequest":{"description":"The recipient count to work out for one language version. Sent only by Hosted's own background dispatcher, never by a client.","required":["campaignid","requestid"],"properties":{"requestid":{"description":"Id of the stored count record for the language version. It must exist.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"},"campaignid":{"description":"Id of the campaign. It must exist.","type":"integer","example":42}},"type":"object"},"TranslationStatusResponse":{"description":"Where a campaign's translation stands, and each language of it.","required":["status","variations"],"properties":{"status":{"description":"The state of the translation as a whole. It is reported as in_progress while recipient counts are still being worked out, even when every language has finished.","type":"string","enum":["in_progress","completed","failed"],"example":"in_progress"},"variations":{"description":"One entry per language: the languages being translated into, and the language the message was written in.","type":"array","items":{"$ref":"#/components/schemas/TranslationVariation"}}},"type":"object"},"TranslationVariation":{"description":"One language version of a campaign's message and where its translation stands.","required":["code","label","status","messageId","recipientCount"],"properties":{"code":{"description":"The translation service's code for the language.","type":"string","example":"es"},"label":{"description":"The name of the language.","type":"string","example":"Spanish"},"status":{"description":"Where this language stands. The language the message was written in is always completed.","type":"string","enum":["in_progress","completed","failed"],"example":"completed"},"messageId":{"description":"Id of the message holding this language version. Null until it exists.","type":["integer","null"],"example":4821},"recipientCount":{"description":"How many recipients receive this language version. Null while still being counted.","type":["integer","null"],"example":1250}},"type":"object"},"TriggerTypeEnum":{"enum":["INBOUND_ANY_MESSAGE","INBOUND_SPECIFIC_MESSAGE","OUTBOUND_CAMPAIGN_API","OUTBOUND_CAMPAIGN_CSV","OUTBOUND_CAMPAIGN_SEGMENT","OUTBOUND_ANY","META_C2WA","INTEGRATIONS_HUBSPOT","INTEGRATIONS_ZAPIER","FROM_FLOW","CSAT","OTHER"],"type":"string","description":"* `INBOUND_ANY_MESSAGE` - Inbound Any Message\n* `INBOUND_SPECIFIC_MESSAGE` - Inbound Specific Message\n* `OUTBOUND_CAMPAIGN_API` - Outbound Campaign Api\n* `OUTBOUND_CAMPAIGN_CSV` - Outbound Campaign Csv\n* `OUTBOUND_CAMPAIGN_SEGMENT` - Outbound Campaign Segment\n* `OUTBOUND_ANY` - Outbound Any\n* `META_C2WA` - Meta C2Wa\n* `INTEGRATIONS_HUBSPOT` - Integrations Hubspot\n* `INTEGRATIONS_ZAPIER` - Integrations Zapier\n* `FROM_FLOW` - From Flow\n* `CSAT` - Csat\n* `OTHER` - Other"},"UnderReviewStatusRequest":{"description":"The account standing to evaluate and how long an account stays under review after leaving it.","required":["window_days"],"properties":{"down4":{"description":"Account standing (down4 value) to evaluate. Omit it to use the requesting account's own. The value review marks the account as under review.","type":["string","null"],"example":"review"},"window_days":{"description":"Days after the account leaves review during which it is still reported as under review. Zero or greater.","type":["integer","null"],"example":7}},"type":"object"},"UnscheduleRequest":{"properties":{"campaign_id":{"description":"Id of the campaign.","examples":[42],"exclusiveMinimum":0,"title":"Campaign Id","type":"integer"}},"required":["campaign_id"],"title":"UnscheduleRequest","type":"object"},"UnsentTranslatedCampaign":{"description":"A translated campaign that has not been sent.","required":["campaignid","name","status","mdate","external_identifier"],"properties":{"campaignid":{"description":"Id of the campaign, as a string of digits: the database layer returns every value as a string.","type":"string","example":"42"},"name":{"description":"Name of the campaign.","type":"string","example":"Spring sale"},"status":{"description":"The campaign's status as a string: \"0\" for a draft, \"1\" for scheduled. Sent campaigns are not listed.","type":"string","enum":["0","1"],"example":"0"},"mdate":{"description":"When the campaign was last modified, as a database timestamp.","type":"string","example":"2026-10-20 14:30:00"},"external_identifier":{"description":"Id of the campaign's stored translation request.","type":"string","format":"uuid","example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}},"type":"object"},"UnsentTranslatedCampaignsResetRequest":{"description":"The unsent translated campaigns to reset.","required":["campaignids"],"properties":{"campaignids":{"description":"Ids of the campaigns, at least one. Every one must be a draft or scheduled campaign, and the list must include every unsent translated campaign the account has.","type":"array","items":{"type":"integer"},"minItems":1,"example":[42,43]}},"type":"object"},"UpdateAiSettingsRequest":{"description":"The AI settings to save for the calling user.","required":["convert_conversation_uploads_to_resources"],"properties":{"convert_conversation_uploads_to_resources":{"description":"Whether files the user uploads in an AI conversation are also saved as resources.","type":"boolean","example":true}},"type":"object"},"UpdateDispatchRequest":{"description":"Queue payload for running an update of a generated campaign. CampaignGenerationService::triggerUpdate builds it from the body of PUT /ai/campaign/generation/update/{requestId}, and the template-to-campaign, campaign-edits and content-remapping flows build it for their own records; the server resolves the stored request, brand kit, summarization and block configurations from the ids.","required":["request_id"],"properties":{"request_id":{"description":"UUID of the request to update. Must name a stored campaign generation, template-to-campaign, campaign edits or content-remapping record.","type":"string","format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"template":{"description":"Key of the layout to move the campaign onto. Counts as a change only when it differs from the one stored on the request.","type":["string","null"],"example":"promote"},"brandkit_uuid":{"description":"UUID of the brand kit to restyle with, or null. Counts as a change only when it differs from the one stored on the request.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarization_uuid":{"description":"UUID of the content summarization to draw on, or null. Counts as a change only when it differs from the one stored on the request.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"use_summarization_link":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"edit_prompt":{"description":"Free-text instruction for the model, or null when only the layout, brand kit, summarization, blocks or images change.","type":["string","null"],"example":"Make it shorter and more upbeat"},"content_change":{"description":"True to let the model rewrite the body content.","type":"boolean","example":true},"subject_change":{"description":"True to let the model rewrite the subject line.","type":"boolean","example":false},"preheader_change":{"description":"True to let the model rewrite the preheader.","type":"boolean","example":false},"name_change":{"description":"True to let the model rename the campaign.","type":"boolean","example":false},"requestRecord":{"description":"The stored request, from request_id. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"brandkitRecord":{"description":"The stored brand kit, from brandkit_uuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"summarizationRecord":{"description":"The stored summarization, from summarization_uuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"labelId":{"description":"Id of the campaign folder (label) to file the campaign under, or null to leave it.","type":["integer","null"],"example":3},"sessionid":{"description":"Caller's session id, carried through for tracing.","type":["string","null"],"example":"sess_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"callback_context":{"description":"Where to report completion when the update was started by an automation block, or null. Carried onto the CampaignEditCompletedEvent.","properties":{"blockid":{"description":"Id of the automation block.","type":"integer","example":42},"seriesid":{"description":"Id of the automation.","type":"integer","example":12},"requestid":{"description":"The block's own request id.","type":"string","example":"blk_01HZX3K9Q2M8N7P6R5T4V3W2Y1"}},"type":"object"},"blocks":{"description":"Blocks to place in the layout, each with its type and configuration, or null to leave the blocks alone. A non-null list counts as a change.","type":"array","items":{"required":["type"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"blockConfigurations":{"description":"The blocks as configuration objects, built from blocks. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"images":{"description":"Images to place in the email, at most 7, each with its http or https URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image, at most 2048 characters.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}}},"type":"object"},"UpdateRequest":{"description":"What to change on a generated campaign. At least one of a changed template, a changed brandkitUuid, a changed summarizationUuid, an editPrompt, blocks or images must be given, or the request is refused with 422.","required":["template"],"properties":{"brandkitUuid":{"description":"UUID of a brand kit of the account to restyle the email with, or null. Counts as a change only when it differs from the one stored on the request.","type":["string","null"],"format":"uuid","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"summarizationUuid":{"description":"UUID of a finished content summarization of the account to draw the copy from, or null. Counts as a change only when it differs from the one stored on the request. Refused with 409 while the summarization is in progress and 422 when it errored.","type":["string","null"],"format":"uuid","example":"6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c"},"summarizationRecord":{"description":"The stored summarization, from summarizationUuid. Resolved by the server; not part of the payload.","type":"object","readOnly":true},"useSummarizationLink":{"description":"True to link the email's buttons to the summarized page.","type":["boolean","null"],"example":false},"template":{"description":"Key of the layout the campaign should be on. Counts as a change only when it differs from the one stored on the request.","type":"string","enum":["promote","welcome","monthly","whatsnew","announcement","letsmove","clean","producthighlight","flashsale","chillvibes","boldheader","colorblocks","fashioneditorial","flashsalecountdown","freetrialcountdown","elegantambiance"],"example":"promote"},"editPrompt":{"description":"Free-text instruction for the model, or null when only the layout, brand kit, summarization, blocks or images change.","type":["string","null"],"example":"Make it shorter and more upbeat"},"contentChange":{"description":"True to let the model rewrite the body content; false to keep it, for instance when only the layout changes.","type":"boolean","example":true},"subjectChange":{"description":"True to let the model rewrite the subject line.","type":"boolean","example":false},"preheaderChange":{"description":"True to let the model rewrite the preheader.","type":"boolean","example":false},"labelId":{"description":"Id of a campaign folder (label) of the account to file the campaign under, or null to leave it.","type":["integer","null"],"example":3},"sessionId":{"description":"Caller's session id, carried through the queue for tracing.","type":["string","null"],"example":"sess_01HZX3K9Q2M8N7P6R5T4V3W2Y1"},"blocks":{"description":"Blocks to place in the layout, each with its type and configuration, or null to leave the blocks alone. A non-null list counts as a change.","type":"array","items":{"required":["type"],"properties":{"type":{"description":"Block type.","type":"string","example":"product"},"config":{"description":"Block configuration, keyed by option.","type":"object","example":{"productId":12}}},"type":"object"}},"images":{"description":"Images to place in the email, at most 7, each with its http or https URL and the position it fills.","type":"array","items":{"required":["url","position"],"properties":{"url":{"description":"http or https URL of the image, at most 2048 characters.","type":"string","example":"https://example.activehosted.com/content/images/hero.png"},"position":{"description":"Where in the email the image goes.","type":"string","example":"hero"},"altText":{"description":"Alternative text for the image. Optional.","type":"string","example":"Autumn collection hero shot"}},"type":"object"}}},"type":"object"},"UpdateResourceRequest":{"description":"What to change on a resource file summary. At least one of summary or original_file_name is required.","properties":{"summary":{"description":"The new summary of the file's content. Must not be blank.","type":"string","example":"A six-page guide to the company brand."},"original_file_name":{"description":"The new name of the file. Must not be blank and is at most 250 characters.","type":"string","example":"brand-guidelines-2026.pdf"}},"type":"object"},"UpgradeRequestSentResponse":{"description":"Confirmation that the account's primary admin has been notified of the request.","required":["sent"],"properties":{"sent":{"description":"Always true: the email was sent now, or had already been sent for this account and request type.","type":"boolean","example":true}},"type":"object"},"UploadedAccountFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"url":{"type":"string","format":"uri","readOnly":true},"uploaded_file":{"type":"string","format":"uri"},"content_type":{"type":"string"},"original_name":{"type":"string","nullable":true,"maxLength":255}},"required":["id","uploaded_file","url"]},"UserBasicEdit":{"type":"object","properties":{"id":{"type":"integer"}},"required":["id"]},"UserProfileBackfillResponse":{"description":"Whether the call started building a profile for the user.","required":["dispatched","alreadyBackfilled"],"properties":{"dispatched":{"description":"True when a job to build the profile was queued. False when the user already has a profile or has no recent conversations.","type":"boolean","example":true},"alreadyBackfilled":{"description":"True when the user already had a profile, so nothing was queued.","type":"boolean","example":false}},"type":"object"},"UserProfileRefreshJobResponse":{"description":"The outcome of one queued profile refresh. Skips are reported as success so the queue does not retry them.","required":["success"],"properties":{"success":{"description":"Always true, including when the job was skipped.","type":"boolean","example":true},"skipped":{"description":"Why nothing was refreshed: user_not_found when the user no longer exists on the account, in_flight when another refresh for the user is already running. Omitted when the profile was refreshed.","type":"string","enum":["user_not_found","in_flight"],"example":"in_flight"}},"type":"object"},"UserProfileRefreshRequest":{"description":"The user whose profile to refresh.","required":["account_id","user_id"],"properties":{"account_id":{"description":"Id of the account the user belongs to. Must be the calling account.","type":"integer","example":12345},"user_id":{"description":"Id of the user whose profile to refresh.","type":"integer","example":7}},"type":"object"},"UserProfileResponse":{"description":"The AI-generated profile of a user, built from their last 30 days of AI conversations. A user with no profile yet gets an empty one.","required":["account_id","user_id","who_they_are","how_they_work","top_of_mind","summary_last","summary_all","generated_at","last_requested_at","earliest_conversation_at","latest_conversation_at"],"properties":{"account_id":{"description":"Id of the account the profile belongs to.","type":"integer","example":12345},"user_id":{"description":"Id of the user the profile describes.","type":"integer","example":7},"who_they_are":{"description":"One or two sentences on who the user is. Empty until a profile has been generated.","type":"string","example":"Marketing manager at a small online shop who sends weekly newsletters."},"how_they_work":{"description":"The user's preferences and frequent activities.","type":"array","items":{"type":"string"},"example":["Prefers short subject lines","Builds automations from templates"]},"top_of_mind":{"description":"What the user has recently been trying to get done, inferred from their latest requests.","type":"array","items":{"type":"string"},"example":["Setting up a welcome series"]},"summary_last":{"description":"What the user did in their most recent finished conversation. Empty until a profile has been generated.","type":"string","example":"Drafted a welcome email for new subscribers."},"summary_all":{"description":"What the user did across the whole 30-day window. Empty until a profile has been generated.","type":"string","example":"Created two campaigns and a welcome automation."},"generated_at":{"description":"When the profile was generated, as an ISO 8601 UTC timestamp.","type":"string","example":"2026-10-19T14:30:00Z"},"last_requested_at":{"description":"When the profile was last read, as a UTC date and time. Null if it has never been read.","type":["string","null"],"example":"2026-10-19 15:02:11"},"earliest_conversation_at":{"description":"When the oldest conversation in the window took place, as an ISO 8601 UTC timestamp. Null if the profile was not generated from conversations.","type":["string","null"],"example":"2026-09-21T09:12:00Z"},"latest_conversation_at":{"description":"When the newest conversation in the window took place, as an ISO 8601 UTC timestamp. Null if the profile was not generated from conversations.","type":["string","null"],"example":"2026-10-19T13:55:00Z"}},"type":"object"},"UserSimple":{"type":"object","properties":{"id":{"type":"integer"},"first_name":{"type":"string","readOnly":true},"last_name":{"type":"string","readOnly":true},"email":{"type":"string","format":"email","readOnly":true},"account":{"type":"integer","readOnly":true,"nullable":true},"profile_image":{"type":"string","format":"uri","readOnly":true,"nullable":true},"date_joined":{"type":"string","format":"date-time","readOnly":true}},"required":["account","date_joined","email","first_name","id","last_name","profile_image"]},"UserStateEntry":{"type":"object","description":"One saved piece of state.","required":["type","value"],"properties":{"type":{"type":"string","enum":["value","list","set","hash"],"description":"How the value is kept. value is one string, list is an ordered list, set is a list with no repeats and no fixed order, hash is an object of names to strings."},"value":{"type":["string","number","boolean","array","object"],"description":"The value. A string or number for value; an array of strings or numbers for list and set; an object of names to strings or numbers for hash. Saving replaces the whole value. Numbers and booleans come back as strings.","example":"12"}}},"UserStateNamespaces":{"type":"object","description":"Saved state by namespace. Each property name is a namespace, such as automation.","additionalProperties":{"type":"object","description":"Saved state in one namespace. Each property name is a key.","additionalProperties":{"$ref":"#/components/schemas/UserStateEntry"}}},"ValidationError":{"title":"ValidationError","type":"object","properties":{"loc":{"title":"Location","type":"array","items":{"anyOf":[{"type":"string"},{"type":"integer"}]}},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"},"input":{"title":"Input"},"ctx":{"title":"Context","type":"object"}},"required":["loc","msg","type"]},"VariantSetPickRequest":{"description":"Which take of the set becomes the campaign, and optionally what to attribute it to.","required":["variantKey"],"properties":{"variantKey":{"description":"The key of the take to commit, as recorded on the set.","type":["string","null"],"example":"b"},"attribution":{"description":"Optional attribution for the campaign the pick creates: the insight resource that led to it and the trace that grouped the run. Analytics metadata only; blank values count as absent.","properties":{"resourceId":{"description":"Id of the insight resource the set was composed for.","type":"string","example":"insight-42"},"traceId":{"description":"Id of the trace that grouped the composition.","type":"string","example":"trace-7f3a"}},"type":"object","example":{"resourceId":"insight-42","traceId":"trace-7f3a"}}},"type":"object"},"VariantSetReserveRequest":{"description":"A reservation for a set of takes: the id the set will be known by, and how long it stays pickable.","required":["requestId"],"properties":{"requestId":{"description":"The caller's key for the set, 4 to 128 characters of letters, digits, dots, colons, underscores or dashes; every later call names the set by it. Reserving again under the same id answers 200 with the existing set and takes no second slot.","type":["string","null"],"example":"toolu_01MdDJX8YPKg"},"expiresAt":{"description":"When the set stops being pickable: an absolute ISO-8601 instant with a Z or offset. Omitted, the set is pickable for 24 hours.","type":["string","null"],"example":"2026-10-09T12:00:00Z"}},"type":"object"},"VariantSetVariantsRequest":{"description":"The takes the sender was shown, one entry per take in the order the engine answered them.","required":["variants"],"properties":{"variants":{"description":"One entry per take, at most 3, in the order shown. At least one take must carry an assetDraftId; a take the engine failed is sent without one, so the record shows the slot the sender saw empty. Sending the same list again answers 200 with the stored set; a different list is refused with 409.","type":"array","items":{"required":["variantKey","angle"],"properties":{"variantKey":{"description":"Short lowercase key the picker names the take by, unique within the set: the position or the angle.","type":"string","example":"a"},"angle":{"description":"The angle the take led with, from the engine's closed wheel.","type":"string","example":"outcome"},"layout":{"description":"The layout the take was composed in, when the engine named one. At most 64 characters.","type":"string","example":"hero-first"},"assetDraftId":{"description":"The asset draft the take became. Absent for a take that failed to compose.","type":"string","example":"draft-7c2e"}},"type":"object"},"maxItems":3,"minItems":1,"example":[{"variantKey":"a","angle":"outcome","layout":"hero-first","assetDraftId":"draft-7c2e"},{"variantKey":"b","angle":"objection","assetDraftId":"draft-9d10"},{"variantKey":"c","angle":"moment"}]}},"type":"object"},"WebhookSampleSendResult":{"description":"What the URL answered to the sample payload of one event type.","properties":{"responseCode":{"description":"HTTP status the URL answered with. `0` for a type with no sample data, which is not sent, and when the URL answered with a 5xx status or could not be reached.","type":"integer","example":200},"responseBody":{"description":"The body the URL answered with, cut to 400 characters followed by `...` when longer. When `responseCode` is `0`, the reason instead: for an unknown type, a message listing the valid types; otherwise the error the HTTP client raised.","type":"string","example":"OK"}},"type":"object"},"WebsiteImageSaveRequest":{"description":"The image to import.","required":["url"],"properties":{"url":{"description":"Address of the image, as answered by POST /ai/images/scrape. Must be https and public; fetched and checked before import.","type":"string","example":"https://www.example.com/images/hero.jpg"}},"type":"object"},"WeekdayEnum":{"enum":[0,1,2,3,4,5,6],"type":"integer","description":"* `0` - Monday\n* `1` - Tuesday\n* `2` - Wednesday\n* `3` - Thursday\n* `4` - Friday\n* `5` - Saturday\n* `6` - Sunday"},"WhatsAppMessage":{"type":"object","properties":{"id":{"type":"string"},"to_number":{"type":"string","readOnly":true},"from_number":{"type":"string","readOnly":true},"body":{"type":"string","nullable":true},"direction":{"type":"string"},"timestamp":{"type":"string","format":"date-time","readOnly":true},"contact":{"type":"string"},"status":{"allOf":[{"$ref":"#/components/schemas/MessageStatusEnum"}],"readOnly":true},"queued_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"accepted_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"sent_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"delivered_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"read_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"failed_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"provider_id":{"type":"string","readOnly":true,"nullable":true},"provider_error_code":{"type":"string","readOnly":true,"nullable":true},"provider_error_message":{"type":"string","readOnly":true,"nullable":true},"sent_by":{"$ref":"#/components/schemas/SimpleUser"},"is_deleted":{"type":"boolean","readOnly":true},"content":{"readOnly":true,"nullable":true},"whatsapp_template":{"$ref":"#/components/schemas/WhatsAppTemplateSimpleRead"},"content_type":{"type":"string","readOnly":true,"nullable":true},"content_url":{"type":"string","format":"uri","readOnly":true,"nullable":true},"msg_type":{"allOf":[{"$ref":"#/components/schemas/MessageTypeEnum"}],"readOnly":true},"location":{"$ref":"#/components/schemas/LocationMessage"},"failed_attempts":{"type":"integer","readOnly":true},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactMessage"}},"source":{"allOf":[{"$ref":"#/components/schemas/MessageSourceEnum"}],"readOnly":true},"context_message":{"allOf":[{"$ref":"#/components/schemas/WhatsAppMessageWithoutContext"}],"readOnly":true}},"required":["accepted_on","contact","contacts","content","content_type","content_url","context_message","delivered_on","direction","failed_attempts","failed_on","from_number","id","is_deleted","location","msg_type","provider_error_code","provider_error_message","provider_id","queued_on","read_on","sent_by","sent_on","source","status","timestamp","to_number","whatsapp_template"]},"WhatsAppMessageSimple":{"type":"object","properties":{"id":{"type":"string"},"to_number":{"type":"string","readOnly":true},"from_number":{"type":"string","readOnly":true},"body":{"type":"string","nullable":true},"direction":{"type":"string"},"timestamp":{"type":"string","format":"date-time","readOnly":true},"contact":{"type":"string"},"status":{"allOf":[{"$ref":"#/components/schemas/MessageStatusEnum"}],"readOnly":true},"queued_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"accepted_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"sent_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"delivered_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"read_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"failed_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"provider_id":{"type":"string","readOnly":true,"nullable":true},"provider_error_code":{"type":"string","readOnly":true,"nullable":true},"provider_error_message":{"type":"string","readOnly":true,"nullable":true},"sent_by":{"$ref":"#/components/schemas/SimpleUser"},"is_deleted":{"type":"boolean","readOnly":true},"content":{"readOnly":true,"nullable":true},"whatsapp_template":{"type":"string","format":"uuid","readOnly":true,"nullable":true},"content_type":{"type":"string","readOnly":true,"nullable":true},"content_url":{"type":"string","format":"uri","nullable":true,"maxLength":2000},"msg_type":{"$ref":"#/components/schemas/MessageTypeEnum"},"failed_attempts":{"type":"integer","readOnly":true},"source":{"allOf":[{"$ref":"#/components/schemas/MessageSourceEnum"}],"readOnly":true}},"required":["accepted_on","contact","content","content_type","delivered_on","direction","failed_attempts","failed_on","from_number","id","is_deleted","provider_error_code","provider_error_message","provider_id","queued_on","read_on","sent_by","sent_on","source","status","timestamp","to_number","whatsapp_template"]},"WhatsAppMessageWithoutContext":{"type":"object","properties":{"id":{"type":"string"},"to_number":{"type":"string","readOnly":true},"from_number":{"type":"string","readOnly":true},"body":{"type":"string","nullable":true},"direction":{"type":"string"},"timestamp":{"type":"string","format":"date-time","readOnly":true},"contact":{"type":"string"},"status":{"allOf":[{"$ref":"#/components/schemas/MessageStatusEnum"}],"readOnly":true},"queued_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"accepted_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"sent_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"delivered_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"read_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"failed_on":{"type":"string","format":"date-time","readOnly":true,"nullable":true},"provider_id":{"type":"string","readOnly":true,"nullable":true},"provider_error_code":{"type":"string","readOnly":true,"nullable":true},"provider_error_message":{"type":"string","readOnly":true,"nullable":true},"sent_by":{"$ref":"#/components/schemas/SimpleUser"},"is_deleted":{"type":"boolean","readOnly":true},"content":{"readOnly":true,"nullable":true},"whatsapp_template":{"$ref":"#/components/schemas/WhatsAppTemplateSimpleRead"},"content_type":{"type":"string","readOnly":true,"nullable":true},"content_url":{"type":"string","format":"uri","readOnly":true,"nullable":true},"msg_type":{"allOf":[{"$ref":"#/components/schemas/MessageTypeEnum"}],"readOnly":true},"location":{"$ref":"#/components/schemas/LocationMessage"},"failed_attempts":{"type":"integer","readOnly":true},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactMessage"}},"source":{"allOf":[{"$ref":"#/components/schemas/MessageSourceEnum"}],"readOnly":true}},"required":["accepted_on","contact","contacts","content","content_type","content_url","delivered_on","direction","failed_attempts","failed_on","from_number","id","is_deleted","location","msg_type","provider_error_code","provider_error_message","provider_id","queued_on","read_on","sent_by","sent_on","source","status","timestamp","to_number","whatsapp_template"]},"WhatsAppTemplateRead":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"language":{"$ref":"#/components/schemas/LanguageEnum"},"components":{"nullable":true},"id":{"type":"string","format":"uuid","readOnly":true,"description":"The UUID of the WhatsApp Template to be sent."},"category":{"$ref":"#/components/schemas/CategoryEnum"},"status":{"$ref":"#/components/schemas/WhatsAppTemplateStatusEnum"},"rejected_reason":{"type":"string","nullable":true},"is_deleted":{"type":"boolean"},"channel":{"allOf":[{"$ref":"#/components/schemas/SimpleChannel"}],"readOnly":true,"description":"The ID of the WhatsApp Channel that the WhatsApp Template is for."},"is_sample":{"type":"boolean"},"show_in_sandbox":{"type":"boolean"}},"required":["category","channel","id","language","name"]},"WhatsAppTemplateSend":{"type":"object","properties":{"variables":{"type":"array","items":{"type":"string"},"description":"An array of variables to be used in the WhatsApp Template. Variables are taken in order HEADER, BODY and BUTTONs. (e.g. position 0 corresponds to the HEADER (if it exists) or variable {{1}}, position 1 to variable {{2}} and so on."},"phone":{"type":"string","description":"The phone number to send the WhatsApp Template to.","maxLength":20}},"required":["phone"]},"WhatsAppTemplateSendPublicResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Message Id"},"conversation":{"type":"string","format":"uuid","description":"Message Conversation Id"}},"required":["conversation","id"]},"WhatsAppTemplateSimpleRead":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"language":{"$ref":"#/components/schemas/LanguageEnum"},"components":{"nullable":true},"id":{"type":"string","format":"uuid","readOnly":true,"description":"The UUID of the WhatsApp Template to be sent."},"category":{"$ref":"#/components/schemas/CategoryEnum"},"status":{"$ref":"#/components/schemas/WhatsAppTemplateStatusEnum"},"rejected_reason":{"type":"string","nullable":true},"is_deleted":{"type":"boolean"},"channel":{"allOf":[{"$ref":"#/components/schemas/SimpleChannel"}],"description":"The ID of the WhatsApp Channel that the WhatsApp Template is for."},"show_in_sandbox":{"type":"boolean"}},"required":["category","channel","id","language","name"]},"WhatsAppTemplateStatusEnum":{"enum":["draft","approved","in_appeal","pending","rejected","pending_deletion","deleted","disabled","submitted"],"type":"string","description":"* `draft` - Draft\n* `approved` - Approved\n* `in_appeal` - In Appeal\n* `pending` - Pending\n* `rejected` - Rejected\n* `pending_deletion` - Pending Deletion\n* `deleted` - Deleted\n* `disabled` - Disabled\n* `submitted` - Submitted"},"WhatsappConnectionBulkSyncRequest":{"description":"The Integration Layer connection to push every contact through. Keys are read in snake_case or camelCase.","required":["connection_id"],"properties":{"connection_id":{"description":"ID of the Integration Layer connection the requests to the WhatsApp service are proxied through.","type":"string","example":"8812"}},"type":"object"},"WhatsappConnectionContactSyncRequest":{"description":"The contact to push to the WhatsApp service, and the Integration Layer connection to push it through. Keys are read in snake_case or camelCase.","required":["contact_id","connection_id"],"properties":{"contact_id":{"description":"ID of the contact to push.","type":"integer","example":42},"connection_id":{"description":"ID of the Integration Layer connection the requests to the WhatsApp service are proxied through.","type":"string","example":"8812"}},"type":"object"},"WhatsappContactDeleteRequest":{"description":"The WhatsApp service contact to remove. Keys are read in snake_case or camelCase, so contactExternalId is accepted too.","required":["contact_external_id"],"properties":{"contact_external_id":{"description":"ID the WhatsApp service gave the contact when it was first pushed, as Hosted recorded it against the contact.","type":"string","example":"3f1c2a9e-7b4d-4e8a-9c11-5d2f6b7a8e90"}},"type":"object"},"WhatsappContactSyncRequest":{"description":"The contact to push to the WhatsApp service. Keys are read in snake_case or camelCase, so contactId is accepted too.","required":["contact_id"],"properties":{"contact_id":{"description":"ID of the contact to push.","type":"integer","example":42}},"type":"object"},"WhatsappFlowEventData":{"description":"One WhatsApp flow execution: which flow ran, for which contact, and the status it reached.","required":["id","contact","status","created_on","flow"],"properties":{"id":{"description":"ID of the flow execution in the WhatsApp service. Becomes the id of the published event record.","type":"string","example":"9b3e4f1a-2c6d-4a7b-8e5f-0d1c2b3a4f5e"},"contact":{"description":"The contact the flow ran for.","required":["ac_id"],"properties":{"ac_id":{"description":"ID of the ActiveCampaign contact. A missing or empty value answers 400; a contact that does not exist answers 404.","type":"integer","example":42}},"type":"object"},"status":{"description":"Status the flow execution reached. Only COMPLETED is accepted; any other value answers 400.","type":"string","enum":["COMPLETED"],"example":"COMPLETED"},"created_on":{"description":"When the flow execution was created, ISO 8601 with a timezone offset. Forwarded unchanged.","type":"string","example":"2026-10-15T14:03:27-05:00"},"flow":{"description":"The flow that ran.","required":["id"],"properties":{"id":{"description":"ID of the flow in the WhatsApp service. A missing or empty value answers 400.","type":"string","example":"c4a8e2d1-5f7b-4c3e-a9d6-1b2e3f4a5c6d"}},"type":"object"}},"type":"object"},"WhatsappFlowEventRequest":{"description":"A flow execution event from the WhatsApp service. Keys are read in snake_case or camelCase.","required":["event_data"],"properties":{"event_data":{"$ref":"#/components/schemas/WhatsappFlowEventData","description":"The flow execution the event reports. Null or missing fails the request."}},"type":"object"},"WhatsappServiceTokenRequest":{"description":"The WhatsApp service API key to store on the account.","required":["token"],"properties":{"token":{"description":"API key generated in the WhatsApp service, stored as given.","type":"string","example":"your-whatsapp-service-api-key"}},"type":"object"}},"requestBodies":{"RootDO":{"description":"Segment Request Document Object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}},"required":true}},"responses":{"AccountCustomFieldMetaBulkConflict":{"description":"The service answered 409.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCustomFieldMetaBulkErrors"},"example":{"errors":[{"status":409,"title":"Conflict"}]}}}},"AccountCustomFieldMetaBulkForbidden":{"description":"The user cannot manage account fields, or the service answered 403. The two cases have different bodies.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCustomFieldMetaBulkErrors"},"examples":{"NoPermission":{"value":{"errors":[{"status":"403","detail":"Forbidden"}]}},"ServiceForbidden":{"value":{"errors":[{"status":403,"title":"Forbidden"}]}}}}}},"AccountCustomFieldMetaBulkInvalid":{"description":"The service refused the data. Hosted builds one entry per service error. The title holds the service's message and detail is empty.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"The service's message."},"detail":{"type":"string","description":"Always empty."},"code":{"type":"integer","description":"Always 422."},"source":{"type":"object","properties":{"pointer":{"type":"string","description":"The service's pointer, after /data/attributes."}}}}}}}},"example":{"errors":[{"title":"The field label field is required.","detail":"","code":422,"source":{"pointer":"/data/attributes/field_label"}}]}}}},"AccountCustomFieldMetaBulkMethodNotAllowed":{"description":"The request used another verb. The Allow header names the one verb this path takes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCustomFieldMetaBulkErrors"},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}},"headers":{"Allow":{"description":"The verb this path takes.","schema":{"type":"string"}}}},"AccountCustomFieldMetaBulkNotFound":{"description":"The service answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCustomFieldMetaBulkErrors"},"example":{"errors":[{"status":404,"title":"Not Found"}]}}}},"AccountCustomFieldMetaBulkResult":{"description":"The service's answer, with its status code. A body with a data list comes back under accountCustomFieldMeta, with keys in camelCase, as for GET /accountCustomFieldMeta. Any other body is decoded and encoded again, so its form can change. An empty object comes back as an empty list, and an empty body as null. Its fields are set by the service.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"AttributionNotEnabled":{"description":"The account does not have Attribution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactConversionPointErrors"}}}},"ContactAutomationStatsBodyNotObject":{"description":"The body is a non-empty JSON value that is not an object, such as [1], 1 or true. An empty array, 0, \"0\", false, null, an empty string or invalid JSON is treated as an empty body and gets the 405. This check runs before the 405.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationStatErrors"},"examples":{"Array body":{"value":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}}}},"ContactAutomationStatsMethodNotAllowed":{"description":"The operation is not supported. Returned every time, except when a POST, PUT or PATCH body is a non-empty JSON value that is not an object.","headers":{"Allow":{"description":"Always GET.","schema":{"type":"string","const":"GET"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationStatErrors"},"examples":{"Not supported":{"value":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}}}},"ContactAutomationStatsNotSupported":{"description":"Always returned. The operation is not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationStatErrors"},"examples":{"Not supported":{"value":{"errors":[{"status":404,"title":"Not Found"}]}}}}}},"ContactConversionBadBody":{"description":"The body is not a JSON object: a non-empty JSON list or a single non-empty value. An empty list, 0, 0.0, \"0\", false, null, an empty string or a body that is not valid JSON counts as an empty body instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, as a number."},"title":{"type":"string"},"detail":{"type":"string","description":"Request body must be a JSON object, followed by what was given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"ContactConversionForbidden":{"description":"The account does not have attribution.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One error.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as text.","example":"403"},"detail":{"type":"string","description":"Says to upgrade the account.","example":"Upgrade your account to enable Attribution"}}}}}}}}},"ContactConversionNotFound":{"description":"No entry has that id, or the entry is left out.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no entry has the id.","example":"No Result found for SubscriberConversion with id 100"}}}}}},"ContactConversionPointBadBody":{"description":"The body is not a JSON object: a non-empty JSON list or a single non-empty value. An empty list, 0, 0.0, \"0\", false, null, an empty string or a body that is not valid JSON counts as an empty body instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, as a number."},"title":{"type":"string"},"detail":{"type":"string","description":"Request body must be a JSON object, followed by what was given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"ContactConversionPointNotFound":{"description":"No point has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no point has the id.","example":"No Result found for SubscriberConversionPoint with id 100"}}}}}},"ContactConversionSourceBadBody":{"description":"The body is not a JSON object: a non-empty JSON list or a single non-empty value. An empty list, 0, false, null, an empty string or a body that is not valid JSON counts as an empty body instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, as a number."},"title":{"type":"string"},"detail":{"type":"string","description":"Request body must be a JSON object, followed by what was given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"ContactConversionSourceError":{"description":"The operation failed on the server.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Something went wrong on our end. Please try again later"}}}},"ContactConversionUpdated":{"description":"The updated entry under contactConversion.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversion":{"$ref":"#/components/schemas/ContactConversionSaved"}}},"example":{"contactConversion":{"contact":"12","conversion":"3","conversionTrigger":"5","converted_by_type":"EcomOrder","converted_by_id":"88","triggerType":"ecommerce","modifier":"","value":20,"currency":"usd","dynamic":"0","cdate":"2026-09-01T14:03:12-05:00","udate":"2026-09-02T09:30:00-05:00","id":"41","conversiontrigger":"5","convertedBy":{"type":"ecom-order","id":"88"}}}}}},"ContactGoalListNotFound":{"description":"No entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no entry has the id.","example":"No Result found for SubscriberGoalList with id 100"}}}}}},"ContactGoalNotFound":{"description":"No goal completion has this id. Body: message, \"No Result found for SubscriberGoal with id\" followed by the id as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no goal completion has the id.","example":"No Result found for SubscriberGoal with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for SubscriberGoal with id 100"}}}}}},"ContactGoalTagNotFound":{"description":"No entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no entry has the id.","example":"No Result found for SubscriberGoalTag with id 100"}}}}}},"DealCustomFieldMetaBulkConflict":{"description":"The service answered 409.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkError"},"example":{"errors":[{"status":409,"title":"Conflict"}]}}}},"DealCustomFieldMetaBulkForbidden":{"description":"The user lacks pg_deal_fields, or the service answered 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkError"},"examples":{"NoPermission":{"value":{"errors":[{"status":"403","detail":"Forbidden"}]}},"ServiceForbidden":{"value":{"errors":[{"status":403,"title":"Forbidden"}]}}}}}},"DealCustomFieldMetaBulkMethodNotAllowed":{"description":"The request used a method the path does not accept.","headers":{"Allow":{"description":"The method the path accepts: DELETE for bulkDelete, PATCH for the others.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkError"},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}},"DealCustomFieldMetaBulkNotFound":{"description":"The service answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkError"},"example":{"errors":[{"status":404,"title":"Not Found"}]}}}},"DealCustomFieldMetaBulkResult":{"description":"The service's answer. Hosted passes on its status code. A JSON body without a data member comes back as the same JSON. A body with a data list comes back as a dealCustomFieldMeta list, as for GET /dealCustomFieldMeta. The shape of the body is up to the service.","content":{"application/json":{"schema":{"type":"object","description":"Body from the custom fields service."}}}},"DealCustomFieldMetaBulkUnprocessable":{"description":"The service refused the request. Hosted rewrites each of the service's errors into this shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkServiceError"}}}},"ExclusionBodyNotObject":{"description":"The body is a JSON list, a string, a number or true, not an object. A body that is not valid JSON, null, an empty list, 0, 0.0, false, \"0\" or an empty string counts as an empty object instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExclusionBodyNotObjectError"}}}},"ExclusionNotFound":{"description":"No rule has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExclusionNotFoundError"}}}},"ExclusionWriteResult":{"description":"The request was handled. A failed check also returns 200. The body then has status error, a message and a code, and nothing is written.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ExclusionSaved"},{"$ref":"#/components/schemas/ExclusionWriteFailed"}]},"examples":{"Result":{"value":{"exclusion":{"id":"7","email":"sam@example.com"},"status":"success"}},"Failed":{"value":{"status":"error","message":"Exclusion already exists","code":409}}}}}},"LabelBadBody":{"description":"The body is JSON but not an object, such as a non-empty list or a non-empty string. An empty body, a body that is not JSON, and empty values such as [] or 0 count as an empty object instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code","example":400},"title":{"type":"string","description":"Name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"LabelInvalid":{"description":"The name is blank after cleaning, another label or initiative already has it, or the description is longer than 500 characters. On create, a missing name or a body without a label object gives the same error as a blank name. Two requests that save the same name at the same moment can both pass this check; the second then gets a 422 with message \"Could not process request\" and the database error under error, not this body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelValidationErrors"},"example":{"errors":[{"title":"The label name is required","detail":"","code":"field_missing","error":"label_label_was_not_provided","source":{"pointer":"/data/attributes/label"}}]}}}},"LabelNotFound":{"description":"No label has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for Folder with id 3"}}},"example":{"message":"No Result found for Folder with id 3"}}}},"ListsMethodNotAllowed":{"description":"A method other than POST. The Allow header says POST.","headers":{"Allow":{"description":"The accepted method","schema":{"type":"string","example":"POST"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsHttpErrors"},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}}},"parameters":{"ContactAutomationHelperAutomation":{"name":"automation","in":"query","required":true,"description":"ID of the automation.","schema":{"type":"integer"}},"ContactAutomationStatId":{"name":"id","in":"path","required":true,"description":"Two whole numbers joined by a hyphen: the contact id, then the automation id. For example, 1-6 is contact 1 in automation 6. GET returns 404 for any other form.","schema":{"type":"string","example":"1-6"}},"ContactConversionId":{"name":"id","in":"path","description":"ID of the entry.","required":true,"schema":{"type":"integer"}},"ContactConversionPointId":{"name":"id","in":"path","description":"Id of the point.","required":true,"schema":{"type":"integer"}},"ContactConversionSourceId":{"name":"id","in":"path","required":true,"description":"Id of the contact conversion source.","schema":{"type":"string"},"example":"5d41402abc4b2a76b9719d911017c592"},"ContactGoalId":{"name":"id","in":"path","description":"ID of the goal completion.","required":true,"schema":{"type":"integer","format":"int32"}},"ContactGoalListId":{"name":"id","in":"path","description":"ID of the entry.","required":true,"schema":{"type":"integer"}},"ContactGoalTagId":{"name":"id","in":"path","description":"ID of the entry.","required":true,"schema":{"type":"integer"}},"ExclusionId":{"name":"id","in":"path","required":true,"description":"ID of the rule.","schema":{"type":"integer","format":"int32"}},"LabelId":{"name":"id","in":"path","required":true,"description":"ID of the label","schema":{"type":"integer"}}}},"security":[{"sec0":[]}],"paths":{"/account/accountEvent":{"post":{"summary":"Deliver an account event","description":"Receives one account lifecycle or billing package event, forwarded from the account events topic by the billing account events proxy, and routes it to the handlers that adjust the account: update-package runs the restore-branding, default-scores, ecommerce-connection, automation-downgrade, phone-only and BotSense handlers; create-package and create-account run the phone-only and BotSense handlers; delete-account and archive-account run the disconnect-email handler. The other types only clear the cached entitlements. Internal: service-to-service, not part of the public API. Legacy endpoint with no method guard: any HTTP method is answered the same way; POST is the documented verb and the one callers use.","operationId":"send-account-event","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"type":"string","description":"Event type. Any other value is a 400.","enum":["create-package","update-package","unexpire-account","enable-account","disable-account","create-account","delete-account","archive-account","unarchive-account","expire-account","failed-revenue-recovery"]},"timestamp":{"type":"string","description":"When the event happened, as the sender wrote it. Missing is a 500."},"data":{"type":"object","description":"The event payload. Missing or not an object is a 500. For create-package and update-package it is the subscription: account_id, product, is_trial, plan_id, plan_tier, quantity, tier and, optionally, product_tier. For the account types it is the account: id, account, dbip, down4, expire and is_expired. Members are read as they are sent; a missing member is read as null.","properties":{"account_id":{"description":"Package events: ID of the account the subscription belongs to."},"product":{"description":"Package events: product of the subscription."},"is_trial":{"description":"Package events: whether the subscription is a trial."},"plan_id":{"description":"Package events: plan of the subscription."},"plan_tier":{"description":"Package events: plan tier of the subscription."},"quantity":{"description":"Package events: quantity of the subscription."},"tier":{"description":"Package events: tier of the subscription."},"product_tier":{"description":"Package events, optional: product tier of the subscription."},"id":{"description":"Account events: ID of the account."},"account":{"description":"Account events: domain name of the account."},"dbip":{"description":"Account events: database host of the account."},"down4":{"description":"Account events: the account's availability status."},"expire":{"description":"Account events: expiration date of the account."},"is_expired":{"description":"Account events: whether the account has expired."}}}},"example":{"type":"update-package","timestamp":"2026-10-01T12:00:00Z","data":{"account_id":123,"product":"marketing","is_trial":false,"plan_id":1,"plan_tier":2,"quantity":1,"tier":2}}}}}},"responses":{"200":{"description":"The event was routed. The body is empty."},"400":{"description":"The event type is not one of the allowed types, or a handler failed while processing it. The body is empty."},"500":{"description":"The request failed on the server. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Something went wrong on our end. Please try again later\"."}}}}}}},"deprecated":false,"x-internal":true}},"/account/billable-contacts":{"get":{"summary":"Retrieve the account's billable contact count","description":"Returns how many contacts count against the account's contact limit. Accounts billed on all contacts, and accounts on an AI plan, count every contact; other accounts count contacts with an active list subscription. The count comes from the timed cache unless skipCache is true; a database count refreshes the cache. Internal: backs the app UI, not part of the public API.","operationId":"retrieve-account-billable-contacts","parameters":[{"name":"skipCache","in":"query","description":"The literal string true counts in the database instead of reading the cached count. Any other value, or none, reads the cache.","required":false,"schema":{"type":"string","enum":["true","false"]},"example":"true"}],"responses":{"200":{"description":"The billable contact count.","content":{"application/json":{"schema":{"required":["billableContacts"],"properties":{"billableContacts":{"description":"Number of contacts that count against the contact limit.","type":"integer","example":1250}},"type":"object"}}}},"500":{"description":"Counting failed. Body: errors, a list with one item carrying status (\"500\") and detail (\"Failed to get billable contacts\")."}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/account/customReportsPreparing":{"get":{"summary":"Retrieve whether custom reports data is ready","description":"Whether the account's custom reports data has been prepared, as recorded in the custom report ETL status table. Any failure reading that status answers prepared: false. Internal: backs the app UI, not part of the public API.","operationId":"retrieve-custom-reports-preparing","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The preparation status.","content":{"application/json":{"schema":{"type":"object","required":["prepared"],"properties":{"prepared":{"type":"boolean","description":"True once the account's custom reports data is prepared; false while it is not, or when the status cannot be read.","example":true}}}}}},"405":{"description":"The request used a method other than GET. The body is empty and the Allow header names GET."}},"deprecated":false,"x-internal":true}},"/account/email":{"get":{"summary":"Retrieve the account owner's email address","description":"Returns the email address of the account owner, read from the core database and cached for a day. Called by the TrackCmp service, which raises site tracking events with the owner's email. Internal: service-to-service, not part of the public API.","operationId":"retrieve-account-owner-email","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The owner's email address.","content":{"application/json":{"schema":{"type":"object","required":["accountOwnerEmail"],"properties":{"accountOwnerEmail":{"type":"string","description":"Email address of the account owner.","example":"owner@example.com"}}}}}},"405":{"description":"The request used a method other than GET. The body is empty and the Allow header names GET."},"500":{"description":"No owner email is stored for the account. accountOwnerEmail is null.","content":{"application/json":{"schema":{"type":"object","properties":{"accountOwnerEmail":{"type":"null","description":"Always null here."}}}}}}},"deprecated":false,"x-internal":true}},"/account/entitlements":{"get":{"summary":"List the account's entitlements","description":"Returns every entitlement of the account's plan that Hosted recognises, from the entitlements store or the billing package service. Internal: backs the app UI, not part of the public API. Served by a small router inside the legacy entitlements file: /account/entitlements answers GET, /account/entitlements/{code} answers GET and /account/entitlements/refresh answers POST; another method is a 405 and any other path under it is a 403.","operationId":"list-account-entitlements","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The entitlements.","content":{"application/json":{"schema":{"type":"object","required":["entitlements"],"properties":{"entitlements":{"type":"array","description":"The account's entitlements.","items":{"$ref":"#/components/schemas/AccountEntitlement"}}}}}}}},"deprecated":false,"x-internal":true}},"/account/entitlements/refresh":{"post":{"summary":"Refresh the account's cached entitlements","description":"Re-reads the account's entitlements from the entitlements store, bypassing the cache, so later reads see the current plan. Takes no body. Internal: backs the app UI, not part of the public API. Served by a small router inside the legacy entitlements file: /account/entitlements answers GET, /account/entitlements/{code} answers GET and /account/entitlements/refresh answers POST; another method is a 405 and any other path under it is a 403.","operationId":"refresh-account-entitlements","x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"Whether the refresh worked.","content":{"application/json":{"schema":{"type":"object","required":["refreshed"],"properties":{"refreshed":{"type":"boolean","description":"True when the entitlements were re-read; false when reading them failed.","example":true}}}}}}},"deprecated":false,"x-internal":true}},"/account/entitlements/{code}":{"get":{"summary":"Retrieve one of the account's entitlements","description":"Returns one entitlement of the account's plan by code. For code sms the response also carries the API user's effective SMS permissions. Internal: backs the app UI and the AI agents, not part of the public API. Served by a small router inside the legacy entitlements file: /account/entitlements answers GET, /account/entitlements/{code} answers GET and /account/entitlements/refresh answers POST; another method is a 405 and any other path under it is a 403.","operationId":"retrieve-account-entitlement","x-canonical-resource":"activecampaign_account","parameters":[{"name":"code","in":"path","description":"Code of the entitlement, for example sms.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The entitlement.","content":{"application/json":{"schema":{"type":"object","required":["entitlement"],"properties":{"entitlement":{"$ref":"#/components/schemas/AccountEntitlement"},"permissions":{"type":"object","description":"Only for code sms: each SMS permission as the API user effectively holds it. All true while granular SMS permissions are off or for the main admin group.","properties":{"campaign_view":{"type":"boolean","description":"May view SMS campaigns."},"campaign_manage":{"type":"boolean","description":"May manage SMS campaigns."},"campaign_send":{"type":"boolean","description":"May send SMS campaigns."},"keyword_view":{"type":"boolean","description":"May view SMS keywords."},"keyword_manage":{"type":"boolean","description":"May manage SMS keywords."},"registration":{"type":"boolean","description":"May access SMS registration."},"sending_options":{"type":"boolean","description":"May manage SMS sending options."},"reporting":{"type":"boolean","description":"May view SMS reports."},"inbox":{"type":"boolean","description":"May view the inbox."}}}}}}}},"404":{"description":"The account does not have this entitlement, or Hosted does not recognise the code. Body: errors, a list with one item carrying status, title and detail (\"Entitlement '<code>' not found\").","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 404."},"title":{"type":"string","description":"The HTTP status title."},"detail":{"type":"string","description":"Names the code that was not found."}}}}}}}}}},"deprecated":false,"x-internal":true}},"/account/franchisee":{"post":{"summary":"Link a franchisee account to the franchisor","description":"Links another account to the authenticated franchisor account as its franchisee, optionally requiring the franchisor to approve the franchisee's campaigns before they send. The account must be a franchisor and the API user must be in the main admin group. After the write the call re-reads the link until it matches the values sent, waiting up to about ten seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"create-franchisee","requestBody":{"description":"A JSON object with the link at the top level (not wrapped in a franchisee member).","required":true,"content":{"application/json":{"schema":{"required":["franchisee_account_id"],"properties":{"franchisee_account_id":{"description":"ID of the account to link as a franchisee. Must not be the franchisor's own account ID.","type":"integer","example":2002},"approval_required":{"description":"Whether the franchisee's campaigns need the franchisor's approval before they send. Defaults to false.","type":"boolean","example":true}},"type":"object"},"example":{"franchisee_account_id":2002,"approval_required":true}}}},"responses":{"201":{"description":"The franchisee is linked. message is \"Franchisee inserted\".","content":{"application/json":{"schema":{"required":["message","franchisee"],"properties":{"message":{"description":"Always \"Franchisee inserted\".","type":"string"},"franchisee":{"$ref":"#/components/schemas/FranchiseeAccountMapping","description":"The franchisee link as read back from the core database after the write."}},"type":"object"}}}},"400":{"description":"franchisee_account_id is missing, empty or the franchisor's own account ID, or the body is not a JSON object. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The link was not stored, or could not be read back with the values sent: the body is message, \"Franchisee not inserted\". A failed database write, for instance when the account is already linked as a franchisee, answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisee not inserted"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/account/franchisee/{id}":{"get":{"summary":"Retrieve a franchisee linked to the franchisor","description":"Returns the link between the authenticated franchisor account and one of its franchisee accounts. The account must be a franchisor and the API user must be in the main admin group. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"retrieve-franchisee","parameters":[{"name":"id","in":"path","description":"ID of the franchisee account. The franchisor's own account ID is a 403.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The franchisee link.","content":{"application/json":{"schema":{"required":["franchisee"],"properties":{"franchisee":{"$ref":"#/components/schemas/FranchiseeAccountMapping","description":"The franchisee link."}},"type":"object"}}}},"400":{"description":"The ID is 0. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is the franchisor's own account ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"404":{"description":"The account with this ID is not a franchisee of this franchisor. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true},"put":{"summary":"Update a franchisee's approval requirement","description":"Sets whether one of the authenticated franchisor's franchisee accounts needs the franchisor's approval before its campaigns send. The account must be a franchisor and the API user must be in the main admin group. After the write the call re-reads the link until it matches the value sent, waiting up to about ten seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"update-franchisee","parameters":[{"name":"id","in":"path","description":"ID of the franchisee account. The franchisor's own account ID is a 403.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"A JSON object with approval_required at the top level (not wrapped in a franchisee member).","required":true,"content":{"application/json":{"schema":{"required":["approval_required"],"properties":{"approval_required":{"description":"Whether the franchisee's campaigns need the franchisor's approval before they send. Must be present; null is a server error.","type":"boolean","example":false}},"type":"object"},"example":{"approval_required":false}}}},"responses":{"200":{"description":"The link was updated. message is \"Franchisee updated\".","content":{"application/json":{"schema":{"required":["message","franchisee"],"properties":{"message":{"description":"Always \"Franchisee updated\".","type":"string"},"franchisee":{"$ref":"#/components/schemas/FranchiseeAccountMapping","description":"The franchisee link as read back from the core database after the write."}},"type":"object"}}}},"400":{"description":"The ID is 0, approval_required is missing, or the body is not a JSON object. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is the franchisor's own account ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The franchisee link could not be read back with the values sent: the body is message, \"Franchisee not updated\". This includes an account that is not a franchisee of this franchisor. A failed database write answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisee not updated"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Unlink a franchisee from the franchisor","description":"Removes the link between the authenticated franchisor account and one of its franchisee accounts. The account must be a franchisor and the API user must be in the main admin group. The call re-reads the link until it is gone, retrying for about two seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"delete-franchisee","parameters":[{"name":"id","in":"path","description":"ID of the franchisee account. The franchisor's own account ID is a 403.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The link was removed, or there was none.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always \"Franchisee deleted\".","type":"string","example":"Franchisee deleted"}},"type":"object"}}}},"400":{"description":"The ID is 0. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is the franchisor's own account ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The link was still readable after the retries: the body is message, \"Franchisee not deleted\". A failed database write answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisee not deleted"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/account/franchisor":{"post":{"summary":"Register the account as an ACHQ franchisor","description":"Registers the authenticated account as an ACHQ franchisor, storing the URL and API key of the franchisor's ACHQ API that Hosted calls back, for example to submit franchisee campaigns for approval. The account must not already be a franchisee and the API user must be in the main admin group. After the write the call re-reads the franchisor until it matches the values sent, waiting up to about ten seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"create-franchisor","requestBody":{"description":"A JSON object with the franchisor's API details at the top level (not wrapped in a franchisor member).","required":true,"content":{"application/json":{"schema":{"required":["apiUrl","apiKey"],"properties":{"apiUrl":{"description":"Base URL of the franchisor's ACHQ API. Must not be empty.","type":"string","example":"https://franchisor.api-us1.com"},"apiKey":{"description":"API key Hosted sends as x-api-key when it calls the franchisor's ACHQ API. Must not be empty. Stored, never returned.","type":"string","example":"a1b2c3d4e5f6"}},"type":"object"},"example":{"apiUrl":"https://franchisor.api-us1.com","apiKey":"a1b2c3d4e5f6"}}}},"responses":{"201":{"description":"The account is registered as a franchisor. message is \"Franchisor inserted\".","content":{"application/json":{"schema":{"required":["message","franchisor"],"properties":{"message":{"description":"Always \"Franchisor inserted\".","type":"string"},"franchisor":{"$ref":"#/components/schemas/ACHQFranchisor","description":"The franchisor as read back from the core database after the write."}},"type":"object"}}}},"400":{"description":"apiUrl or apiKey is missing or empty, or the body is not a JSON object. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account is a franchisee, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The franchisor was not stored, or could not be read back with the values sent: the body is message, \"Franchisor not inserted\". A failed database write, for instance when the account is already a franchisor, answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisor not inserted"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/account/franchisor/{id}":{"get":{"summary":"Retrieve the account's ACHQ franchisor record","description":"Returns the authenticated account's franchisor record and the franchisee accounts linked to it. The account must be a franchisor, the path ID must be its own account ID and the API user must be in the main admin group. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"retrieve-franchisor","parameters":[{"name":"id","in":"path","description":"ID of the franchisor account. Must be the authenticated account's own ID; any other ID is a 403.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The franchisor record.","content":{"application/json":{"schema":{"required":["franchisor"],"properties":{"franchisor":{"$ref":"#/components/schemas/ACHQFranchisor","description":"The account's franchisor record."}},"type":"object"}}}},"400":{"description":"The ID is 0. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is not the authenticated account's own ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"404":{"description":"The account has no franchisor record. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true},"put":{"summary":"Update the account's ACHQ franchisor record","description":"Replaces the stored API URL, API key or both on the authenticated account's franchisor record; a field left out keeps its value. The account must be a franchisor, the path ID must be its own account ID and the API user must be in the main admin group. After the write the call re-reads the franchisor until it matches the values sent, waiting up to about ten seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"update-franchisor","parameters":[{"name":"id","in":"path","description":"ID of the franchisor account. Must be the authenticated account's own ID; any other ID is a 403.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"A JSON object with at least one of apiUrl and apiKey at the top level (not wrapped in a franchisor member).","required":true,"content":{"application/json":{"schema":{"properties":{"apiUrl":{"description":"New base URL of the franchisor's ACHQ API.","type":"string","example":"https://franchisor.api-us1.com"},"apiKey":{"description":"New API key Hosted sends as x-api-key to the franchisor's ACHQ API. Stored, never returned.","type":"string","example":"f6e5d4c3b2a1"}},"type":"object"},"example":{"apiKey":"f6e5d4c3b2a1"}}}},"responses":{"200":{"description":"The franchisor record was updated. message is \"Franchisor updated\".","content":{"application/json":{"schema":{"required":["message","franchisor"],"properties":{"message":{"description":"Always \"Franchisor updated\".","type":"string"},"franchisor":{"$ref":"#/components/schemas/ACHQFranchisor","description":"The franchisor as read back from the core database after the write."}},"type":"object"}}}},"400":{"description":"The ID is 0, both apiUrl and apiKey are missing or empty, or the body is not a JSON object. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is not the authenticated account's own ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The franchisor could not be read back with the values sent: the body is message, \"Franchisor not updated\". A failed database write answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisor not updated"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete the account's ACHQ franchisor record","description":"Removes the authenticated account's franchisor record, so Hosted stops calling the franchisor's ACHQ API. The account must be a franchisor, the path ID must be its own account ID and the API user must be in the main admin group. The call re-reads the record until it is gone, retrying for about two seconds. Internal: called by the ACHQ franchise application, not part of the public API.","operationId":"delete-franchisor","parameters":[{"name":"id","in":"path","description":"ID of the franchisor account. Must be the authenticated account's own ID; any other ID is a 403.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The franchisor record was deleted, or there was none.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always \"Franchisor deleted\".","type":"string","example":"Franchisor deleted"}},"type":"object"}}}},"400":{"description":"The ID is 0. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The ID is not the authenticated account's own ID, the account is not a franchisor, or the API user is not in the main admin group. Body: errors, a list with one item carrying status and title."},"500":{"description":"The record was still readable after the retries: the body is message, \"Franchisor not deleted\". A failed database write answers the generic error instead. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed.","type":"string","example":"Franchisor not deleted"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/account/info":{"get":{"summary":"Retrieve the account's plan, limits and features","description":"Returns what the app needs to know about the authenticated account at start-up: plan and tier, seat, contact and sending limits and their usage, which features the plan includes, site date formats, the sending cell, and the location of the IP address the request came from. Most limits and counts are strings. Not the same as GET /settings/account. Internal: backs the app UI, not part of the public API.","operationId":"retrieve-account-info","responses":{"200":{"description":"The account information. The response is marked private for caches.","content":{"application/json":{"schema":{"properties":{"id":{"description":"ID of the account, as stored; may come back as a numeric string.","type":["integer","string"],"example":"123"},"name":{"description":"The account's domain name.","type":"string","example":"myaccount.activehosted.com"},"rsid":{"description":"ID of the reseller the account belongs to, as a numeric string; \"0\" for an account that is not resold.","type":"string","example":"0"},"date_time":{"description":"When the account was created (Y-m-d H:i:s).","type":"string","example":"2025-01-01 00:00:00"},"date_first_login":{"description":"When the account was first logged in to (Y-m-d H:i:s); null before the first login.","type":["string","null"],"example":"2025-01-10 00:00:00"},"expirationDate":{"description":"Date the account expires (Y-m-d).","type":"string","example":"2026-12-31"},"customDomain":{"description":"Custom domain (CNAME) configured for the account; empty when there is none.","type":["string","null"],"example":""},"plan":{"description":"Marketing plan of the account, as a numeric string; empty when the account has none.","type":"string","example":"123"},"planTier":{"description":"Marketing plan tier, as a numeric string; empty when there is none.","type":"string","example":"2"},"crmPlan":{"description":"CRM plan of the account, as a numeric string; empty when the account has no CRM.","type":"string","example":""},"crmPlanTier":{"description":"CRM plan tier, as a numeric string; empty when there is none.","type":"string","example":""},"crmSeatLimit":{"description":"Number of CRM seats the plan allows. 0 without CRM; -1 means unlimited.","type":"integer","example":0},"emSeatLimit":{"description":"Number of marketing seats the plan allows. 0 without email marketing; -1 means unlimited.","type":"integer","example":25},"version":{"description":"Application version the account runs.","type":"string","example":"9.0"},"isCurrentlyUnderSubscriberLimit":{"description":"Whether the account is within its contact limit.","type":"boolean"},"isReseller":{"description":"Whether the account is a reseller account.","type":"boolean"},"isShowAcBranding":{"description":"Whether ActiveCampaign branding is shown: branding links are on and the account is not a reseller account.","type":"boolean"},"hasSupportWidgetAccess":{"description":"Whether the support (Zendesk) widget is available to the account.","type":"boolean"},"isForeverFree":{"description":"Whether the account is on the deprecated forever-free plan.","type":"boolean"},"lang":{"description":"Language of the account.","type":"string","example":"english"},"currency":{"description":"Currency of the account; USD by default.","type":"string","example":"USD"},"baa":{"description":"Whether the account has a Business Associate Agreement (HIPAA).","type":"boolean"},"affiliate":{"description":"Whether the account is an affiliate account.","type":"boolean"},"enterprise":{"description":"Whether the account is on an Enterprise plan.","type":"boolean"},"beta":{"description":"Whether the account is in the beta programme.","type":"boolean"},"userlimit":{"description":"User count stored on the account; may come back as a numeric string.","type":["integer","string"],"example":"1"},"monthlyCredits":{"description":"Monthly sending credits of the account.","type":"integer","example":0},"rolloverCredits":{"description":"Sending credits rolled over from earlier months.","type":"integer","example":0},"mailLimitOk":{"description":"Whether the account is within its monthly sending limit.","type":"boolean"},"mailLimitNotOkReason":{"description":"Why the sending limit check failed; \"No reason given.\" when it did not.","type":"string","example":"No reason given."},"subscriberLimit":{"description":"Contact limit of the account; may come back as a numeric string.","type":["integer","string"],"example":"250"},"subscriberCount":{"description":"Number of contacts counted against the limit, as a numeric string.","type":"string","example":"42"},"hasAttribution":{"description":"Whether the plan includes attribution.","type":"boolean"},"userLimitReached":{"description":"Whether the account has used all of its user seats.","type":"boolean"},"noGroupAccess":{"description":"Whether the plan lacks user groups.","type":"boolean"},"hasAccount":{"description":"Whether the account is entitled to CRM accounts (companies).","type":"boolean"},"hasCRM":{"description":"Whether the account has CRM (deals).","type":"boolean"},"hasCampaign":{"description":"Whether the account has email marketing (campaigns).","type":"boolean"},"hasSiteMessages":{"description":"Whether the plan includes site messages.","type":"boolean"},"hasTasks":{"description":"Whether the plan includes tasks.","type":"boolean"},"hasDeepData":{"description":"Whether the account may use Deep Data (ecommerce) integrations.","type":"boolean"},"hasIntegrations":{"description":"Whether the account has any connected Deep Data integration.","type":"boolean"},"hasLookerDealsReport":{"description":"Whether the account has the Looker deals report.","type":"boolean"},"hasCustomReporting":{"description":"Whether the account has custom reporting.","type":"boolean"},"hasContactScoring":{"description":"Whether the plan includes contact scoring.","type":"boolean"},"hasScores":{"description":"Whether the plan includes lead scoring.","type":"boolean"},"hasFormBranding":{"description":"Whether forms carry ActiveCampaign branding.","type":"boolean"},"hasFormBrandingToggle":{"description":"Whether the form branding toggle is shown.","type":"boolean"},"canUseFormBrandingToggle":{"description":"Whether the form branding toggle may be switched.","type":"boolean"},"hasWinProbability":{"description":"Whether the plan includes deal win probability.","type":"boolean"},"hasEcomReporting":{"description":"Whether the plan includes ecommerce reporting.","type":"boolean"},"hasAutomationSplitTesting":{"description":"Whether the plan includes split actions in automations.","type":"boolean"},"hasAutomationsMap":{"description":"Whether the plan includes the automations map.","type":"boolean"},"canCreateCustomDomain":{"description":"Whether the account may set up a custom domain.","type":"boolean"},"hasCustomBranding":{"description":"Whether the plan includes custom branding.","type":"boolean"},"newBilling":{"description":"Always true.","type":"boolean"},"domainVerificationRequired":{"description":"Whether sending domains must be verified before use.","type":"boolean"},"isTestAccount":{"description":"Whether the account is an internal test account.","type":"boolean"},"timezone":{"description":"Time zone of the account; empty when none is set.","type":"string","example":"America/Chicago"},"siteInfo":{"description":"Site settings of the account.","properties":{"name":{"description":"Site name.","type":"string","example":"Email Marketing"},"serial":{"description":"Serial of the installation; empty when none is stored.","type":"string","example":""},"timeFormat":{"description":"Time format of the site, as a strftime pattern.","type":"string","example":"%H:%M"},"dateFormat":{"description":"Date format of the site, as a strftime pattern.","type":"string","example":"%m/%d/%Y"},"dateTimeFormat":{"description":"Date and time format of the site, as a strftime pattern.","type":"string","example":"%m/%d/%Y %H:%M"},"sentEmails":{"description":"Emails sent since the billing period started.","type":"integer","example":1500}},"type":"object"},"geoIp":{"description":"Location of the IP address the request came from, every value as a string. An empty array when the address cannot be located.","oneOf":[{"properties":{"city":{"description":"City.","type":"string","example":"Chicago"},"country_name":{"description":"Country name.","type":"string","example":"United States"},"area_code":{"description":"Always \"0\".","type":"string","example":"0"},"country_code":{"description":"ISO country code.","type":"string","example":"US"},"region":{"description":"ISO code of the most specific subdivision.","type":"string","example":"IL"},"continent_code":{"description":"Continent code.","type":"string","example":"NA"},"postal_code":{"description":"Postal code.","type":"string","example":"60601"},"latitude":{"description":"Latitude.","type":"string","example":"41.8781"},"longitude":{"description":"Longitude.","type":"string","example":"-87.6298"},"dma_code":{"description":"Metro (DMA) code; empty when unknown.","type":"string","example":"602"},"tz":{"description":"Time zone.","type":"string","example":"America/Chicago"},"region_name":{"description":"Name of the most specific subdivision.","type":"string","example":"Illinois"},"loc":{"description":"Readable location built from the other fields.","type":"string","example":"Chicago, IL, United States"}},"type":"object"},{"type":"array","items":{"type":"string"},"maxItems":0}]},"sendingEngineCell":{"description":"Routing cell the account sends from; empty when unknown.","type":"string","example":"product-aws-use1-s-1"},"engagedContactsGated":{"description":"For an account on an AI plan, whether it is over its engaged-contacts limit so sending is blocked; null when the account is not on an AI plan.","type":["boolean","null"],"example":null}},"type":"object"}}}},"500":{"description":"Reading the account information failed. Body: message, \"An exception occurred.\".","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"An exception occurred.\".","type":"string","example":"An exception occurred."}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/account/onboardingLog":{"get":{"summary":"Retrieve the account's onboarding answers","description":"Returns what the account owner answered in the signup onboarding flow, from the account's onboarding log in the core database. Any user of the account may call it. Every value is a string as stored, empty when the question was not answered; the later questions, from info_website on, may also be null. Internal: backs the app UI, not part of the public API.","operationId":"retrieve-account-onboarding-log","responses":{"200":{"description":"The onboarding answers. An empty object when the account has no onboarding log.","content":{"application/json":{"schema":{"properties":{"email":{"description":"Email address stored on the onboarding log.","type":"string","example":"owner@example.com"},"current_step":{"description":"Onboarding step the owner last reached.","type":"string","example":"name"},"info_name":{"description":"Name the owner entered.","type":"string","example":"Sam Example"},"info_business_contacts":{"description":"Answer about how many contacts the business has, as stored.","type":"string","example":""},"info_business_industry":{"description":"Industry of the business.","type":"string","example":""},"info_business_name":{"description":"Name of the business.","type":"string","example":"Example Co"},"info_business_location":{"description":"Location of the business.","type":"string","example":""},"info_business_empcount":{"description":"Company size (employee count) answer.","type":"string","example":""},"info_products":{"description":"Tools or products the business already uses.","type":"string","example":""},"info_goals":{"description":"Goals answer.","type":"string","example":""},"info_goals_other":{"description":"Free-text answer for a goal not among the choices.","type":"string","example":""},"info_website":{"description":"Website of the business.","type":["string","null"],"example":"https://example.com"},"info_current_tool":{"description":"Current tool answer.","type":["string","null"],"example":""},"info_onboarding_version":{"description":"Version of the onboarding flow that stored the answers.","type":["string","null"],"example":""},"info_channels":{"description":"Channels answer.","type":["string","null"],"example":""},"info_country_code_region":{"description":"Country region answer.","type":["string","null"],"example":""},"info_country_code_country":{"description":"Country code answer.","type":["string","null"],"example":""},"info_work_type":{"description":"Work type answer.","type":["string","null"],"example":""},"info_platform_intention":{"description":"Platform intention answer: what the owner means to use the platform for.","type":["string","null"],"example":""},"info_experience_level":{"description":"Experience level answer.","type":["string","null"],"example":""}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/account/upgrade":{"post":{"summary":"Opt the account in to a version upgrade","description":"Records that the API user opted the account in to a new application version: stores the target version as the account's upgrade preference, so the upgrade prompt is not shown again, and reports the opt-in to the upgrade webhook. 9.0 is the only version accepted. Reads a form-encoded body, not JSON. The response body is the JSON literal null. Internal: backs the app's upgrade prompt, not part of the public API.","operationId":"upgrade-account-version","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["targetVersion"],"properties":{"targetVersion":{"type":"string","description":"Version to upgrade to. Must be 9.0.","enum":["9.0"],"example":"9.0"}}}}}},"responses":{"200":{"description":"The opt-in was recorded. The body is the JSON literal null.","content":{"application/json":{"schema":{"type":"null"}}}},"405":{"description":"The request used a method other than POST. Body: errors, a list with one item carrying status and title."},"422":{"description":"targetVersion is missing or not 9.0.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 422."},"title":{"type":"string","description":"Always \"Invalid attribute\"."},"source":{"type":"object","description":"Where the error is.","properties":{"pointer":{"type":"string","description":"Always /data/attributes/targetVersion."}}}}}}}}}}},"500":{"description":"The upgrade webhook did not answer success, or could not be reached. The upgrade preference is already stored by then. Body: message, \"Something went wrong on our end. Please try again later\".","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Something went wrong on our end. Please try again later\"."}}}}}}},"deprecated":false,"x-internal":true}},"/accountContacts":{"post":{"summary":"Create an association","description":"Links a contact to an account, optionally with the contact's job title there. A contact can be linked to only one account; to move it, change or delete its existing link. Saving a link also sets the contact's account (`orgid` and `orgname` on the contact) and can start automations that run when a contact's account changes. Needs permission to edit contacts.","operationId":"create-an-account-1","x-canonical-resource":"accountContacts","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountContact":{"description":"The link to create.","properties":{"account":{"type":"integer","description":"ID of an existing account.","format":"int32"},"contact":{"type":"integer","description":"ID of an existing contact that is not linked to a different account.","format":"int32"},"jobTitle":{"type":"string","description":"The contact's job title at the account."}},"required":["account","contact"],"type":"object"}}},"examples":{"Request Example":{"value":{"accountContact":{"contact":2,"account":1,"jobTitle":"Product Manager"}}}}}}},"responses":{"201":{"description":"The link was created. `accounts` holds the linked account.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accounts\": [\n        {\n            \"name\": \"Example Inc\",\n            \"accountUrl\": \"https://www.example.com\",\n            \"createdTimestamp\": \"2019-05-15T15:58:16-05:00\",\n            \"updatedTimestamp\": \"2019-06-26T10:49:10-05:00\",\n            \"owner\": \"1\",\n            \"links\": {\n                \"notes\": \"https://example.api-us1.com/api/3/accounts/2/notes\",\n                \"accountCustomFieldData\": \"https://example.api-us1.com/api/3/accounts/2/accountCustomFieldData\",\n                \"accountContacts\": \"https://example.api-us1.com/api/3/accounts/2/accountContacts\",\n                \"emailActivities\": \"https://example.api-us1.com/api/3/accounts/2/emailActivities\",\n                \"contactEmails\": \"https://example.api-us1.com/api/3/accounts/2/contactEmails\",\n                \"owner\": \"https://example.api-us1.com/api/3/accounts/2/owner\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"accountContact\": {\n        \"account\": 2,\n        \"contact\": 1,\n        \"jobTitle\": \"Product Manager\",\n        \"createdTimestamp\": \"2019-06-26T10:49:10-05:00\",\n        \"updatedTimestamp\": \"2019-06-26T10:49:10-05:00\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/3/accountContacts/2/account\",\n            \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/1/contact\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"accountContact":{"description":"The new link.","type":"object","properties":{"account":{"description":"ID of the account. Returned as it was sent, so it may be a number or a string.","type":["integer","string"],"default":0,"examples":[2]},"contact":{"description":"ID of the contact. Returned as it was sent, so it may be a number or a string.","type":["integer","string"],"default":0,"examples":[1]},"jobTitle":{"description":"The contact's job title at the account, as sent. Absent when it was not sent.","type":"string","examples":["Product Manager"]},"createdTimestamp":{"description":"When the link was created, in ISO 8601 format.","type":"string","examples":["2019-06-26T10:49:10-05:00"]},"updatedTimestamp":{"description":"When the link was last changed, in ISO 8601 format.","type":"string","examples":["2019-06-26T10:49:10-05:00"]},"links":{"description":"URLs of the linked records.","type":"object","properties":{"account":{"description":"URL that returns the account.","type":"string","examples":["https://:account.api-us1.com/api/3/accountContacts/2/account"]},"contact":{"description":"URL that returns the contact.","type":"string","examples":["https://:account.api-us1.com/api/3/accountContacts/1/contact"]}}},"id":{"description":"ID of the link.","type":"string","examples":["1"]}}},"accounts":{"$ref":"#/components/schemas/SideloadedAccounts"}}}}}},"400":{"description":"The body is a non-empty JSON list or a non-empty single value instead of an object. This is checked before anything else. An empty body is read as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactHttpError"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The caller lacks permission to edit contacts. Nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactHttpError"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Forbidden"}]}}}},"422":{"description":"The link failed validation. Nothing was saved. Possible problems: `account` or `contact` is missing, or no account or contact has that id; the contact is already linked to this account; or the contact is already linked to a different account. A contact already linked to this account gets both of the last two errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactValidationErrors"},"examples":{"Missing account":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The account attribute was not provided\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/account\"\n            },\n            \"error\": \"accountContact_account_was_not_provided\"\n        }\n    ]\n}"},"Contact on another account":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"This contact is already associated with an account. We currently do not support contacts on multiple accounts.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/account,contact\"\n            },\n            \"error\": \"\"\n        }\n    ]\n}"}}}}}},"deprecated":false,"x-mcp-tool":{"name":"link_contact_to_account","title":"Link Contact to Account","description":"Add a contact to a CRM account (associate them with it), optionally with their job title there. A contact can only be associated with one account; check list_account_contacts first.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List all associations","description":"Lists links between contacts and accounts. Filter by contact to find a contact's account, or by account to list its contacts. Each link also carries the date and type of the newest of these activities with the contact: a one-to-one email, a campaign sent to them, an automation they started or finished, a forward or reply, a text sent or received, an automation goal they reached, or a deal task. Results come in no guaranteed order. For some accounts, users outside the Admin group see only links for contacts on lists they can access, or on no list.","operationId":"list-all-associations-1","x-canonical-resource":"accountContacts","parameters":[{"name":"filters[contact]","in":"query","description":"Return only links for this contact ID.","schema":{"type":"integer","format":"int32"}},{"name":"filters[account]","in":"query","description":"Return only links for this account ID.","schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"How many links to return. Defaults to 20; values over 100 return 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"How many links to skip. Defaults to 0.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The matching links.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountContacts\": [\n        {\n            \"account\": \"2\",\n            \"contact\": \"3\",\n            \"jobTitle\": \"Product Manager\",\n            \"createdTimestamp\": \"2019-06-26T10:49:10-05:00\",\n            \"updatedTimestamp\": \"2019-06-26T10:49:10-05:00\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/3/accountContacts/17/account\",\n                \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/17/contact\"\n            },\n            \"id\": \"17\"\n        },\n        {\n            \"account\": \"2\",\n            \"contact\": \"1\",\n            \"jobTitle\": \"Product Manager\",\n            \"createdTimestamp\": \"2019-06-26T11:26:09-05:00\",\n            \"updatedTimestamp\": \"2019-06-26T11:26:09-05:00\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/3/accountContacts/18/account\",\n                \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/18/contact\"\n            },\n            \"id\": \"18\"\n        },\n        {\n            \"account\": \"3\",\n            \"contact\": \"2\",\n            \"jobTitle\": \"Product Manager\",\n            \"createdTimestamp\": \"2019-06-26T11:26:15-05:00\",\n            \"updatedTimestamp\": \"2019-06-26T11:26:15-05:00\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/3/accountContacts/19/account\",\n                \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/19/contact\"\n            },\n            \"id\": \"19\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"accountContacts":{"description":"The links on this page.","type":"array","items":{"type":"object","properties":{"account":{"description":"ID of the account.","type":"string","examples":["2"]},"contact":{"description":"ID of the contact.","type":"string","examples":["3"]},"jobTitle":{"description":"The contact's job title at the account. null when none was set.","type":["string","null"],"examples":["Product Manager"]},"createdTimestamp":{"description":"When the link was created, in ISO 8601 format.","type":"string","examples":["2019-06-26T10:49:10-05:00"]},"updatedTimestamp":{"description":"When the link was last changed, in ISO 8601 format.","type":"string","examples":["2019-06-26T10:49:10-05:00"]},"links":{"description":"URLs of the linked records.","type":"object","properties":{"account":{"description":"URL that returns the account.","type":"string","examples":["https://:account.api-us1.com/api/3/accountContacts/17/account"]},"contact":{"description":"URL that returns the contact.","type":"string","examples":["https://:account.api-us1.com/api/3/accountContacts/17/contact"]}}},"id":{"description":"ID of the link.","type":"string","examples":["17"]},"lastContactDate":{"type":"string","description":"When the newest of those activities happened (see the operation description), in ISO 8601 format. Absent when there is none.","examples":["2019-06-27T09:12:00-05:00"]},"lastContactType":{"type":["string","null"],"description":"What that activity was, as a label in the user's language: Email, Text, or for a deal task the name of its task type (Task when the task no longer exists). Absent when there is none. Null when the deal task has no task type.","examples":["Email"]}}}},"meta":{"description":"Information about the whole result.","type":"object","properties":{"total":{"description":"Number of matching links, ignoring limit and offset, as a numeric string.","type":"string","examples":["3"]}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_account_contacts","title":"List Account Contacts","description":"List which contacts are associated with which CRM accounts, with each contact's job title at that account. Filter by an account id to see the contacts associated with it, or by a contact id to see which account a contact is associated with.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/accountContacts/{id}":{"get":{"summary":"Retrieve an association","description":"Returns one link between a contact and an account. No list permissions are applied.","operationId":"retrieve-an-association","x-canonical-resource":"accountContacts","parameters":[{"name":"id","in":"path","description":"ID of the link.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The link.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountContact\": {\n        \"account\": \"2\",\n        \"contact\": \"1\",\n        \"jobTitle\": \"Product Manager\",\n        \"createdTimestamp\": \"2019-06-26T11:26:09-05:00\",\n        \"updatedTimestamp\": \"2019-06-26T11:26:09-05:00\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/3/accountContacts/18/account\",\n            \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/18/contact\"\n        },\n        \"id\": \"18\"\n    }\n}"}},"schema":{"type":"object","properties":{"accountContact":{"description":"The link.","type":"object","properties":{"account":{"description":"ID of the account.","type":"string","example":"2"},"contact":{"description":"ID of the contact.","type":"string","example":"1"},"jobTitle":{"description":"The contact's job title at the account. null when none was set.","type":["string","null"],"example":"Product Manager"},"createdTimestamp":{"description":"When the link was created, in ISO 8601 format.","type":"string","example":"2019-06-26T11:26:09-05:00"},"updatedTimestamp":{"description":"When the link was last changed, in ISO 8601 format.","type":"string","example":"2019-06-26T11:26:09-05:00"},"links":{"description":"URLs of the linked records.","type":"object","properties":{"account":{"description":"URL that returns the account.","type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/18/account"},"contact":{"description":"URL that returns the contact.","type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/18/contact"}}},"id":{"description":"ID of the link.","type":"string","example":"18"}}}}}}}},"404":{"description":"No link has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for CustomerAccountSubscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says that no link has this id.","type":"string","example":"No Result found for CustomerAccountSubscriber with id 100"}}}}}}},"deprecated":false},"put":{"summary":"Update an association","description":"Changes a link. Send only the fields to change; the others keep their values. Changing `account` moves the contact to that account. Saving a link also sets the contact's account (`orgid` and `orgname` on the contact) and can start automations that run when a contact's account changes. Changing `contact` does not clear `orgid` and `orgname` on the contact that was linked before. Needs permission to edit contacts. PATCH /accountContacts/{id} does the same thing.","operationId":"update-an-association-1","x-canonical-resource":"accountContacts","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the link.","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountContact":{"description":"The fields to change.","properties":{"account":{"type":"integer","description":"ID of an existing account to move the contact to.","format":"int32"},"contact":{"type":"integer","description":"ID of an existing contact that is not linked to a different account.","format":"int32"},"jobTitle":{"type":"string","description":"The contact's job title at the account."}},"type":"object"}}},"examples":{"Request Example":{"value":{"accountContact":{"jobTitle":"Product Manager"}}}}}}},"responses":{"200":{"description":"The link was changed. `accounts` holds the linked account.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accounts\": [\n        {\n            \"name\": \"Example Inc\",\n            \"accountUrl\": \"https://www.example.com\",\n            \"createdTimestamp\": \"2019-05-15T15:58:16-05:00\",\n            \"updatedTimestamp\": \"2019-06-26T10:49:10-05:00\",\n            \"owner\": \"1\",\n            \"links\": {\n                \"notes\": \"https://example.api-us1.com/api/3/accounts/3/notes\",\n                \"accountCustomFieldData\": \"https://example.api-us1.com/api/3/accounts/3/accountCustomFieldData\",\n                \"accountContacts\": \"https://example.api-us1.com/api/3/accounts/3/accountContacts\",\n                \"emailActivities\": \"https://example.api-us1.com/api/3/accounts/3/emailActivities\",\n                \"contactEmails\": \"https://example.api-us1.com/api/3/accounts/3/contactEmails\",\n                \"owner\": \"https://example.api-us1.com/api/3/accounts/3/owner\"\n            },\n            \"id\": \"3\"\n        }\n    ],\n    \"accountContact\": {\n        \"account\": \"3\",\n        \"contact\": \"2\",\n        \"jobTitle\": \"CEO\",\n        \"createdTimestamp\": \"2019-06-26T11:26:15-05:00\",\n        \"updatedTimestamp\": \"2019-06-26T11:29:57-05:00\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/3/accountContacts/19/account\",\n            \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/19/contact\"\n        },\n        \"id\": \"19\"\n    }\n}"}},"schema":{"type":"object","properties":{"accountContact":{"description":"The changed link.","type":"object","properties":{"account":{"description":"ID of the account. Returned as it was sent, so it may be a number or a string.","type":["integer","string"],"example":"3"},"contact":{"description":"ID of the contact. Returned as it was sent, so it may be a number or a string.","type":["integer","string"],"example":"2"},"jobTitle":{"description":"The contact's job title at the account: the value sent, or the stored value (which may be null) when jobTitle was not sent.","type":["string","null"],"example":"CEO"},"createdTimestamp":{"description":"When the link was created, in ISO 8601 format.","type":"string","example":"2019-06-26T11:26:15-05:00"},"updatedTimestamp":{"description":"When the link was last changed, in ISO 8601 format.","type":"string","example":"2019-06-26T11:29:57-05:00"},"links":{"description":"URLs of the linked records.","type":"object","properties":{"account":{"description":"URL that returns the account.","type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/19/account"},"contact":{"description":"URL that returns the contact.","type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/19/contact"}}},"id":{"description":"ID of the link.","type":"string","example":"19"}}},"accounts":{"$ref":"#/components/schemas/SideloadedAccounts"}}}}}},"400":{"description":"The body is a non-empty JSON list or a non-empty single value instead of an object. This is checked before anything else. An empty body is read as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactHttpError"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The caller lacks permission to edit contacts. Nothing was changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactHttpError"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Forbidden"}]}}}},"404":{"description":"No link has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for CustomerAccountSubscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says that no link has this id.","type":"string","example":"No Result found for CustomerAccountSubscriber with id 100"}}}}}},"422":{"description":"The changed link failed validation. Nothing was saved. Possible problems: `account` or `contact` was set to an empty value or to an id that does not exist; or `contact` was changed to a contact already linked to a different account, or already linked to this account (which gives both errors).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactValidationErrors"}}}}},"deprecated":false},"delete":{"summary":"Delete an association","description":"Removes a contact from an account. The contact and the account are kept. The contact's account (`orgid` and `orgname` on the contact) is cleared, which can start automations that run when a contact's account changes. Needs permission to edit contacts.","operationId":"delete-an-association-1","x-canonical-resource":"accountContacts","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the link.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The link was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The caller lacks permission to edit contacts. Nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountContactHttpError"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Forbidden"}]}}}},"404":{"description":"No link has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for CustomerAccountSubscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says that no link has this id.","type":"string","example":"No Result found for CustomerAccountSubscriber with id 100"}}}}}}},"deprecated":false}},"/accountCustomFieldData":{"post":{"summary":"Set an account custom field value","description":"","operationId":"create-a-custom-field-value","x-canonical-resource":"custom_field_value","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountCustomFieldDatum":{"properties":{"customerAccountId":{"type":"integer","description":"The ID of the account this field value relates to","format":"int32"},"customFieldId":{"type":"integer","description":"The ID of the custom field metum this field value relates to","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For `currency` field only, this needs to be in cents: eg, 10050 = 100.5) For `dropdown` and `radio` fields send one option as a plain string, exactly as it appears in the field's options (for example `option 1`). For `multiselect` and `checkbox` fields send a JSON array of options. The `||option 1||option 2||` form used by contact custom fields is not accepted here."},"fieldCurrency":{"type":"string","description":"Currency code for the money value","default":"Default Currency for Field"}},"required":["customerAccountId","customFieldId","fieldValue"],"type":"object"}}},"examples":{"text":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":1,"fieldValue":"Northeast region"}}},"textarea":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":2,"fieldValue":"Met at the 2026 trade show.\nFollow up after the product demo."}}},"hidden":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":3,"fieldValue":"partner-ref-1234"}}},"dropdown":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":4,"fieldValue":"option 1"}}},"radio":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":5,"fieldValue":"option 2"}}},"multiselect":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":6,"fieldValue":["option 1","option 3","option 4"]}}},"checkbox":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":7,"fieldValue":["option 1"]}}},"currency":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":8,"fieldValue":9999,"fieldCurrency":"usd"}}},"number":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":9,"fieldValue":"100.99"}}},"date":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":10,"fieldValue":"2026-12-31"}}},"datetime":{"value":{"accountCustomFieldDatum":{"customerAccountId":2,"customFieldId":11,"fieldValue":"2026-05-19T14:45:00-05:00"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldDatum\": {\n        \"id\": \"5\",\n        \"accountCustomFieldMetumId\": 1,\n        \"accountId\": 2,\n        \"customFieldId\": 1,\n        \"createdTimestamp\": \"2018-11-06 02:27:05\",\n        \"updatedTimestamp\": \"2018-11-06 02:27:05\",\n        \"fieldValue\": \"test title\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/5/account\",\n            \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/5/accountCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","examples":["5"]},"accountCustomFieldMetumId":{"type":"integer","default":0,"examples":[1]},"accountId":{"type":"integer","default":0,"examples":[2]},"customFieldId":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-11-06 02:27:05"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:27:05"]},"fieldValue":{"type":"string","examples":["test title"]},"links":{"type":"object","properties":{"account":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/5/account"]},"accountCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/5/accountCustomFieldMetum"]}}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"set_account_custom_field_value","title":"Set Account Custom Field Value","description":"Give one CRM organization its first value in a field it holds no value for yet. To change a value it already holds, use update_account_custom_field_value with that value's id from list_account_custom_field_values.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List account custom field values","description":"","operationId":"list-all-custom-field-values-2","x-canonical-resource":"custom_field_value","parameters":[{"name":"filters[customerAccountId]","in":"query","description":"Filter results by a specific account (note that Id uses a capital I)","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldData\": [\n        {\n            \"id\": \"3\",\n            \"accountCustomFieldMetumId\": 1,\n            \"accountId\": 1,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:26:07\",\n            \"updatedTimestamp\": \"2018-11-06 02:26:07\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/3/account\",\n                \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/3/accountCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"4\",\n            \"accountCustomFieldMetumId\": 1,\n            \"accountId\": 3,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:26:51\",\n            \"updatedTimestamp\": \"2018-11-06 02:26:51\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/4/account\",\n                \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/4/accountCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"5\",\n            \"accountCustomFieldMetumId\": 1,\n            \"accountId\": 2,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:27:05\",\n            \"updatedTimestamp\": \"2018-11-06 02:27:05\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/5/account\",\n                \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/5/accountCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"1\",\n            \"accountCustomFieldMetumId\": 5,\n            \"accountId\": 2,\n            \"customFieldId\": 5,\n            \"createdTimestamp\": \"2018-10-29 20:40:38\",\n            \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n            \"fieldValue\": \"New title\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/account\",\n                \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/accountCustomFieldMetum\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldData":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["3"]},"accountCustomFieldMetumId":{"type":"integer","default":0,"examples":[1]},"accountId":{"type":"integer","default":0,"examples":[1]},"customFieldId":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-11-06 02:26:07"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:26:07"]},"fieldValue":{"type":"string","examples":["test title"]},"links":{"type":"object","properties":{"account":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/3/account"]},"accountCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/3/accountCustomFieldMetum"]}}}}}},"meta":{"type":"object","properties":{"total":{"type":"string"}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_account_custom_field_values","title":"List Account Custom Field Values","description":"The values CRM company accounts hold in their company account custom fields, one item per account per field.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/accountCustomFieldData/bulkCreate":{"post":{"summary":"Bulk create a custom account field value","description":"","operationId":"bulk-create-a-custom-account-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"array":{"properties":{"customerAccountId":{"type":"integer","description":"The ID of the account this field value relates to","format":"int32"},"customFieldId":{"type":"integer","description":"The ID of the custom field metum this field value relates to","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For currency field only, this needs to be in cents: eg, 10050 = 100.5)"},"fieldCurrency":{"type":"string","description":"Currency code for the money value"}},"required":["customerAccountId","customFieldId","fieldValue"],"type":"object"}}},"examples":{"Request Example":{"value":[{"accountId":"1","customFieldId":"1","fieldValue":"test title"},{"accountId":"1","customFieldId":"2","fieldValue":"test title"},{"accountId":"1","customFieldId":"3","fieldValue":["option 1","option 3","option 4"]},{"accountId":"1","customFieldId":"4","fieldValue":9999,"fieldCurrency":"cad"},{"accountId":"1","customFieldId":"5","fieldValue":"100.99"},{"accountId":"1","customFieldId":"6","fieldValue":"2018-12-31"},{"accountId":"1","customFieldId":"7","fieldValue":"2020-05-19T02:45:00-05:00"}]}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"the bulk insert was successful\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"the bulk insert was successful"}}}}}}},"deprecated":false}},"/accountCustomFieldData/bulkUpdate":{"patch":{"summary":"Bulk update account custom field values","description":"","operationId":"bulk-update-a-custom-account-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"array":{"properties":{"id":{"type":"integer","description":"ID of the dealCustomFieldData to update","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For currency field only, this needs to be in cents: eg, 10050 = 100.5)"},"fieldCurrency":{"type":"string","description":"Currency code for the money value"}},"required":["id","fieldValue"],"type":"object"}}},"examples":{"Request Example":{"value":[{"id":"1","fieldValue":"test title"},{"id":"2","fieldValue":["option 1","option 3","option 4"]},{"id":"3","fieldValue":9999,"fieldCurrency":"cad"},{"id":"4","fieldValue":"100.99"},{"id":"5","fieldValue":"2018-12-31"},{"id":"6","fieldValue":"2020-05-19T02:45:00-05:00"}]}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"AccountCustomFieldDatas with ID(s): 1, 2, 3, 4, 5 successfully bulk updated.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"AccountCustomFieldDatas with ID(s): 1, 2, 3, 4, 5 successfully bulk updated."}}}}}}},"deprecated":false}},"/accountCustomFieldData/{id}":{"get":{"summary":"Retrieve an account custom field value","description":"","operationId":"retrieve-a-custom-field-value","x-canonical-resource":"custom_field_value","parameters":[{"name":"id","in":"path","description":"ID of the dealCustomFieldData to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldDatum\": {\n        \"id\": \"1\",\n        \"accountId\": 2,\n        \"customFieldId\": 5,\n        \"createdTimestamp\": \"2018-10-29 20:40:38\",\n        \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n        \"fieldValue\": \"New title\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/account\",\n            \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/accountCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"accountId":{"type":"integer","example":2,"default":0},"customFieldId":{"type":"integer","example":5,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-29 20:40:38"},"updatedTimestamp":{"type":"string","example":"2018-11-06 02:21:36"},"fieldValue":{"type":"string","example":"New title"},"links":{"type":"object","properties":{"account":{"type":"string","example":"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/account"},"accountCustomFieldMetum":{"type":"string","example":"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/accountCustomFieldMetum"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"put":{"summary":"Update an account custom field value","description":"","operationId":"update-a-custom-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom fields value to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountCustomFieldDatum":{"properties":{"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For `currency` field only, this needs to be in cents: eg, 10050 = 100.5) For `dropdown` and `radio` fields send one option as a plain string, exactly as it appears in the field's options (for example `option 1`). For `multiselect` and `checkbox` fields send a JSON array of options. The `||option 1||option 2||` form used by contact custom fields is not accepted here."},"fieldCurrency":{"type":"string","description":"Currency code for the `currency` value","default":"Default Currency for Field"}},"required":[],"type":"object"}}},"examples":{"text":{"value":{"accountCustomFieldDatum":{"fieldValue":"Northeast region"}}},"textarea":{"value":{"accountCustomFieldDatum":{"fieldValue":"Met at the 2026 trade show.\nFollow up after the product demo."}}},"hidden":{"value":{"accountCustomFieldDatum":{"fieldValue":"partner-ref-1234"}}},"dropdown":{"value":{"accountCustomFieldDatum":{"fieldValue":"option 1"}}},"radio":{"value":{"accountCustomFieldDatum":{"fieldValue":"option 2"}}},"multiselect":{"value":{"accountCustomFieldDatum":{"fieldValue":["option 1","option 3","option 4"]}}},"checkbox":{"value":{"accountCustomFieldDatum":{"fieldValue":["option 1"]}}},"currency":{"value":{"accountCustomFieldDatum":{"fieldValue":9999,"fieldCurrency":"usd"}}},"number":{"value":{"accountCustomFieldDatum":{"fieldValue":"100.99"}}},"date":{"value":{"accountCustomFieldDatum":{"fieldValue":"2026-12-31"}}},"datetime":{"value":{"accountCustomFieldDatum":{"fieldValue":"2026-05-19T14:45:00-05:00"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldDatum\": {\n        \"id\": \"1\",\n        \"accountId\": 2,\n        \"customFieldId\": 5,\n        \"createdTimestamp\": \"2018-10-29 20:40:38\",\n        \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n        \"fieldValue\": \"New title\",\n        \"links\": {\n            \"account\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/account\",\n            \"accountCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/accountCustomFieldData/1/accountCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"accountId":{"type":"integer","default":0,"examples":[2]},"customFieldId":{"type":"integer","default":0,"examples":[5]},"createdTimestamp":{"type":"string","examples":["2018-10-29 20:40:38"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:21:36"]},"fieldValue":{"type":"string","examples":["New title"]},"links":{"type":"object","properties":{"account":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/1/account"]},"accountCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldData/1/accountCustomFieldMetum"]}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"update_account_custom_field_value","title":"Update Account Custom Field Value","description":"Change an account custom field value that already exists, by the value's id from list_account_custom_field_values.","annotations":{"readOnlyHint":false,"idempotentHint":true,"openWorldHint":false}}},"delete":{"summary":"Delete an account custom field value","description":"","operationId":"delete-a-custom-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the dealCustomFieldData to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"AccountCustomFieldData deleted.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"AccountCustomFieldData deleted."}}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false}},"/accountCustomFieldMeta":{"post":{"summary":"Create an account custom field","description":"","operationId":"create-a-customfieldmeta","x-canonical-resource":"custom_field_definition","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountCustomFieldMetum":{"properties":{"fieldLabel":{"type":"string","description":"Name of the field"},"fieldType":{"type":"string","description":"Type of field. Possible values are: `text`, `textarea`, `date`, `datetime`, `dropdown`, `multiselect`, `radio`, `checkbox`, `hidden`, `currency`, `number`, or `lookup`. A `lookup` field shows a field of a related object instead of holding a value of its own, and is configured through `field_options`. The type of an existing field is never changed by an update, so a field has to be created as a `lookup`."},"fieldOptions":{"type":["array","object"],"description":"Options for the field. A list of values, necessary if `field_type` is `dropdown`, `multiselect`, `radio`, or `checkbox`. For a `lookup` field it is an object instead: `{\"lookup\": {\"object\": \"account|contact|deal\", \"field\": \"<field id>\"}}`, naming the object and the field whose value is shown. An update may change a lookup field's configuration, and an update that omits it keeps the stored one.","items":{"type":"string"}},"fieldDefault":{"type":"string","description":"Default value of the field"},"fieldDefaultCurrency":{"type":"string","description":"The 3-letter currency code of the default currency for the field. Only necessary if `field_type` is `currency`."},"isFormVisible":{"type":"boolean","description":"Whether or not the field is visible on forms"},"displayOrder":{"type":"integer","description":"Order for displaying the field on Manage Fields page and deal profiles","format":"int32"},"isRequired":{"type":"boolean","description":"When true, fieldDefault is required."}},"required":["fieldLabel","fieldType"],"type":"object"}}},"examples":{"text":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample text field2","fieldType":"text","fieldDefault":"Default Text","isFormVisible":1,"displayOrder":1}}},"textarea":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample textarea field","fieldType":"textarea","fieldDefault":"Default Text in Text Area","isFormVisible":1,"displayOrder":2}}},"date (ISO ONLY)":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample date field","fieldType":"date","fieldDefault":"2018-12-31 00:00:00","isFormVisible":1,"displayOrder":3}}},"dropdown":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample dropdown field","fieldType":"dropdown","fieldDefault":"option 2","fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"displayOrder":4}}},"multiselect":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample multiselect field","fieldType":"multiselect","fieldDefault":["option 2","option 3"],"fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"displayOrder":5}}},"radio":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample radio field","fieldType":"radio","fieldDefault":"option 2","fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"displayOrder":6}}},"checkbox":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample checkbox field","fieldType":"checkbox","fieldDefault":["option 2","option 3"],"fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"displayOrder":7}}},"hidden":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample hidden field","fieldType":"hidden","fieldDefault":"Default Text in Hidden Field","isFormVisible":1,"displayOrder":8}}},"number":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample number field","fieldType":"number","fieldDefault":"100.99","isFormVisible":1,"displayOrder":9}}},"currency":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample money field","fieldType":"currency","fieldDefault":"10099","fieldDefaultCurrency":"aud","isFormVisible":1,"displayOrder":10}}},"datetime":{"value":{"accountCustomFieldMetum":{"fieldLabel":"sample datetime field","fieldType":"datetime","fieldDefault":"2020-05-16T03:15:00-05:00","isFormVisible":1,"displayOrder":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 0,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 19:57:37\",\n        \"links\": {\n            \"accountCustomFieldData\": \"https://:account.api-us1.com/api/:version/3/accountCustomFieldMeta/1/accountCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"fieldLabel":{"type":"string","examples":["title"]},"fieldType":{"type":"string","examples":["text"]},"fieldOptions":{},"fieldDefault":{"type":"string","examples":["Default Text"]},"isFormVisible":{"type":"integer","default":0,"examples":[1]},"isRequired":{"type":"integer","default":0,"examples":[0]},"displayOrder":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-10-22 19:57:37"]},"updatedTimestamp":{"type":"string","examples":["2018-10-22 19:57:37"]},"links":{"type":"object","properties":{"accountCustomFieldData":{"type":"string","examples":["https://:account.api-us1.com/api/:version/3/accountCustomFieldMeta/1/accountCustomFieldData"]}}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"errors\": [{\n  \t\"title\": \"The field type field is required.\",\n    \"detail\": \"\",\n    \"code\": 422\n  }]\n}"}}}}}},"deprecated":false,"x-mcp-tool":{"name":"create_account_custom_field","title":"Create Account Custom Field","description":"Add a new custom field to company accounts. Creates the field itself on every account: its label, type and options.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List account custom fields","description":"","operationId":"list-all-custom-fields-meta","x-canonical-resource":"custom_field_definition","parameters":[{"name":"limit","in":"query","description":"The number of fields returned per request.","schema":{"type":"integer","format":"int32","default":100}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldMeta\": [\n        {\n            \"id\": \"1\",\n            \"fieldLabel\": \"Text Example\",\n            \"fieldType\": \"text\",\n            \"fieldOptions\": null,\n            \"fieldDefault\": 1,\n            \"fieldDefaultCurrency\": null,\n            \"isFormVisible\": 0,\n            \"isRequired\": 0,\n            \"displayOrder\": 1,\n            \"personalization\": \"\",\n            \"knownFieldId\": null,\n            \"hideFieldFlag\": 0,\n            \"createdTimestamp\": \"2019-04-23 15:34:00\",\n            \"updatedTimestamp\": \"2019-05-03 15:16:51\",\n            \"links\": {\n                \"accountCustomFieldData\": \"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData\"\n            }\n        },\n        {\n            \"id\": \"2\",\n            \"fieldLabel\": \"Multiple Choice Example\",\n            \"fieldType\": \"multiselect\",\n            \"fieldOptions\": [\n            \t\"Option 1\",\n            \t\"Option 2\",\n            \t\"Option 3\"\n            ],\n            \"fieldDefault\": 1,\n            \"fieldDefaultCurrency\": null,\n            \"isFormVisible\": 0,\n            \"isRequired\": 0,\n            \"displayOrder\": 2,\n            \"personalization\": \"\",\n            \"knownFieldId\": null,\n            \"hideFieldFlag\": 0,\n            \"createdTimestamp\": \"2019-04-23 15:34:00\",\n            \"updatedTimestamp\": \"2019-05-03 15:16:51\",\n            \"links\": {\n                \"accountCustomFieldData\": \"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldMeta":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"fieldLabel":{"type":"string","examples":["Text Example"]},"fieldType":{"type":"string","examples":["text"]},"fieldOptions":{},"fieldDefault":{"type":"integer","default":0,"examples":[1]},"fieldDefaultCurrency":{},"isFormVisible":{"type":"integer","default":0,"examples":[0]},"isRequired":{"type":"integer","default":0,"examples":[0]},"displayOrder":{"type":"integer","default":0,"examples":[1]},"personalization":{"type":"string","examples":[""]},"knownFieldId":{},"hideFieldFlag":{"type":"integer","default":0,"examples":[0]},"createdTimestamp":{"type":"string","examples":["2019-04-23 15:34:00"]},"updatedTimestamp":{"type":"string","examples":["2019-05-03 15:16:51"]},"links":{"type":"object","properties":{"accountCustomFieldData":{"type":"string","examples":["https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData"]}}}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_account_custom_fields","title":"List Account Custom Fields","description":"Every custom field defined on CRM company accounts: the company account fields, each with its type and label.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/accountCustomFieldMeta/bulkDelete":{"delete":{"summary":"Delete many account custom fields","description":"Deletes several account custom fields in one call. Send a JSON list of field ids. Hosted sends the body to the service as it was decoded: a list stays a list, an empty JSON object is sent as an empty list, an object with keys 0, 1 and so on as a list, any other object as the same object, and a single value is sent as a list of one. An empty body, or one that is not valid JSON, is sent as an empty list. Needs the permission to manage account fields. Hosted sends the request to the custom fields service and returns the service's status code and body. When the service answers 403, 404 or 409, Hosted returns its own error with the same status. When it answers 422, Hosted rewrites the service's errors. Any other verb on this path returns 405. Internal: not part of the public API.","operationId":"bulk-delete-account-custom-fields","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"array","description":"Ids of the fields to delete.","items":{"type":["integer","string"]}},"example":["2","3"]}}},"responses":{"200":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkResult"},"403":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkForbidden"},"404":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkNotFound"},"405":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkMethodNotAllowed"},"409":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkConflict"},"422":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkInvalid"}}}},"/accountCustomFieldMeta/bulkUpdate":{"patch":{"summary":"Update many account custom fields","description":"Updates several account custom fields in one call. Send a JSON list with one object per field. The objects are not wrapped in accountCustomFieldMetum. Hosted turns each key into snake_case, so fieldLabel and field_label both reach the service as field_label. Keys with a null value are dropped. All other values are sent as they are. Unlike PUT /accountCustomFieldMeta/{id}, Hosted does not check the personalization tag, the default of a required field or the lookup fields flag. It also does not set updated_by. An empty body, or one that is not valid JSON, is sent as an empty list. Needs the permission to manage account fields. Hosted sends the request to the custom fields service and returns the service's status code and body. When the service answers 403, 404 or 409, Hosted returns its own error with the same status. When it answers 422, Hosted rewrites the service's errors. Any other verb on this path returns 405. Internal: not part of the public API.","operationId":"bulk-update-account-custom-fields","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountCustomFieldMetaBulkUpdateItem"}},"example":[{"id":"2","fieldLabel":"Region","displayOrder":1},{"id":"3","fieldLabel":"Plan","fieldOptions":["Basic","Plus"]}]}}},"responses":{"200":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkResult"},"403":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkForbidden"},"404":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkNotFound"},"405":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkMethodNotAllowed"},"409":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkConflict"},"422":{"$ref":"#/components/responses/AccountCustomFieldMetaBulkInvalid"}}}},"/accountCustomFieldMeta/{id}":{"get":{"summary":"Retrieve an account custom field","description":"","operationId":"retrieve-a-custom-field-meta","x-canonical-resource":"custom_field_definition","parameters":[{"name":"id","in":"path","description":"ID of the field to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"New Title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 1,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 20:04:21\",\n        \"links\": {\n            \"accountCustomFieldData\": \"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"fieldLabel":{"type":"string","example":"New Title"},"fieldType":{"type":"string","example":"text"},"fieldOptions":{},"fieldDefault":{"type":"string","example":"Default Text"},"isFormVisible":{"type":"integer","example":1,"default":0},"isRequired":{"type":"integer","example":1,"default":0},"displayOrder":{"type":"integer","example":1,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-22 19:57:37"},"updatedTimestamp":{"type":"string","example":"2018-10-22 20:04:21"},"links":{"type":"object","properties":{"accountCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"put":{"summary":"Update an account custom field","description":"","operationId":"update-a-custom-field","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom field to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"accountCustomFieldMetum":{"properties":{"fieldLabel":{"type":"string","description":"Name of the field"},"fieldOptions":{"type":"array","description":"Options for the field. Only necessary if field_type is dropdown, multiselect, radio, or checkbox.","items":{"type":"string"}},"fieldDefault":{"type":"string","description":"Default value of the field"},"isFormVisible":{"type":"boolean","description":"Whether or not the field is visible on forms"},"displayOrder":{"type":"integer","description":"Order for displaying the field on Manage Fields page and deal profiles","format":"int32"},"isRequired":{"type":"boolean","description":"When true, fieldDefault is required."},"personalization":{"type":"string","minLength":1},"fieldType":{"type":"string"}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"accountCustomFieldMetum":{"fieldLabel":"New Title","fieldDefault":"Default Text","isFormVisible":1,"displayOrder":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"New Title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 1,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 20:04:21\",\n        \"links\": {\n            \"accountCustomFieldData\": \"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"accountCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"fieldLabel":{"type":"string","example":"New Title"},"fieldType":{"type":"string","example":"text"},"fieldOptions":{},"fieldDefault":{"type":"string","example":"Default Text"},"isFormVisible":{"type":"integer","example":1,"default":0},"isRequired":{"type":"integer","example":1,"default":0},"displayOrder":{"type":"integer","example":1,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-22 19:57:37"},"updatedTimestamp":{"type":"string","example":"2018-10-22 20:04:21"},"links":{"type":"object","properties":{"accountCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/:version/accountCustomFieldMeta/1/accountCustomFieldData"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete an account custom field","description":"","operationId":"delete-a-custom-field","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the field to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"AccountCustomFieldMeta deleted.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"AccountCustomFieldMeta deleted."}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false}},"/accountOpenTrends":{"get":{"summary":"Retrieve the account's campaign open trend","description":"Unique campaign opens over a date range, grouped by hour of the day, day of the week or day of the month, with each bucket's share of the total and the bar height the open trend report draws. Counts distinct contacts per bucket, from campaign opens only (automation and other message opens are left out). A user other than the primary admin only sees opens of campaigns sent to their own lists. Internal: backs the open trend report in the app.","operationId":"retrieve-account-open-trends","parameters":[{"name":"type","in":"query","description":"How opens are grouped: hour (hour of the day, 24 rows), week (day of the week, 7 rows, Monday first) or month (day of the month, 32 rows from 0 to 31; row 0 is always empty). Hours and days are in the calling user's time zone.","schema":{"type":"string","default":"hour","enum":["hour","week","month"]},"example":"week"},{"name":"listId","in":"query","description":"Only count opens of campaigns sent to this list. Ignored when the calling user is not the primary admin and the list is not one of theirs. A user other than the primary admin only ever sees opens of campaigns sent to their own lists.","schema":{"type":"integer"},"example":3},{"name":"tagId","in":"query","description":"Only count opens by contacts who carry this tag.","schema":{"type":"integer"},"example":7},{"name":"from","in":"query","description":"First day of the range, as Y-m-d. The range is used only when both from and to are sent; otherwise it is the last 30 days, today included.","schema":{"type":"string"},"example":"2026-09-01"},{"name":"to","in":"query","description":"Last day of the range, as Y-m-d, included. Must be later than from.","schema":{"type":"string"},"example":"2026-09-30"},{"name":"includeMpp","in":"query","description":"Send 1 to add opens recorded through Apple Mail Privacy Protection to the hour and week groupings. The month grouping never includes them.","schema":{"type":"integer","default":0,"enum":[0,1]},"example":0}],"responses":{"200":{"description":"One row per bucket, in bucket order, even when a bucket has no opens.","content":{"application/json":{"schema":{"required":["paginator","cnt","rows","max","total","total_sent_amount"],"properties":{"paginator":{"description":"Always 1. A pass-through value the legacy report screen used to tell its sections apart.","type":"integer","example":1},"cnt":{"description":"Number of rows: 24 for hour, 7 for week, 32 for month.","type":"integer","example":7},"rows":{"description":"The buckets, in order: hours 0 to 23, Monday to Sunday, or days 0 to 31.","type":"array","items":{"required":["hits","label","hitsratio","hitsratio4bar","total"],"properties":{"hits":{"description":"Unique contacts who opened in this bucket. A string of digits when the bucket has opens and the number 0 when it has none; always a number for month.","type":["string","integer"],"example":"120"},"label":{"description":"The bucket: the hour in 24- and 12-hour form for hour (such as \"09 (9AM)\"), the day name in the user's language for week (such as \"Monday\"), or the day of the month as a number for month.","type":["string","integer"],"example":"Monday"},"hitsratio":{"description":"This bucket's share of total, as a percentage rounded to two decimals; 0 when total is 0.","type":"number","example":17.14},"hitsratio4bar":{"description":"hitsratio scaled against a rounded-up maximum, as a percentage rounded to two decimals: the bar height the report draws for this bucket.","type":"number","example":57.13},"total":{"description":"The total across all buckets, repeated on every row.","type":"integer","example":700}},"type":"object"}},"max":{"description":"The largest bucket's share of total, as a percentage rounded to two decimals; the report's axis scaling multiplies a share under 1 by 100. 0 when there are no opens.","type":"number","example":20.57},"total":{"description":"Unique opens across all buckets: the sum of hits.","type":"integer","example":700},"total_sent_amount":{"description":"For month, the number of campaign emails sent, summed over sent campaigns whose send date falls in the range; the report uses it for its 10% threshold. The figure is cached for 24 hours per account whatever range is asked for. -1 for hour and week.","type":"integer","example":-1}},"type":"object"},"example":{"paginator":1,"cnt":7,"rows":[{"hits":"120","label":"Monday","hitsratio":17.14,"hitsratio4bar":57.13,"total":700},{"hits":"144","label":"Tuesday","hitsratio":20.57,"hitsratio4bar":68.57,"total":700}],"max":20.57,"total":700,"total_sent_amount":-1}}}},"422":{"description":"A query parameter fails validation: type is not hour, week or month, listId or tagId is not a positive whole number, from or to is not a Y-m-d date, or to is not later than from. One error per failed check.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed check.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"The validator's message for the failed check.","type":"string","example":"The value you selected is not a valid choice."},"source":{"description":"The query parameter that failed.","properties":{"pointer":{"description":"The parameter, as /data/attributes/<name>.","type":"string","example":"/data/attributes/type"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"An unexpected error while building the report. A failing open-count query does not answer 500: it is logged and its buckets come back as 0.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Failed to fetch open trend data\".","type":"string","example":"Failed to fetch open trend data"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/accounts":{"post":{"summary":"Create an account","description":"Create a new account","operationId":"create-an-account-new","x-canonical-resource":"crm_account","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"account":{"properties":{"name":{"type":"string","description":"Account's name"},"accountUrl":{"type":"string","description":"Account's website"},"owner":{"type":"integer","description":"The userId of the account owner.","default":1,"format":"int32"},"fields":{"type":"array","description":"Account's custom field values `{customFieldId: int, fieldValue: string, fieldCurrency?:string}[]`","items":{"properties":{"customFieldId":{"type":"integer","description":"Field ID, ID of the Custom Field Meta Data","format":"int32"},"fieldValue":{"type":"string","description":"Updated field value. For `currency` field, this needs to be in cents not dollars (or 100 x Base Unit)."},"fieldCurrency":{"type":"string","description":"Required only for the `currency` field type. The three letter currency code for the currency value"}},"required":["customFieldId","fieldValue"],"type":"object"}},"matchingEnabled":{"type":["integer","boolean"]}},"required":["name"],"type":"object"},"useDefaults":{"type":"boolean","description":"Read but has no effect."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"account":{"name":"Example Account","accountUrl":"https://www.example.com","owner":1,"fields":[{"customFieldId":9,"fieldValue":"500-1000"},{"customFieldId":20,"fieldValue":1234,"fieldCurrency":"GBP"}]}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"account\": {\n        \"name\": \"Example Account\",\n        \"accountUrl\": \"https://www.example.com\",\n        \"createdTimestamp\": \"2019-06-12T16:52:16-05:00\",\n        \"updatedTimestamp\": \"2019-06-12T16:52:16-05:00\",\n        \"links\": [],\n        \"fields\": [\n            {\n                \"customFieldId\": 9,\n                \"fieldValue\": \"501 - 1000\",\n                \"accountId\": \"1\"\n            },\n            {\n                \"customFieldId\": 20,\n                \"fieldValue\": 1234,\n        \t\t\t\t\"fieldCurrency\": \"GBP\",\n                \"accountId\": \"1\"\n            }\n        ],\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"account":{"type":"object","properties":{"name":{"type":"string","examples":["Example Account"]},"accountUrl":{"type":"string","examples":["https://www.example.com"]},"createdTimestamp":{"type":"string","examples":["2019-06-12T16:52:16-05:00"]},"updatedTimestamp":{"type":"string","examples":["2019-06-12T16:52:16-05:00"]},"links":{"type":"array"},"fields":{"type":"array","items":{"type":"object","properties":{"customFieldId":{"type":"integer","default":0,"examples":[9]},"fieldValue":{"type":"string","examples":["501 - 1000"]},"accountId":{"type":"string","examples":["1"]}}}},"id":{"type":"string","examples":["1"]}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Missing Data":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The account name was not provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/name\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The account name was not provided."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/name"}}}}}}}}},"text/plain":{"examples":{"Already Existing":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"An account named \\\"Example Account\\\" already exists. Please choose a new name.\",\n            \"detail\": \"\",\n            \"code\": \"duplicate\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/name\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"An account named \"Example Account\" already exists. Please choose a new name."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"duplicate"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/name"}}}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"create_account","title":"Create Account","description":"Create a CRM account (company) with a name, and optionally a website URL, an owner user id and account custom field values. Check list_accounts first so the same company is not created twice.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List all accounts","description":"Retrieve all existing account","operationId":"list-all-accounts","x-canonical-resource":"crm_account","parameters":[{"name":"search","in":"query","description":"Search by name","schema":{"type":"string"}},{"name":"count_deals","in":"query","description":"Whether to compute the contactCount and dealCount counts for the number of contacts/deals associated with each account. Set it to true to include the right counts. If set to false or omitted from the call, then contactCount and dealCount will not be counted and be simply displayed as 0.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"accountUrl":{"type":["string","null"]},"owner":{"type":["string","null"]},"contactCount":{"type":"string"},"dealCount":{"type":"string"},"createdTimestamp":{"type":"string"},"updatedTimestamp":{"type":"string"}}}},"meta":{"type":"object","properties":{"total":{"type":"string"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_accounts","title":"List Accounts","description":"List CRM accounts (companies), optionally narrowed by a name search. Use it to find an account_id when the user names a company, before get_account, update_account or link_contact_to_account. Set count_deals to true to include each account's deal count.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/accounts/activity":{"get":{"summary":"List an account's activity","description":"Internal: backs the activity stream on an account's page in the app. Hosted reads the account's feed from the activity feed service, then fills in the records each activity refers to (`actor`, `object`, `origin`, `target`) with their current details. An activity that refers to a record that no longer exists, or that the signed-in user may not see, is left out; a user reference is kept either way. The account ID is passed to the feed service as given: it is not checked against the CRM accounts, and no Accounts entitlement or permission is checked. Follow `meta.nextPage` to read the next page. Only GET is answered; any other method gets 405 with an empty body.","operationId":"list-account-activities","x-canonical-resource":"crm_account","parameters":[{"name":"id","in":"query","description":"ID of the account whose activity to list","required":true,"schema":{"type":"integer"},"example":21},{"name":"after","in":"query","description":"The `eventKey` of the last activity already read; the page starts after it. `meta.nextPage` carries it.","required":false,"schema":{"type":"string"},"example":"1423580695-OHXnUakk"},{"name":"category","in":"query","description":"Only activities of this category; passed to the activity feed service as given","required":false,"schema":{"type":"string"},"example":"task"}],"responses":{"200":{"description":"One page of the account's activity","content":{"application/json":{"schema":{"type":"object","properties":{"activities":{"type":"array","description":"The activities on this page","items":{"$ref":"#/components/schemas/CustomerAccountActivity"}},"meta":{"type":"object","description":"Paging information; other properties the feed service returns are passed through","properties":{"nextPage":{"type":["string","null"],"description":"Path of the next page, `/api/3/accounts/activity?id=<id>&after=<eventKey>` (with `category` when one was given), built from the last activity the feed service returned. Null once a page comes back empty.","example":"/api/3/accounts/activity?id=21&after=1423580695-OHXnUakk"}}}}},"example":{"activities":[{"feed":"urn:ac-hosted:customer-account:12345/19","eventKey":"1423580695-OHXnUakk","action":"updated","category":"task","published":"2015-02-10T15:04:55Z","accountId":"12345","actor":{"urn":"urn:ac-hosted:user:12345/2","id":"2","type":"user","firstName":"Stan","lastName":"Stanley","username":"sstanley"},"object":{"urn":"urn:ac-hosted:task:12345/12","id":"12","type":"task","title":"Test Contact Task","typeTitle":"Call","outcomeTitle":"good","outcomeInfo":"Info for Contact Task"},"target":{"urn":"urn:ac-hosted:contact:12345/23","id":"23","type":"contact","firstName":"Phil","lastName":"Phillips","email":"pphillips@example.com"},"summary":"Task was completed for contact 23","context":[]}],"meta":{"nextPage":"/api/3/accounts/activity?id=21&after=1423580695-OHXnUakk"}}}}},"405":{"description":"The request did not use GET. The body is empty."},"422":{"description":"The `id` query parameter is missing","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What is wrong","example":"id must be provided"}}}}}},"500":{"description":"The activity feed service could not be reached or answered with an error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong","example":"Unable to retrieve Activity"}}}}}}},"deprecated":false,"x-internal":true}},"/accounts/bulkUpdate":{"patch":{"summary":"Bulk update accounts","description":"Internal: backs bulk edit on the Accounts list in the app. Applies the same actions to up to 100 accounts. The actions are first applied to a stand-in account and validated, so a URL that is not a URL or an owner who is not a user fails the whole request with 422 before any account changes. Then each account is saved in turn through the same code as PUT /accounts/{id}, entitlement and edit-accounts permission check included; an account that cannot be saved (it does not exist, the user may not edit it, it fails validation) is listed in `failed` and the rest are still saved. With `validationOnly` the request stops after validation. Only PATCH is routed; other methods get 405.","operationId":"bulk-update-accounts","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountIds","actions"],"properties":{"accountIds":{"type":"array","description":"IDs of the accounts to update; at least 1 and at most 100","minItems":1,"maxItems":100,"items":{"type":["integer","string"]},"example":[1,2]},"actions":{"type":"array","description":"The changes to apply to every account, in order; at least one","minItems":1,"items":{"type":"object","required":["action","payload"],"properties":{"action":{"type":"string","enum":["update-url","update-owner","update-custom-field"],"description":"Which change: `update-url` sets the website URL from `payload.url`; `update-owner` sets the owner from `payload.userid`; `update-custom-field` sets custom field `payload.fieldId` to `payload.value`, with `payload.currency` for a currency field"},"payload":{"type":"object","description":"The values the action reads; each action requires its own properties and refuses the request without them","properties":{"url":{"type":"string","description":"New website URL; required by `update-url`","example":"https://www.example.com"},"userid":{"type":["integer","string"],"description":"ID of the new owner; required by `update-owner`","example":3},"fieldId":{"type":["integer","string"],"description":"ID of the account custom field; required by `update-custom-field`","example":9},"value":{"type":["string","number"],"description":"New value of the custom field; required by `update-custom-field`. For a currency field, the amount in the smallest unit of the currency (cents).","example":"500-1000"},"currency":{"type":"string","description":"Three-letter currency code; read by `update-custom-field` for currency fields","example":"USD"}}}}}},"validationOnly":{"type":"boolean","description":"When true, validate the actions and answer without updating any account","default":false}}},"example":{"accountIds":[1,2],"actions":[{"action":"update-owner","payload":{"userid":3}},{"action":"update-custom-field","payload":{"fieldId":9,"value":"500-1000"}}]}}}},"responses":{"200":{"description":"The actions were applied, or only validated when `validationOnly` was sent","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"array","description":"IDs of the accounts that were saved, as sent; empty after `validationOnly`","items":{"type":["integer","string"]}},"failed":{"type":"array","description":"IDs of the accounts that could not be saved, as sent","items":{"type":["integer","string"]}},"validation":{"type":["boolean","null"],"description":"True when only validation ran; null otherwise"}}},"example":{"success":[1],"failed":[2],"validation":null}}}},"405":{"description":"The request did not use PATCH"},"422":{"description":"The request was refused before any account changed: `accountIds` is missing, empty or longer than 100, `actions` is missing or empty, an action lacks its `payload` or a property it requires, or the actions failed validation (`url` is not a URL, `userid` is not a user). Malformed requests answer `{\"errors\": [{\"status\": 422, \"title\": ..., \"detail\": ...}]}`; a validation failure answers `{\"errors\": [...]}` with one entry per problem.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"What is wrong","items":{"type":"object"}}}}}}}},"deprecated":false,"x-internal":true}},"/accounts/bulk_delete":{"delete":{"summary":"Bulk delete accounts","description":"Delete an existing account","operationId":"bulk-delete-accounts","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"[]ids","in":"query","description":"An integer id of the account to be deleted","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"meta\": {\n        \"success\": true\n    }\n}"}},"schema":{"type":"object","properties":{"meta":{"type":"object","properties":{"success":{"type":"boolean","example":true,"default":true}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"post":{"summary":"Bulk delete accounts with POST","description":"Internal: the verb the app sends from the Accounts list; the same script answers DELETE /accounts/bulk_delete. Deletes the given accounts immediately and, when contacts belonged to them, queues a background process that clears the account from those contacts. Every ID must exist, or nothing is deleted. The IDs are read from the form body, as the app sends them, or from the query string. Needs the Accounts feature and the delete-accounts permission.","operationId":"bulk-delete-accounts-via-post","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["ids[]"],"properties":{"ids[]":{"type":"array","description":"IDs of the accounts to delete, as repeated `ids[]` keys","items":{"type":"integer"},"example":[1,2]}}}}}},"responses":{"200":{"description":"The accounts were deleted","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","description":"Outcome of the request","properties":{"success":{"type":"boolean","description":"Always true on a 200","example":true}}}}},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the Accounts feature, or the user may not delete accounts","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["integer","string"],"description":"HTTP status code of the error"},"title":{"type":"string","description":"Name of the HTTP status, when the error carries one"},"detail":{"type":"string","description":"What went wrong, when the error carries a message"}}}}}}}}},"422":{"description":"Nothing was deleted: no `ids` were sent, some of the IDs are not accounts (the message lists them), or the process that clears the account from contacts could not be queued. The body is a plain-text message.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/accounts/getDefaultAccountOwner":{"get":{"summary":"Retrieve the default account owner","description":"Internal: read by the app's delete-users flow to find out whether a user being deleted is the default account owner. Returns the account-wide default owner setting: the user an account is given when it has no valid owner (user 1 when the setting is empty). No permission is checked. Only GET is answered; any other method gets 200 with an empty body.","operationId":"retrieve-default-account-owner","x-canonical-resource":"crm_account","responses":{"200":{"description":"The setting","content":{"application/json":{"schema":{"type":"object","properties":{"val":{"type":"string","description":"ID of the default account owner, as stored; an empty string when none has been set","example":"3"}}},"example":{"val":"3"}}}}},"deprecated":false,"x-internal":true}},"/accounts/reassign_multiple":{"post":{"summary":"Reassign accounts to another user","description":"Internal: called by the app's delete-users flow to hand the accounts owned by the users being deleted to another user. Queues a background process that makes `toUser` the owner of every account owned by one of `fromUsers`; the answer comes before the accounts change. The parameters are read from the form body, as the app sends them, or from the query string. Needs the Accounts feature; no other permission is checked. Legacy endpoint with no method guard: any HTTP method is answered the same way; POST is the documented verb and the one the app sends.","operationId":"reassign-accounts-to-user","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["fromUsers[]","toUser"],"properties":{"fromUsers[]":{"type":"array","description":"IDs of the users whose accounts to reassign, as repeated `fromUsers[]` keys; a single `fromUsers` value is also accepted","items":{"type":"integer"},"example":[4,5]},"toUser":{"type":"integer","description":"ID of the user who becomes the owner","example":3}}}}}},"responses":{"200":{"description":"The reassignment was queued","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","description":"Outcome of the request","properties":{"success":{"type":"boolean","description":"Always true on a 200","example":true}}}}},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the Accounts feature. The body is `{\"errors\": [{\"status\": \"403\", \"detail\": \"Upgrade your account to enable the Accounts Feature\"}]}`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["integer","string"],"description":"HTTP status code of the error"},"title":{"type":"string","description":"Name of the HTTP status, when the error carries one"},"detail":{"type":"string","description":"What went wrong, when the error carries a message"}}}}}}}}},"422":{"description":"`toUser` is missing or is not a user, or the reassignment process could not be queued. The body is a plain-text message.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/accounts/setDefaultAccountOwner":{"put":{"summary":"Set the default account owner","description":"Internal: called by the app's delete-users flow when the user being deleted is the default account owner. Stores the user in `val` as the account-wide default owner, the user an account is given when it has no valid owner, after deleting any per-user copies of the setting. No permission is checked. Only PUT is answered; any other method gets 200 with an empty body.","operationId":"update-default-account-owner","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"val","in":"query","description":"ID of the user to make the default account owner","required":true,"schema":{"type":"integer"},"example":3}],"responses":{"200":{"description":"The setting was saved","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true on a 200","example":true}}},"example":{"success":true}}}},"404":{"description":"No user with the ID in `val`","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found","example":"No Result found for User with id 99"}}}}}},"422":{"description":"`val` is missing, zero or not a number. The body is `{\"errors\": [{\"status\": \"422\", \"detail\": \"Invalid user id was provided.\"}]}`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["integer","string"],"description":"HTTP status code of the error"},"title":{"type":"string","description":"Name of the HTTP status, when the error carries one"},"detail":{"type":"string","description":"What went wrong, when the error carries a message"}}}}}}}}}},"deprecated":false,"x-internal":true}},"/accounts/{id}":{"put":{"summary":"Update an account","description":"Update an existing account","operationId":"update-an-account-new","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Account's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"account":{"properties":{"name":{"type":"string","description":"Account's name"},"accountUrl":{"type":"string","description":"Account's website"},"fields":{"type":"array","description":"Account's custom field values `{customFieldId: int, fieldValue: string, fieldCurrency?:string}[]`","items":{"properties":{"customFieldId":{"type":"integer","description":"Field ID, ID of the Custom Field Meta Data","format":"int32"},"fieldValue":{"type":"string","description":"Updated field value. For `currency` field, this needs to be in cents not dollars (or 100 x Base Unit)."},"fieldCurrency":{"type":"string","description":"Required only for the `currency` field type. The three letter currency code for the currency value"}},"required":["customFieldId","fieldValue"],"type":"object"}},"owner":{"type":"integer","description":"The userId of the Account owner.","default":1,"format":"int32"},"matchingEnabled":{"type":["integer","boolean"]}},"required":[],"type":"object"},"useDefaults":{"type":"boolean","description":"Read but has no effect."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"account":{"name":"Example Account","accountUrl":"https://www.example.com","fields":[{"customFieldId":9,"fieldValue":"500-1000"},{"customFieldId":20,"fieldValue":1234,"fieldCurrency":"GBP"}]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"account\": {\n        \"name\": \"Example Account\",\n        \"accountUrl\": \"https://www.example.com\",\n        \"createdTimestamp\": \"2019-04-03T13:57:31-05:00\",\n        \"updatedTimestamp\": \"2019-06-12T16:55:32-05:00\",\n        \"links\": [],\n        \"fields\": [\n            {\n                \"customFieldId\": 9,\n                \"fieldValue\": \"501 - 1000\",\n                \"accountId\": \"1\"\n            },\n            {\n                \"customFieldId\": 20,\n                \"fieldValue\": 1234,\n              \t\"fieldCurrency\": \"GBP\",\n                \"accountId\": \"1\"\n            }\n        ],\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"account":{"type":"object","properties":{"name":{"type":"string","examples":["Example Account"]},"accountUrl":{"type":"string","examples":["https://www.example.com"]},"createdTimestamp":{"type":"string","examples":["2019-04-03T13:57:31-05:00"]},"updatedTimestamp":{"type":"string","examples":["2019-06-12T16:55:32-05:00"]},"links":{"type":"array"},"fields":{"type":"array","items":{"type":"object","properties":{"customFieldId":{"type":"integer","default":0,"examples":[9]},"fieldValue":{"type":"string","examples":["501 - 1000"]},"accountId":{"type":"string","examples":["1"]}}}},"id":{"type":"string","examples":["1"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"update_account","title":"Update Account","description":"Change an existing CRM account's name, website URL, owner or account custom field values. Only the fields you send change.","annotations":{"readOnlyHint":false,"idempotentHint":true,"openWorldHint":false}}},"get":{"summary":"Retrieve an account","description":"Retrieve an existing account","operationId":"retrieve-an-account","x-canonical-resource":"crm_account","parameters":[{"name":"id","in":"path","description":"Account's ID","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"account\": {\n        \"name\": \"Example Account\",\n        \"accountUrl\": \"https://www.example.com\",\n        \"owner\": \"1\",\n        \"createdTimestamp\": \"2019-05-15T15:58:16-05:00\",\n        \"updatedTimestamp\": \"2019-05-15T15:58:16-05:00\",\n        \"links\": [],\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"account":{"type":"object","properties":{"name":{"type":"string","examples":["Example Account"]},"accountUrl":{"type":["string","null"],"examples":["https://www.example.com"]},"owner":{"type":["string","null"],"examples":["1"]},"createdTimestamp":{"type":"string","examples":["2019-05-15T15:58:16-05:00"]},"updatedTimestamp":{"type":"string","examples":["2019-05-15T15:58:16-05:00"]},"links":{"type":"array"},"id":{"type":"string","examples":["1"]}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"get_account","title":"Get Account","description":"Get one CRM account by its id: name, website URL, owner and timestamps. Find the id with list_accounts when the user names the company.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}},"delete":{"summary":"Delete an account","description":"Delete an existing account","operationId":"delete-an-account","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Account's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"patch":{"summary":"Update an account with PATCH","description":"Internal: the whitelist routes PATCH to the same action as PUT /accounts/{id}, so the body and every answer are the same; the app sends PUT. Only the properties sent in `account` change; the others keep their stored values. Custom field values in `account.fields` are saved after the account, and a failure there does not fail the request: it is reported in `account.customFieldSaveStatus` of a 200. Needs the Accounts feature and the edit-accounts permission; changing `accountUrl` on an account with domain matching on needs an admin.","operationId":"patch-an-account","parameters":[{"name":"id","in":"path","description":"ID of the account to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["account"],"properties":{"account":{"description":"The properties to change","properties":{"name":{"description":"Name of the account. Must stay non-blank and unique across the account's CRM accounts; 4-byte characters such as emoji are removed before saving.","type":"string","example":"Example Account"},"accountUrl":{"description":"Website URL of the account; refused when it is not a URL","type":"string","example":"https://www.example.com"},"owner":{"description":"ID of the user who owns the account; refused when no such user exists","type":["integer","string"],"example":1},"matchingEnabled":{"description":"Whether contacts are matched to this account by the domain of `accountUrl`: 1 on, 0 off","type":["integer","boolean"],"example":1},"fields":{"description":"Custom field values to save on the account","type":"array","items":{"required":["customFieldId","fieldValue"],"properties":{"customFieldId":{"description":"ID of the account custom field (accountCustomFieldMeta)","type":"integer","example":9},"fieldValue":{"description":"The value. For a currency field, the amount in the smallest unit of the currency (cents).","type":["string","number"],"example":"500-1000"},"fieldCurrency":{"description":"Three-letter currency code; for currency fields only","type":"string","example":"USD"}},"type":"object"}}},"type":"object"},"useDefaults":{"description":"Read by the action and passed to validation, which ignores it today; sending it changes nothing","type":"boolean","example":false}},"type":"object"}}}},"responses":{"200":{"description":"The account as saved","content":{"application/json":{"schema":{"properties":{"account":{"description":"The account after the update","properties":{"id":{"description":"ID of the account","type":["string","integer"],"example":"1"},"name":{"description":"Name of the account","type":"string","example":"Example Account"},"accountUrl":{"description":"Website URL of the account","type":["string","null"],"example":"https://www.example.com"},"owner":{"description":"ID of the user who owns the account","type":["string","integer"],"example":"1"},"matchingEnabled":{"description":"Whether domain matching is on for the account; null when it was never set","type":["string","integer","boolean","null"],"example":"0"},"createdTimestamp":{"description":"When the account was created, ISO 8601 with offset","type":"string","example":"2019-04-03T13:57:31-05:00"},"updatedTimestamp":{"description":"When the account was last updated, ISO 8601 with offset","type":"string","example":"2019-06-12T16:55:32-05:00"},"fields":{"description":"The custom field values sent in the request, each with the account ID added; empty when none were sent","type":"array","items":{"properties":{"customFieldId":{"description":"ID of the account custom field","type":"integer","example":9},"fieldValue":{"description":"The value as sent","type":["string","number"],"example":"500-1000"},"fieldCurrency":{"description":"Currency code, when one was sent","type":"string","example":"USD"},"accountId":{"description":"ID of the account the value belongs to","type":["string","integer"],"example":"1"}},"type":"object"}},"customFieldSaveStatus":{"description":"Outcome of saving `fields`","properties":{"status":{"description":"success, or failed when the custom field values could not be saved","type":"string","enum":["success","failed"],"example":"success"},"error":{"description":"Why the values were not saved; only when status is failed","type":"string","example":"Unable to save custom fields"},"details":{"description":"Details of the failure; only when status is failed","properties":{"status":{"description":"HTTP status the custom field save failed with","type":"integer","example":422}},"type":["object","null"]}},"type":"object"},"links":{"description":"URLs of the account's related resources (notes, accountCustomFieldData, accountContacts, emailActivities, contactEmails, owner)","type":"object","additionalProperties":{"type":"string"}}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is not a JSON object, or has no `account` object"},"403":{"description":"The account does not have the Accounts feature, the user may not edit accounts, or a user who is not an admin tried to change `accountUrl` while domain matching is on"},"404":{"description":"No account with this ID"},"422":{"description":"The account failed validation: the name is blank or already used by another account, `accountUrl` is not a URL, or `owner` is not a user. The body is `{\"errors\": [...]}` with one entry per problem, each carrying title, detail, code, error and source.pointer.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per validation problem","type":"array","items":{"properties":{"title":{"description":"Human-readable summary of the problem","type":"string"},"detail":{"description":"Further detail; often empty","type":"string"},"code":{"description":"Machine-readable error code","type":"string","example":"field_missing"},"error":{"description":"Machine-readable error key","type":"string"},"source":{"description":"Where the problem is","properties":{"pointer":{"description":"JSON pointer to the offending attribute","type":"string","example":"/data/attributes/name"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/accounts/{id}/notes":{"post":{"summary":"Create an account note","description":"Create a new note for an account","operationId":"create-an-account-note","x-canonical-resource":"crm_account","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Account's id to assign new note to","schema":{"type":"integer"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"Account note's content"},"is_draft":{"type":"integer","description":"0 or 1. 1 marks the note as a draft, 0 as fully created."}},"required":["note"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"note":{"note":"Note for the account"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"accounts\": [\n    {\n      \"name\": \"Museum of Science and Industry\",\n      \"accountUrl\": \"www.msi.com\",\n      \"createdTimestamp\": \"2019-04-03T13:29:35-05:00\",\n      \"updatedTimestamp\": \"2019-06-12T16:59:54-05:00\",\n      \"id\": \"1\"\n    }\n  ],\n  \"note\": {\n    \"cdate\": \"2017-05-31T09:54:30-05:00\",\n    \"id\": \"2\",\n    \"links\": {\n      \"activities\": \"https://:account.api-us1.com/api/3/notes/2/activities\",\n      \"mentions\": \"https://:account.api-us1.com/api/3/notes/2/mentions\",\n      \"notes\": \"https://:account.api-us1.com/api/3/notes/2/notes\",\n      \"owner\": \"https://:account.api-us1.com/api/3/notes/2/owner\",\n      \"user\": \"https://:account.api-us1.com/api/3/notes/2/user\"\n    },\n    \"mdate\": \"2017-05-31T09:54:30-05:00\",\n    \"note\": \"Note for the account\",\n    \"owner\": {\n      \"id\": \"1\",\n      \"type\": \"account\"\n    },\n    \"relid\": \"1\",\n    \"reltype\": \"CustomerAccount\",\n    \"user\": \"1\",\n    \"userid\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","examples":["Museum of Science and Industry"]},"accountUrl":{"type":"string","examples":["www.msi.com"]},"createdTimestamp":{"type":"string","examples":["2019-04-03T13:29:35-05:00"]},"updatedTimestamp":{"type":"string","examples":["2019-06-12T16:59:54-05:00"]},"id":{"type":"string","examples":["1"]}}}},"note":{"type":"object","properties":{"cdate":{"type":"string","examples":["2017-05-31T09:54:30-05:00"]},"id":{"type":"string","examples":["2"]},"links":{"type":"object","properties":{"activities":{"type":"string","examples":["https://:account.api-us1.com/api/3/notes/2/activities"]},"mentions":{"type":"string","examples":["https://:account.api-us1.com/api/3/notes/2/mentions"]},"notes":{"type":"string","examples":["https://:account.api-us1.com/api/3/notes/2/notes"]},"owner":{"type":"string","examples":["https://:account.api-us1.com/api/3/notes/2/owner"]},"user":{"type":"string","examples":["https://:account.api-us1.com/api/3/notes/2/user"]}}},"mdate":{"type":"string","examples":["2017-05-31T09:54:30-05:00"]},"note":{"type":"string","examples":["Note for the account"]},"owner":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"type":{"type":"string","examples":["account"]}}},"relid":{"type":"string","examples":["1"]},"reltype":{"type":"string","examples":["CustomerAccount"]},"user":{"type":"string","examples":["1"]},"userid":{"type":"string","examples":["1"]}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"create_account_note","title":"Add Account Note","description":"Add a note to a CRM account, for example a summary of a call or meeting with that company. The note saves to the account record, in its Notes box.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}}},"/accounts/{id}/notes/{noteId}":{"put":{"summary":"Update an account note","description":"Update an existing note for a account","operationId":"update-a-account-note","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Account's id to assign new note to","schema":{"type":"integer"},"required":true},{"name":"noteId","in":"path","description":"Account note's id to update","schema":{"type":"integer"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"Account note's content"},"is_draft":{"type":"integer","description":"0 or 1. 1 marks the note as a draft, 0 as fully created."}},"required":["note"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"note":{"note":"Update with more info"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"accounts\": [\n    {\n      \"name\": \"Example Account\",\n      \"accountUrl\": \"https://www.example.url\",\n      \"createdTimestamp\": \"2019-04-03T13:29:35-05:00\",\n      \"updatedTimestamp\": \"2019-06-12T16:59:54-05:00\",\n      \"links\": {\n        \"notes\": \"https://:account.api-us1.com/api/3/accounts/1/notes\"\n      },\n      \"id\": \"1\"\n    }\n  ],\n  \"note\": {\n    \"cdate\": \"2017-06-01T13:42:13-05:00\",\n    \"id\": \"2\",\n    \"links\": {\n      \"activities\": \"https://:account.api-us1.com/api/3/notes/2/activities\",\n      \"mentions\": \"https://:account.api-us1.com/api/3/notes/2/mentions\",\n      \"notes\": \"https://:account.api-us1.com/api/3/notes/2/notes\",\n      \"owner\": \"https://:account.api-us1.com/api/3/notes/2/owner\",\n      \"user\": \"https://:account.api-us1.com/api/3/notes/2/user\"\n    },\n    \"mdate\": \"2017-06-01T13:42:13-05:00\",\n    \"note\": \"Update with more info\",\n    \"owner\": {\n      \"id\": \"1\",\n      \"type\": \"account\"\n    },\n    \"relid\": \"1\",\n    \"reltype\": \"CustomerAccount\",\n    \"user\": \"1\",\n    \"userid\": \"1\"\n  }\n}\n"}},"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Example Account"},"accountUrl":{"type":"string","example":"https://www.example.url"},"createdTimestamp":{"type":"string","example":"2019-04-03T13:29:35-05:00"},"updatedTimestamp":{"type":"string","example":"2019-06-12T16:59:54-05:00"},"links":{"type":"object","properties":{"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/accounts/1/notes"}}},"id":{"type":"string","example":"1"}}}},"note":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-06-01T13:42:13-05:00"},"id":{"type":"string","example":"2"},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/activities"},"mentions":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/mentions"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/notes"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/owner"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/user"}}},"mdate":{"type":"string","example":"2017-06-01T13:42:13-05:00"},"note":{"type":"string","example":"Update with more info"},"owner":{"type":"object","properties":{"id":{"type":"string","example":"1"},"type":{"type":"string","example":"account"}}},"relid":{"type":"string","example":"1"},"reltype":{"type":"string","example":"CustomerAccount"},"user":{"type":"string","example":"1"},"userid":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/activities":{"get":{"summary":"List a contact's activity history: recent events such as campaign emails sent, link clicks, list and automation changes, notes","description":"The activity feed of one contact: its history of what the contact has done recently and which campaigns and emails were sent to it, as events recorded over time. Email opens are not activities: this feed shows sends (Log) and clicks (LinkData) but cannot say whether the contact opened an email. Send contact with the contact id. The request first refreshes that contact's feed from the underlying tables, so recent events appear, then returns the entries. A request without contact reads activities across the whole account; on a large account that scans millions of rows and can run for many minutes, so always scope the read to one contact. Each entry says what happened through reference_type and reference_action, and names the underlying record with reference_id and reference (its API type and id). What the types mean: Log, a campaign email was sent to the contact (include reference.log.campaign to see which campaign); LinkData, the contact clicked a tracked link in a campaign email (include reference.link for the link); MppLinkData, a campaign link was fetched by a mail privacy proxy rather than by the contact; Forward, the contact forwarded a campaign; Reply, the contact replied to a campaign; Update, the contact updated their details through a campaign's update link; SubscriberEmail, a one-to-one email was sent to the contact from the platform; SubscriberList with reference_action subscribe or unsubscribe, the contact joined or left a list; SubscriberSeries with start or complete, the contact entered or completed an automation; SeriesBlock with goal, the contact reached an automation goal; Note, a note was added to the contact; SubscriberLog with merge, another contact was merged into this one; TrackingLog, a site-tracking or event-tracking hit, with the event name (or __pagevisit for a page visit) in reference_action; SmsLog, SmsReply and SmsUnsub, an SMS sent, a reply and an opt-out; DealActivity and DealTask, CRM deal activity and tasks; SubscriberConversion, a conversion; EcomOrderActivity, an e-commerce order; HilosFlow and HilosConversation, WhatsApp; Enrichment, a data enrichment run; OmniChannelLinkData, a click on a link in an SMS message; FbAudienceContactLog, the contact was added to or removed from a Facebook custom audience; SubscriberRestoreActivity, the contact was archived (removed) or restored. To keep one kind of event, pass type with one or more API type names separated by commas, for example type=log,link-data; to see only events after a moment, pass after. Results are paged: limit defaults to 20 and is capped at 100, page with offset, and meta.total is the number of matching entries. Always pass orders[tstamp]=desc (newest first) or asc: without it the entries come back grouped by kind, not by time.","operationId":"list-contact-activities","x-canonical-resource":"activity","parameters":[{"name":"contact","in":"query","description":"The contact id. Always send it: without it the read covers every activity on the account. Several contacts can be read at once by repeating the key, contact[]=1&contact[]=2.","schema":{"type":"integer","format":"int32"}},{"name":"after","in":"query","description":"Return only entries recorded strictly after this date and time. Any common date format is accepted; a value without a timezone offset is read in the platform timezone, the one the response's other timestamps carry. An unreadable value returns 422.","schema":{"type":"string","format":"date-time"}},{"name":"type","in":"query","description":"Return only entries of these kinds. One or more API type names separated by commas: log, link-data, mpp-link-data, forward, reply, update, contact-email, contact-list, contact-automation, automation-block, note, contact-log, tracking-log, sms-log, sms-reply, sms-unsub, deal-activity, deal-task, contact-conversion, ecom-order-activity, hilos-flow, hilos-conversation, enrichment, omni-channel-link-data, fb-audience-contact-log, contact-restore-activity. These are the reference_type values written in lower case with dashes, with contact in place of subscriber and automation in place of series; the response's referenceModelName uses the same spelling. The reference_type spelling itself, for example Log or SubscriberList, is accepted too.","schema":{"type":"string"}},{"name":"emails","in":"query","description":"A switch. When the parameter is present with any value, including 0, only one-to-one email activity is returned: SubscriberEmail entries, Reply entries, and deal activities that carry a connected-mailbox email. Leave it out to see every kind of activity.","schema":{"type":"boolean"}},{"name":"include","in":"query","description":"Related records to attach, separated by commas. The reference record itself is always attached. Values: notes, notes.user, recipients, recipients.recipient, reference, reference.automation, reference.campaign, reference.campaign.campaignList, reference.campaign.campaignMessage, reference.campaignMessage, reference.contact, reference.contactList, reference.contactList.list, reference.deal, reference.deal.contact, reference.dealTasktype, reference.link, reference.list, reference.log, reference.log.campaign, reference.log.contact, reference.log.message, reference.message, reference.note, reference.sms, reference.sms.automation, user","schema":{"type":"string","default":"activities to include"}},{"name":"orders[tstamp]","in":"query","description":"Order entries by when they happened: asc for oldest first, desc for newest first.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","description":"Number of entries to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of entries to skip before returning results. Use with limit to page.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The matching activity entries, in the order orders[tstamp] asks for (grouped by kind when it is omitted), with any included related records side-loaded under their own keys, for example contactLists or notes.","content":{"application/json":{"schema":{"type":"object","properties":{"activities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"865","description":"The activity entry id."},"tstamp":{"type":"string","example":"2019-01-03T12:16:19-06:00","description":"When the event happened."},"subscriberid":{"type":"string","example":"4","description":"The contact id."},"reference_type":{"type":"string","example":"Log","description":"The kind of event. See the operation description for what each value means."},"reference_action":{"type":"string","example":"","description":"The sub-kind where a type has several. subscribe or unsubscribe for SubscriberList; start or complete for SubscriberSeries; goal for SeriesBlock; merge for SubscriberLog; add or complete for DealTask; add or remove for FbAudienceContactLog; the event name, or __pagevisit for a site visit, for TrackingLog; enriched or not_found for Enrichment; removed or restored for SubscriberRestoreActivity; start or completed for HilosFlow and created or closed for HilosConversation; original or duplicate on a DealActivity that shares an email with another entry; the message relation type for SmsLog, SmsReply and SmsUnsub. Empty for Log, LinkData, MppLinkData, Forward, Reply, Update, SubscriberEmail and Note."},"reference_id":{"type":"string","example":"13","description":"The id of the underlying record, for example the send log entry for a Log activity."},"referenceModelName":{"type":"string","example":"log","description":"The API type name of the underlying record, the spelling the type parameter takes."},"reference":{"type":["object","null"],"description":"The underlying record as a type and id pair. Null for HilosFlow, HilosConversation and Enrichment entries, which have no underlying record: their details are in jsonData.","properties":{"type":{"type":"string","example":"log","description":"The API type name of the underlying record, the same value as referenceModelName."},"id":{"type":"string","example":"13","description":"The id of the underlying record, the same value as reference_id."}}},"jsonData":{"description":"Extra data for some types, as a JSON string or null."},"userid":{"type":"string","example":"1","description":"The account user who caused the event, when one did."},"permission":{"type":"string","example":"","description":"Permission the caller needs to see the entry; pg_deal entries are hidden from users without deal access."},"notes":{"type":"array","items":{"type":"string"},"description":"Ids of notes attached to the activity."},"recipients":{"type":"array","items":{"type":"string"},"description":"Ids of recipient records attached to the activity."},"user":{"type":["string","null"],"example":"1","description":"The id of the account user who caused the event, the same value as userid. Null when no user did."},"links":{"type":"object","description":"URLs of the related reads for this entry: user, recipients, reference and notes, each at /activities/{id}/<name>."}}},"description":"The activity entries, one per event."},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1","description":"Number of matching entries, as a string."}},"description":"Paging information."}}}}}},"404":{"description":"The contact named by contact does not exist.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the contact id that was not found."}}}}}},"422":{"description":"after is not a readable date and time.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","example":"422","description":"The HTTP status, as a string."},"detail":{"type":"string","example":"not-a-date is not a valid date","description":"Names the value of after that could not be read."}}},"description":"One entry describing the problem."}}}}}}},"deprecated":false}},"/activities/recent":{"get":{"summary":"List recent account activity for the overview","description":"Backs the recent activity widget on the overview page. It is the v3 form of the v1 stats activity stream. Returns the account's activity stream as entries grouped by type and hour, newest first. Each entry says what happened (subscribes, unsubscribes, opens, clicks, forwards, replies and the like), how many times, and lists the contacts involved. Only entries for the calling user's first user group are returned. An entry with no saved contacts gets them read from the source tables, and an entry more than an hour old then keeps them for later calls. Entries with no contacts are left out unless includeEmpty is set. Returns 204 when there are no entries.","operationId":"list-recent-account-activity","x-canonical-resource":"activity","x-internal":true,"x-side-effects":true,"parameters":[{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 6. The value is read as a whole number, and 0 or a value that does not read as a number gives 6.","schema":{"type":"integer","minimum":1,"default":6}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the stream.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"typeFilter","in":"query","description":"Comma-separated activity types to include: subscribe, twitter, facebook, unsubscribe, open, click, forward, update, reply or read. Unknown names are dropped, so a list with only unknown names returns 204. Leave it out for every type.","schema":{"type":"string"},"example":"subscribe,unsubscribe"},{"name":"includeEmpty","in":"query","description":"Any value other than an empty string or 0 keeps entries that have no contacts.","schema":{"type":"string"}},{"name":"expanded","in":"query","description":"Any value other than an empty string or 0 adds each contact's card to the contacts in items: name, first_name, last_name, list count, location, local time and membership fields. Empty values are dropped from those contacts.","schema":{"type":"string"}}],"responses":{"200":{"description":"The entries, newest first.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentActivityStreamEntry"}},"examples":{"Result":{"value":[{"id":"812","groupid":"3","type":"1","tstamp":"2026-10-20 09:00:00","amount":"2","minute":"14","items":[{"id":"110","email":"sam@example.com","tstamp":"2026-10-20 09:14:02","screenshot":"https://www.example.com/avatar/110.png","type":"1"}],"minid":"5010","maxid":"5011","realtstamp":"2026-10-20 09:00:00","typestr":"subscribe","options":{"id":1,"color":"unused","class":"acalert","text":"Subscribed","fade":0,"url":"https://example.activehosted.com/admin/main.php?action=report_list_subscription","icon":"ac-icon-users","icon_bgcolor":"5499ab"},"last":"2026-10-20 09:14:00","isnew":false,"iscurrent":true,"timeago":"20 minutes ago"}]}}}}},"204":{"description":"There are no entries for the request."}}}},"/activities/{id}":{"get":{"summary":"Retrieve one activity entry","description":"Returns one entry of a contact's activity feed by its id. Use it to re-read an entry found through GET /activities. The fields are the same as in the list, except notes and recipients, which appear only in the list. The response carries the entry only: the underlying record is not attached, so read it from the endpoint for its type, using reference.type and reference.id. Unlike GET /activities, this read does not refresh the contact's feed first.","operationId":"retrieve-a-contact-activity","x-canonical-resource":"activity","parameters":[{"name":"id","in":"path","description":"The activity entry id, the id field of a GET /activities entry.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The activity entry.","content":{"application/json":{"schema":{"type":"object","properties":{"activity":{"type":"object","properties":{"id":{"type":"string","example":"7","description":"The activity entry id."},"tstamp":{"type":"string","example":"2026-09-24T17:12:53-05:00","description":"When the event happened."},"subscriberid":{"type":"string","example":"1","description":"The contact id."},"reference_type":{"type":"string","example":"Note","description":"The kind of event. GET /activities explains what each value means."},"reference_action":{"type":"string","example":"","description":"The sub-kind where a type has several, as listed for GET /activities. Empty when the type has none."},"reference_id":{"type":"string","example":"1","description":"The id of the underlying record, for example the send log entry for a Log activity."},"referenceModelName":{"type":"string","example":"note","description":"The API type name of the underlying record, the spelling the type parameter takes."},"reference":{"type":["object","null"],"description":"The underlying record as a type and id pair. Null for HilosFlow, HilosConversation and Enrichment entries, which have no underlying record: their details are in jsonData.","properties":{"type":{"type":"string","example":"note","description":"The API type name of the underlying record, the same value as referenceModelName."},"id":{"type":"string","example":"1","description":"The id of the underlying record, the same value as reference_id."}}},"jsonData":{"description":"Extra data for some types, as a JSON string or null."},"userid":{"type":"string","example":"1","description":"The account user who caused the event, when one did."},"permission":{"type":"string","example":"","description":"The permission that gates this entry in GET /activities: empty, or pg_deal."},"user":{"type":["string","null"],"example":"1","description":"The id of the account user who caused the event, the same value as userid. Null when no user did."},"links":{"type":"object","description":"URLs of the related reads for this entry: user, recipients, reference and notes, each at /activities/{id}/<name>."}},"description":"The activity entry."}}}}}},"404":{"description":"No activity entry has this id, or the entry is filtered out for this caller: a deal activity when the caller has no deal access, a mailbox email in another user's private mailbox, an entry for a deal the caller does not own (without permission to see all deals), or a list subscription that was removed. Entries the list hides only by their permission value are not filtered here and return 200.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Activity with id 999999\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the activity id that was not found."}}}}}}},"deprecated":false}},"/activityRecipients":{"get":{"summary":"List all activity recipients","description":"Lists the activity recipient records in the account. Each record links one entry of a contact's activity feed (see GET /activities) to the contact it is about. A record is written for each new activity entry, always with reltype Subscriber and the contact id in relid. The activity entry's own subscriberid holds the same contact. Saving a change to an entry writes another record, so one entry can have several records. A merge moves the merged contact's records to the surviving contact. The list has no filters or sort options, and records come in no guaranteed order. It does not check the linked activity, so it can return records that GET /activityRecipients/{id} answers with 403. Page with limit and offset, or fetch specific records with ids.","operationId":"list-all-activity-recipients","x-canonical-resource":"activity","parameters":[{"name":"limit","in":"query","description":"Number of records to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","description":"Number of records to skip. Use with limit to page through the records.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated record IDs to return. When set, only those records are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of records under activityRecipients, with the number of matching records in meta.total. activityRecipients is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"activityRecipients":{"type":"array","description":"The records on this page.","items":{"$ref":"#/components/schemas/ActivityRecipient"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, before limit and offset are applied. When ids is set, the number of those ids that exist."}}}}},"examples":{"Result":{"value":{"activityRecipients":[{"reltype":"Subscriber","relid":"6199","activityid":"48211","links":{"recipient":"https://example.api-us1.com/api/3/activityRecipients/90112/recipient","activity":"https://example.api-us1.com/api/3/activityRecipients/90112/activity"},"id":"90112","recipient":{"type":"contact","id":"6199"},"activity":"48211"}],"meta":{"total":1}}}}}}}}}},"/activityRecipients/{id}":{"get":{"summary":"Retrieve an activity recipient","description":"Returns one activity recipient record by its ID, under activityRecipient. The linked activity entry comes beside it, under activities. Returns 404 if no record has the id. Returns 403 when the linked activity entry cannot be read. That happens when the activity entry no longer exists, or it is filtered out for this caller: a deal activity when the caller has no deal access, a mailbox email in another user's private mailbox, an entry for a deal the caller does not own (without permission to see all deals), or a list subscription that was removed.","operationId":"retrieve-an-activity-recipient","x-canonical-resource":"activity","parameters":[{"name":"id","in":"path","description":"ID of the activity recipient record.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record under activityRecipient and its activity entry under activities.","content":{"application/json":{"schema":{"type":"object","properties":{"activities":{"type":"array","description":"The linked activity entry, as the only item.","items":{"$ref":"#/components/schemas/Activity"}},"activityRecipient":{"description":"The record. It also carries activity, the id of the linked activity entry.","allOf":[{"$ref":"#/components/schemas/ActivityRecipient"}]}}},"examples":{"Result":{"value":{"activities":[{"tstamp":"2026-09-01T14:03:12-05:00","subscriberid":"6199","reference_type":"SubscriberList","reference_id":"88","reference_action":"subscribe","jsonData":null,"userid":"0","permission":"","referenceModelName":"contact-list","links":{"user":"https://example.api-us1.com/api/3/activities/48211/user","recipients":"https://example.api-us1.com/api/3/activities/48211/recipients","reference":"https://example.api-us1.com/api/3/activities/48211/reference","notes":"https://example.api-us1.com/api/3/activities/48211/notes"},"id":"48211","user":null,"reference":{"type":"contact-list","id":"88"}}],"activityRecipient":{"reltype":"Subscriber","relid":"6199","activityid":"48211","activity":"48211","links":{"recipient":"https://example.api-us1.com/api/3/activityRecipients/90112/recipient","activity":"https://example.api-us1.com/api/3/activityRecipients/90112/activity"},"id":"90112","recipient":{"type":"contact","id":"6199"}}}}}}}},"403":{"description":"The linked activity entry no longer exists or is filtered out for this caller. Body: {\"errors\":[{\"status\":\"403\",\"detail\":\"Forbidden\"}]}.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string."},"detail":{"type":"string","description":"Error message."}}}}}}}}},"404":{"description":"No activity recipient record has that id. Body: message, \"No Result found for ActivityRecipient with id\" followed by the id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFound"}}}}}}},"/activityRecipients/{id}/activity":{"get":{"summary":"Retrieve the activity of an activity recipient","description":"Returns the activity entry this record links to, under activity, in the same shape as GET /activities/{id}. The body is an empty object {} in the cases where GET /activityRecipients/{id} returns 403: when the activity entry no longer exists, or it is filtered out for this caller: a deal activity when the caller has no deal access, a mailbox email in another user's private mailbox, an entry for a deal the caller does not own (without permission to see all deals), or a list subscription that was removed. Returns 404 if no record has the id.","operationId":"retrieve-activity-recipient-activity","x-canonical-resource":"activity","parameters":[{"name":"id","in":"path","description":"ID of the activity recipient record.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The activity entry under activity, or an empty object ({}). GET /activityRecipients/{id} shows an example entry under activities.","content":{"application/json":{"schema":{"type":"object","properties":{"activity":{"$ref":"#/components/schemas/Activity"}}}}}},"404":{"description":"No activity recipient record has that id. Body: message, \"No Result found for ActivityRecipient with id\" followed by the id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFound"}}}}}}},"/activityRecipients/{id}/recipient":{"get":{"summary":"Retrieve the recipient of an activity recipient","description":"Returns the record that relid points to. The record type comes from reltype and sets the response key. Records are written with reltype Subscriber, so the response is the contact, under contact. The body is an empty object {} when the contact no longer exists or relid is 0. Users outside the Admin group also get {} when the contact is only on lists their group may not access. This read does not check the linked activity entry. Returns 404 if no record has the id.","operationId":"retrieve-activity-recipient-recipient","x-canonical-resource":"activity","parameters":[{"name":"id","in":"path","description":"ID of the activity recipient record.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The contact under contact, or an empty object ({}). The example shows only the fields listed here.","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"type":"object","description":"The contact, in the same shape as contact in GET /contacts/{id}, where the full record is documented. The main fields are listed here. Only the contact itself comes back; none of the arrays that GET /contacts/{id} adds beside it.","properties":{"email":{"type":"string","description":"Email address of the contact."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"id":{"type":"string","description":"Id of the contact. Same value as relid."}}}}},"examples":{"Result":{"value":{"contact":{"email":"sam@example.com","firstName":"Sam","lastName":"Example","id":"6199"}}}}}}},"404":{"description":"No activity recipient record has that id. Body: message, \"No Result found for ActivityRecipient with id\" followed by the id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFound"}}}}}}},"/addressGroups":{"get":{"summary":"List all addressGroups","description":"List the associations between addresses and user groups. Each record links one address to one group; an address that is available to every group has `allgroup` set on the address itself instead of an `addressGroup` record.\n\nThis collection is not filterable. To read the associations for a single address, use `GET /api/3/addresses/{id}/addressGroup`.","operationId":"list-all-addressgroups","x-canonical-resource":"addressGroups","parameters":[{"name":"limit","in":"query","description":"The number of records to return per request. Defaults to 20 and is capped at 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressGroups\": [\n        {\n            \"address\": \"1\",\n            \"group\": \"3\",\n            \"created_timestamp\": \"2026-01-14 09:12:44\",\n            \"updated_timestamp\": \"2026-01-14 09:12:44\",\n            \"links\": {\n                \"address\": \"https://:account.api-us1.com/api/3/addressGroups/1/address\",\n                \"group\": \"https://:account.api-us1.com/api/3/addressGroups/1/group\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressGroups":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","example":"1"},"group":{"type":"string","example":"3"},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"updated_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/address"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/group"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"post":{"summary":"Create an addressGroup","description":"Associates an address with a group. Creating an association that already exists returns the existing record with 200 instead of a duplicate.\n\nCreating a new association also clears `allgroup` (available to every user group) on this address and on every other address that has it set, so those addresses become available only to the groups they are explicitly associated with. The 201 response side-loads the saved address under `addresses`.","operationId":"create-an-addressgroup","requestBody":{"content":{"application/json":{"schema":{"properties":{"addressGroup":{"description":"The address-to-user-group association","required":["address","group"],"properties":{"address":{"description":"ID of the address","type":"integer","format":"int32"},"group":{"description":"ID of the user group","type":"integer","format":"int32"}},"type":"object"}},"type":"object","additionalProperties":false},"examples":{"Request Example":{"summary":"Request Example","value":{"addressGroup":{"address":1,"group":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"addressGroup":{"description":"The address-to-user-group association","properties":{"address":{"description":"ID of the sender address (see /addresses)","type":"string","example":"1"},"group":{"description":"ID of the user group allowed to use the address","type":"string","example":"3"},"created_timestamp":{"description":"When the association was created, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone","type":"string","example":"2026-10-01 15:32:15"},"updated_timestamp":{"description":"When the association was last changed, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone","type":"string","example":"2026-10-01 15:32:15"},"created_by":{"description":"ID of the user who created the association. Not set through the API: null in write responses, and null or \"0\" on later reads","type":["string","null"],"example":null},"updated_by":{"description":"ID of the user who last changed the association. Not set through the API: null in write responses, and null or \"0\" on later reads","type":["string","null"],"example":null},"links":{"description":"API URLs of the related address and user group","properties":{"address":{"description":"URL of the related address","type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/address"},"group":{"description":"URL of the related user group","type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/group"}},"type":"object"},"id":{"description":"ID of the addressGroup association","type":"string","example":"1"}},"type":"object"}},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{\n    \"addressGroup\": {\n        \"address\": \"1\",\n        \"group\": \"3\",\n        \"created_timestamp\": \"2026-10-01 15:32:15\",\n        \"updated_timestamp\": \"2026-10-01 15:32:15\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressGroups/1/address\",\n            \"group\": \"https://:account.api-us1.com/api/3/addressGroups/1/group\"\n        },\n        \"id\": \"1\"\n    }\n}"}}}}},"201":{"description":"201","content":{"application/json":{"schema":{"properties":{"addresses":{"description":"The associated address, side-loaded because creating the association saves it (see the operation description)","type":"array","items":{"description":"An address record in the shape GET /addresses/{id} returns","type":"object"}},"addressGroup":{"description":"The address-to-user-group association","properties":{"address":{"description":"ID of the sender address (see /addresses), returned in the type the request sent it: a JSON number when sent as one; later reads return a numeric string","type":"integer","example":1},"group":{"description":"ID of the user group allowed to use the address, returned in the type the request sent it","type":"integer","example":3},"links":{"description":"API URLs of the related address and user group","properties":{"address":{"description":"URL of the related address","type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/address"},"group":{"description":"URL of the related user group","type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/group"}},"type":"object"},"id":{"description":"ID of the addressGroup association","type":"string","example":"1"}},"type":"object"}},"type":"object"},"examples":{"Result":{"summary":"The resource was created","value":"{\n    \"addresses\": [\n        {\n            \"companyName\": \"Example Co\",\n            \"allgroup\": 0,\n            \"isDefault\": \"0\",\n            \"id\": \"1\"\n        }\n    ],\n    \"addressGroup\": {\n        \"address\": 1,\n        \"group\": 3,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressGroups/1/address\",\n            \"group\": \"https://:account.api-us1.com/api/3/addressGroups/1/group\"\n        },\n        \"id\": \"1\"\n    }\n}"}}}}}},"x-canonical-resource":"addressGroups","x-destructive":false,"x-bulk-operation":false},"delete":{"summary":"Delete an addressGroup by address and group","description":"Removes the association identified by `address` and `group` without needing the addressGroup ID.","operationId":"delete-an-addressgroup-by-address-and-group","parameters":[{"name":"address","in":"query","description":"ID of the address","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group","in":"query","description":"ID of the user group","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{}"}}}}},"400":{"description":"`address` or `group` is missing or not a positive integer.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Validation errors for the query parameters","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":400},"title":{"description":"HTTP status text","type":"string","example":"Bad Request"},"detail":{"description":"Which parameter is missing or not a positive integer","type":"string","example":"The group parameter must be a positive integer."}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request was invalid","value":"{\n    \"errors\": [\n        {\n            \"status\": 400,\n            \"title\": \"Bad Request\",\n            \"detail\": \"The group parameter must be a positive integer.\"\n        }\n    ]\n}"}}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The lookup error","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":404},"title":{"description":"HTTP status text","type":"string","example":"Not Found"},"detail":{"description":"No association matches this address and group","type":"string","example":"Address group association not found"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The resource was not found","value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\",\n            \"detail\": \"Address group association not found\"\n        }\n    ]\n}"}}}}}},"x-canonical-resource":"addressGroups","x-destructive":true,"x-bulk-operation":false}},"/addressGroups/{id}":{"get":{"summary":"Retrieve an addressGroup","description":"","operationId":"retrieve-an-addressgroup","x-canonical-resource":"addressGroups","parameters":[{"name":"id","in":"path","description":"ID of the addressGroup to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressGroup\": {\n        \"address\": \"1\",\n        \"group\": \"3\",\n        \"created_timestamp\": \"2026-01-14 09:12:44\",\n        \"updated_timestamp\": \"2026-01-14 09:12:44\",\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressGroups/1/address\",\n            \"group\": \"https://:account.api-us1.com/api/3/addressGroups/1/group\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressGroup":{"type":"object","properties":{"address":{"type":"string","example":"1"},"group":{"type":"string","example":"3"},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"updated_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/address"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/group"}}},"id":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for AddressGroup with id 19\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for AddressGroup with id 19"}}}}}}},"deprecated":false},"put":{"summary":"Update an addressGroup","description":"Points an existing association at another address or group.","operationId":"update-an-addressgroup","x-canonical-resource":"addressGroups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the addressGroup to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"addressGroup":{"type":"object","properties":{"address":{"type":"integer","description":"ID of the address","format":"int32"},"group":{"type":"integer","description":"ID of the user group","format":"int32"}},"required":["address","group"],"description":"The address-to-user-group association"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"addressGroup":{"address":1,"group":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressGroup\": {\n        \"address\": 1,\n        \"group\": 3,\n        \"created_timestamp\": \"2026-10-01 15:32:15\",\n        \"updated_timestamp\": \"2026-10-01 15:32:15\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressGroups/1/address\",\n            \"group\": \"https://:account.api-us1.com/api/3/addressGroups/1/group\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressGroup":{"type":"object","properties":{"address":{"type":"integer","example":1,"description":"ID of the sender address (see /addresses), returned in the type the request sent it: a JSON number when sent as one; later reads return a numeric string"},"group":{"type":"integer","example":3,"description":"ID of the user group allowed to use the address, returned in the type the request sent it"},"created_timestamp":{"type":"string","example":"2026-10-01 15:32:15","description":"When the association was created, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone"},"updated_timestamp":{"type":"string","example":"2026-10-01 15:32:15","description":"When the association was last changed, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone"},"created_by":{"type":["string","null"],"example":null,"description":"ID of the user who created the association. Not set through the API: null in write responses, and null or \"0\" on later reads"},"updated_by":{"type":["string","null"],"example":null,"description":"ID of the user who last changed the association. Not set through the API: null in write responses, and null or \"0\" on later reads"},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/address","description":"URL of the related address"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/addressGroups/1/group","description":"URL of the related user group"}},"description":"API URLs of the related address and user group"},"id":{"type":"string","example":"1","description":"ID of the addressGroup association"}},"description":"The address-to-user-group association"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for AddressGroup with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for AddressGroup with id 1","description":"No association has this ID"}}}}}}},"deprecated":false},"delete":{"summary":"Delete address associated with a specific user group","description":"","operationId":"delete-an-addressgroup","parameters":[{"name":"id","in":"path","description":"ID of the AddressGroup to delete","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{}"}}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says that no resource was found with the given ID, for example No Result found for AddressGroup with id 19.","type":"string","example":"No Result found for AddressGroup with id 19"}},"type":"object"},"examples":{"Result":{"summary":"The resource was not found","value":"{\n    \"message\": \"No Result found for AddressGroup with id 19\"\n}"}}}}}},"x-canonical-resource":"addressGroups","x-destructive":true,"x-bulk-operation":false}},"/addressLists":{"get":{"summary":"List all addressLists","description":"List the associations between addresses and lists. Each record links one address to one list.\n\nThis collection is not filterable. To read the associations for a single address, use `GET /api/3/addresses/{id}/addressList`.","operationId":"list-all-addresslists","x-canonical-resource":"addressLists","parameters":[{"name":"limit","in":"query","description":"The number of records to return per request. Defaults to 20 and is capped at 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressLists\": [\n        {\n            \"address\": \"1\",\n            \"list\": \"2\",\n            \"created_timestamp\": \"2026-01-14 09:12:44\",\n            \"updated_timestamp\": \"2026-01-14 09:12:44\",\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressLists":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","example":"1"},"list":{"type":"string","example":"2"},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"updated_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"post":{"summary":"Create an addressList","description":"Associates an address with a list. Creating an association that already exists returns the existing record with 200 instead of a duplicate.","operationId":"create-an-addresslist","requestBody":{"content":{"application/json":{"schema":{"properties":{"addressList":{"description":"The address-to-list association","required":["address","list"],"properties":{"address":{"description":"ID of the address","type":"integer","format":"int32"},"list":{"description":"ID of the list","type":"integer","format":"int32"}},"type":"object"}},"type":"object"},"examples":{"Request Example":{"summary":"Request Example","value":{"addressList":{"address":1,"list":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"addressList":{"description":"The address-to-list association","properties":{"address":{"description":"ID of the sender address (see /addresses)","type":"string","example":"1"},"list":{"description":"ID of the list the address is assigned to","type":"string","example":"17"},"created_timestamp":{"description":"When the association was created, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone","type":"string","example":"2026-10-01 15:32:15"},"updated_timestamp":{"description":"When the association was last changed, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone","type":"string","example":"2026-10-01 15:32:15"},"created_by":{"description":"ID of the user who created the association. Not set through the API: null in write responses, and null or \"0\" on later reads","type":["string","null"],"example":null},"updated_by":{"description":"ID of the user who last changed the association. Not set through the API: null in write responses, and null or \"0\" on later reads","type":["string","null"],"example":null},"links":{"description":"API URLs of the related address and list","properties":{"address":{"description":"URL of the related address","type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/address"},"list":{"description":"URL of the related list","type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/list"}},"type":"object"},"id":{"description":"ID of the addressList association","type":"string","example":"1"}},"type":"object"}},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{\n    \"addressList\": {\n        \"address\": \"1\",\n        \"list\": \"17\",\n        \"created_timestamp\": \"2026-10-01 15:32:15\",\n        \"updated_timestamp\": \"2026-10-01 15:32:15\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressLists/1/address\",\n            \"list\": \"https://:account.api-us1.com/api/3/addressLists/1/list\"\n        },\n        \"id\": \"1\"\n    }\n}"}}}}},"201":{"description":"201","content":{"application/json":{"schema":{"properties":{"addressList":{"description":"The address-to-list association","properties":{"address":{"description":"ID of the sender address (see /addresses), returned in the type the request sent it: a JSON number when sent as one; later reads return a numeric string","type":"integer","example":1},"list":{"description":"ID of the list the address is assigned to, returned in the type the request sent it","type":"integer","example":17},"links":{"description":"API URLs of the related address and list","properties":{"address":{"description":"URL of the related address","type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/address"},"list":{"description":"URL of the related list","type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/list"}},"type":"object"},"id":{"description":"ID of the addressList association","type":"string","example":"1"}},"type":"object"}},"type":"object"},"examples":{"Result":{"summary":"The resource was created","value":"{\n    \"addressList\": {\n        \"address\": 1,\n        \"list\": 17,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressLists/1/address\",\n            \"list\": \"https://:account.api-us1.com/api/3/addressLists/1/list\"\n        },\n        \"id\": \"1\"\n    }\n}"}}}}}},"x-canonical-resource":"addressLists","x-destructive":false,"x-bulk-operation":false},"delete":{"summary":"Delete an addressList by address and list","description":"Removes the association identified by `address` and `list` without needing the addressList ID.","operationId":"delete-an-addresslist-by-address-and-list","parameters":[{"name":"address","in":"query","description":"ID of the address","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"list","in":"query","description":"ID of the list","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{}"}}}}},"400":{"description":"`address` or `list` is missing or not a positive integer.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Validation errors for the query parameters","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":400},"title":{"description":"HTTP status text","type":"string","example":"Bad Request"},"detail":{"description":"Which parameter is missing or not a positive integer","type":"string","example":"The list parameter must be a positive integer."}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request was invalid","value":"{\n    \"errors\": [\n        {\n            \"status\": 400,\n            \"title\": \"Bad Request\",\n            \"detail\": \"The list parameter must be a positive integer.\"\n        }\n    ]\n}"}}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The lookup error","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":404},"title":{"description":"HTTP status text","type":"string","example":"Not Found"},"detail":{"description":"No association matches this address and list","type":"string","example":"Address list association not found"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The resource was not found","value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\",\n            \"detail\": \"Address list association not found\"\n        }\n    ]\n}"}}}}}},"x-canonical-resource":"addressLists","x-destructive":true,"x-bulk-operation":false}},"/addressLists/{id}":{"get":{"summary":"Retrieve an addressList","description":"","operationId":"retrieve-an-addresslist","x-canonical-resource":"addressLists","parameters":[{"name":"id","in":"path","description":"ID of the addressList to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressList\": {\n        \"address\": \"1\",\n        \"list\": \"2\",\n        \"created_timestamp\": \"2026-01-14 09:12:44\",\n        \"updated_timestamp\": \"2026-01-14 09:12:44\",\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressList":{"type":"object","properties":{"address":{"type":"string","example":"1"},"list":{"type":"string","example":"2"},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"updated_timestamp":{"type":"string","example":"2026-01-14 09:12:44"},"id":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for AddressList with id 19\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for AddressList with id 19"}}}}}}},"deprecated":false},"put":{"summary":"Update an addressList","description":"Points an existing association at another address or list.","operationId":"update-an-addresslist","x-canonical-resource":"addressLists","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the addressList to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"addressList":{"type":"object","properties":{"address":{"type":"integer","description":"ID of the address","format":"int32"},"list":{"type":"integer","description":"ID of the list","format":"int32"}},"required":["address","list"],"description":"The address-to-list association"}}},"examples":{"Request Example":{"value":{"addressList":{"address":1,"list":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"addressList\": {\n        \"address\": 1,\n        \"list\": 17,\n        \"created_timestamp\": \"2026-10-01 15:32:15\",\n        \"updated_timestamp\": \"2026-10-01 15:32:15\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/addressLists/1/address\",\n            \"list\": \"https://:account.api-us1.com/api/3/addressLists/1/list\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"addressList":{"type":"object","properties":{"address":{"type":"integer","example":1,"description":"ID of the sender address (see /addresses), returned in the type the request sent it: a JSON number when sent as one; later reads return a numeric string"},"list":{"type":"integer","example":17,"description":"ID of the list the address is assigned to, returned in the type the request sent it"},"created_timestamp":{"type":"string","example":"2026-10-01 15:32:15","description":"When the association was created, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone"},"updated_timestamp":{"type":"string","example":"2026-10-01 15:32:15","description":"When the association was last changed, as a database datetime (YYYY-MM-DD HH:MM:SS) without a timezone"},"created_by":{"type":["string","null"],"example":null,"description":"ID of the user who created the association. Not set through the API: null in write responses, and null or \"0\" on later reads"},"updated_by":{"type":["string","null"],"example":null,"description":"ID of the user who last changed the association. Not set through the API: null in write responses, and null or \"0\" on later reads"},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/address","description":"URL of the related address"},"list":{"type":"string","example":"https://:account.api-us1.com/api/3/addressLists/1/list","description":"URL of the related list"}},"description":"API URLs of the related address and list"},"id":{"type":"string","example":"1","description":"ID of the addressList association"}},"description":"The address-to-list association"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for AddressList with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for AddressList with id 1","description":"No association has this ID"}}}}}}},"deprecated":false},"delete":{"summary":"Delete address associated with a specific list","description":"","operationId":"delete-an-addresslist","parameters":[{"name":"id","in":"path","description":"ID of the AddressList to delete","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{}"}}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says that no resource was found with the given ID, for example No Result found for AddressGroup with id 19.","type":"string","example":"No Result found for AddressList with id 6"}},"type":"object"},"examples":{"Result":{"summary":"The resource was not found","value":"{\n    \"message\": \"No Result found for AddressList with id 6\"\n}"}}}}}},"x-canonical-resource":"addressLists","x-destructive":true,"x-bulk-operation":false}},"/addresses":{"post":{"summary":"Create an address","description":"","operationId":"create-an-address","x-canonical-resource":"addresses","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"properties":{"company_name":{"type":"string"},"address_1":{"type":"string"},"address_2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"district":{"type":"string","description":"(Optional for countries that use it)"},"country":{"type":"string","description":"Accepts a (2) two character string - country code (eg 'US', 'CA', 'MX')"},"allgroup":{"type":"integer","format":"int32"},"is_default":{"type":"boolean","description":"Indicates default address"},"sms_name":{"type":["string","null"],"maxLength":50,"description":"SMS name used in the outgoing messages."}},"required":["company_name","address_1","country"],"type":"object"}}},"examples":{"Request Example":{"value":{"address":{"company_name":"TEST NAME","address_1":"TEST ADDRESS","country":"US"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"address\": {\n        \"companyName\": \"TEST NAME\",\n        \"address1\": \"TEST ADDRESS\",\n        \"country\": 3,\n        \"links\": {\n            \"addressGroup\": \"https://:account.api-us1.com/api/3/addresses/3/addressGroup\",\n            \"addressList\": \"https://:account.api-us1.com/api/3/addresses/3/addressList\",\n            \"forms\": \"https://:account.api-us1.com/api/3/addresses/3/forms\"\n        },\n        \"id\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"address":{"type":"object","properties":{"companyName":{"type":"string","example":"TEST NAME"},"address1":{"type":"string","example":"TEST ADDRESS"},"country":{"type":"integer","example":3,"default":0},"links":{"type":"object","properties":{"addressGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/3/addressGroup"},"addressList":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/3/addressList"},"forms":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/3/forms"}}},"id":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all addresses","description":"","operationId":"list-all-addresses","x-canonical-resource":"addresses","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"GET /addresses (Example RESPONSE)":{"value":"{\n    \"addresses\": [\n        {\n            \"companyName\": \"Test Company Name\",\n            \"address1\": \"Test Address\",\n            \"address2\": \"\",\n            \"city\": \"\",\n            \"state\": \"\",\n            \"district\": \"\",\n            \"zip\": \"\",\n            \"country\": \"US\",\n            \"allgroup\": \"0\",\n            \"isDefault\": \"1\",\n            \"links\": {\n                \"addressGroup\": \"https://:account.api-us1.com/api/3/addresses/1/addressGroup\",\n                \"addressList\": \"https://:account.api-us1.com/api/3/addresses/1/addressList\",\n                \"forms\": \"https://:account.api-us1.com/api/3/addresses/1/forms\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"companyName\": \"TEST NAME\",\n            \"address1\": \"TEST ADDRESS\",\n            \"address2\": \"\",\n            \"city\": \"\",\n            \"state\": \"\",\n            \"district\": \"\",\n            \"zip\": \"\",\n            \"country\": \"US\",\n            \"allgroup\": \"0\",\n            \"isDefault\": \"0\",\n            \"links\": {\n                \"addressGroup\": \"https://:account.api-us1.com/api/3/addresses/2/addressGroup\",\n                \"addressList\": \"https://:account.api-us1.com/api/3/addresses/2/addressList\",\n                \"forms\": \"https://:account.api-us1.com/api/3/addresses/2/forms\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"object","properties":{"companyName":{"type":"string","example":"Test Company Name"},"address1":{"type":"string","example":"Test Address"},"address2":{"type":"string","example":""},"city":{"type":"string","example":""},"state":{"type":"string","example":""},"district":{"type":"string","example":""},"zip":{"type":"string","example":""},"country":{"type":"string","example":"US"},"allgroup":{"type":"string","example":"0"},"isDefault":{"type":"string","example":"1"},"links":{"type":"object","properties":{"addressGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressGroup"},"addressList":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressList"},"forms":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/forms"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/addresses/{id}":{"get":{"summary":"Retrieve an address","description":"","operationId":"retrieve-an-address","x-canonical-resource":"addresses","parameters":[{"name":"id","in":"path","description":"ID of the Address to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"address\": {\n        \"companyName\": \"Test Company Name\",\n        \"address1\": \"Test Address\",\n        \"address2\": \"\",\n        \"city\": \"\",\n        \"state\": \"\",\n        \"district\": \"\",\n        \"zip\": \"\",\n        \"country\": \"US\",\n        \"allgroup\": \"0\",\n        \"isDefault\": \"1\",\n        \"links\": {\n            \"addressGroup\": \"https://:account.api-us1.com/api/3/addresses/1/addressGroup\",\n            \"addressList\": \"https://:account.api-us1.com/api/3/addresses/1/addressList\",\n            \"forms\": \"https://:account.api-us1.com/api/3/addresses/1/forms\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"address":{"type":"object","properties":{"companyName":{"type":"string","example":"Test Company Name"},"address1":{"type":"string","example":"Test Address"},"address2":{"type":"string","example":""},"city":{"type":"string","example":""},"state":{"type":"string","example":""},"district":{"type":"string","example":""},"zip":{"type":"string","example":""},"country":{"type":"string","example":"US"},"allgroup":{"type":"string","example":"0"},"isDefault":{"type":"string","example":"1"},"links":{"type":"object","properties":{"addressGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressGroup"},"addressList":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressList"},"forms":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/forms"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update an address","description":"","operationId":"update-an-address","x-canonical-resource":"addresses","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the Address being changed","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"properties":{"company_name":{"type":"string"},"address_1":{"type":"string"},"address_2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"district":{"type":"string","description":"(Optional for countries that use it)"},"country":{"type":"string","description":"Accepts a (2) two character string - country code (eg 'US', 'CA', 'MX')"},"allgroup":{"type":"integer","format":"int32"},"is_default":{"type":"boolean","description":"Indicates default address"},"sms_name":{"type":["string","null"],"maxLength":50,"description":"SMS name used in the outgoing messages."}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"address":{"company_name":"New Test Company Name","address_1":"111 New Test Address","address_2":"","city":"New Test City","state":"Florida","zip":"12345","country":"US"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"address\": {\n        \"companyName\": \"New Test Company Name\",\n        \"address1\": \"111 New Test Address\",\n        \"address2\": \"\",\n        \"city\": \"New Test City\",\n        \"state\": \"Florida\",\n        \"district\": \"\",\n        \"zip\": \"12345\",\n        \"country\": \"US\",\n        \"allgroup\": \"0\",\n        \"isDefault\": \"1\",\n        \"links\": {\n            \"addressGroup\": \"https://:account.api-us1.com/api/3/addresses/1/addressGroup\",\n            \"addressList\": \"https://:account.api-us1.com/api/3/addresses/1/addressList\",\n            \"forms\": \"https://:account.api-us1.com/api/3/addresses/1/forms\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"address":{"type":"object","properties":{"companyName":{"type":"string","example":"New Test Company Name"},"address1":{"type":"string","example":"111 New Test Address"},"address2":{"type":"string","example":""},"city":{"type":"string","example":"New Test City"},"state":{"type":"string","example":"Florida"},"district":{"type":"string","example":""},"zip":{"type":"string","example":"12345"},"country":{"type":"string","example":"US"},"allgroup":{"type":"string","example":"0"},"isDefault":{"type":"string","example":"1"},"links":{"type":"object","properties":{"addressGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressGroup"},"addressList":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/addressList"},"forms":{"type":"string","example":"https://:account.api-us1.com/api/3/addresses/1/forms"}}},"id":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Address with id 3\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Address with id 3"}}}}}}},"deprecated":false},"delete":{"summary":"Delete an address","description":"","operationId":"delete-an-address","parameters":[{"name":"id","in":"path","description":"ID of the Address to delete","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{},"type":"object"},"examples":{"Result":{"summary":"A successful response","value":"{}"}}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says that no resource was found with the given ID, for example No Result found for AddressGroup with id 19.","type":"string","example":"No Result found for Address with id 3"}},"type":"object"},"examples":{"Result":{"summary":"The resource was not found","value":"{\n    \"message\": \"No Result found for Address with id 3\"\n}"}}}}}},"x-canonical-resource":"addresses","x-destructive":true,"x-bulk-operation":false}},"/agents/mcp-gateway/automation-generation/edit":{"post":{"description":"Edit the automation `automation_id` names and return the run handle at once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditAutomationInput"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-automation-edit","summary":"Edit Automation","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"edit_automation","title":"Edit Automation","description":"Start changing an existing automation, named by automation_id, from the user's\nplain-language description of the change, and return a request_id at once. Call\npoll_automation_generation_status with the request_id until phase is complete or cancelled,\nthen tell the user the outcome.\n\nPut the change in prompt, in the user's words. Find the automation_id first if the user named\nthe automation only by name. An automation that cannot be changed reports not_editable, which\nrewording the request will not change."}}},"/agents/mcp-gateway/automation-generation/generate":{"post":{"description":"Build an automation from a brief and return its run handle at once.\n\nPoll `GET /runs/{request_id}`. Send `idempotency_key` on anything you might re-issue: the same key\nreturns the same run rather than building a second automation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateAutomationInput"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-automation-generation","summary":"Generate Automation","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"generate_automation","title":"Generate Automation","description":"Start building a new automation from the user's plain-language description, and return a\nrequest_id at once. A build takes minutes, so this call never waits for it: call\npoll_automation_generation_status with the request_id until phase is complete or cancelled,\nthen tell the user the outcome.\n\nPut the whole request in prompt, in the user's words: what starts the automation, what it\ndoes next, and any emails it sends. Do not split one request into several calls.\n\nThe same call repeated with the same arguments returns the same run rather than building a\nsecond automation. A finished build is saved to the account."}}},"/agents/mcp-gateway/automation-generation/runs":{"get":{"description":"List this account's recent automation runs, newest first.","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Zero-based pagination offset — skip this many runs before returning `limit` more.","default":0,"title":"Offset"},"description":"Zero-based pagination offset — skip this many runs before returning `limit` more."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of runs to return.","default":20,"title":"Limit"},"description":"Maximum number of runs to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRunListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"list-automation-generation-runs","summary":"List Automation Runs","x-canonical-resource":"automation","x-internal":true,"x-mcp-tool":{"name":"list_automation_runs","title":"List Automation Runs","description":"List this account's recent automation runs, newest first. Use it to find a request_id that\nwas lost, then call poll_automation_generation_status with it for the outcome. Runs age out\nafter a few hours, so this is recent activity, not a full history."}}},"/agents/mcp-gateway/automation-generation/runs/{request_id}":{"get":{"description":"Report a run's progress, then its automation or typed outcome, and its emails' progress.\n\nAn unknown run id reads as `queued`. A run whose process died is reported `failed`.","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"description":"request_id returned by generate_automation or edit_automation.","title":"Request Id"},"description":"request_id returned by generate_automation or edit_automation."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"get-automation-generation-run","summary":"Poll Automation Generation Status","x-canonical-resource":"automation","x-internal":true,"x-mcp-tool":{"name":"poll_automation_generation_status","title":"Poll Automation Generation Status","description":"Report an automation run started by generate_automation or edit_automation, by its\nrequest_id. While phase is queued or running, call again. When phase is complete, outcome\nsays how it ended and automation describes what was built or changed; email_progress\nreports the progress of any emails the build is still writing. retryable is true only when starting the\nrequest again can succeed. A request_id this account never started reads as queued."}}},"/agents/mcp-gateway/automation-generation/runs/{request_id}/cancel":{"post":{"description":"Cancel a run still in progress; a finished or unknown run is reported as it stands.\n\nA build hosted already accepted may still complete: the same idempotency key then returns\nthat automation rather than a second one.","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"description":"request_id returned by generate_automation or edit_automation.","title":"Request Id"},"description":"request_id returned by generate_automation or edit_automation."}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"cancel-automation-generation-run","summary":"Cancel Automation Run","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"cancel_automation_run","title":"Cancel Automation Run","description":"Stop an automation run that is still in progress, by its request_id. A run that already\nfinished keeps its outcome and is reported as it stands. A request_id this account has no run\nfor reads as queued, with a message saying nothing was cancelled: never report it cancelled —\ncall list_automation_runs to find the user's run. Otherwise call\npoll_automation_generation_status afterwards to see where it stopped.","annotations":{"idempotentHint":true}}}},"/agents/mcp-gateway/campaign-generation/context":{"get":{"description":"Summaries of the account's recent campaigns and audiences, to ground a generation request.\n\nEach category is read on its own: one that fails or does not answer within a second is named in\n`unavailable` and the others are still returned, so a partial answer never reads as an empty\naccount.","parameters":[{"name":"include","in":"query","required":true,"schema":{"type":"array","items":{"enum":["recent_campaigns","audiences"],"type":"string"},"minItems":1,"description":"Context categories to fetch. At least one category is required — an empty selection would return an empty result that reads as success.","title":"Include"},"description":"Context categories to fetch. At least one category is required — an empty selection would return an empty result that reads as success."},{"name":"campaign_query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Partial campaign name to narrow `recent_campaigns`.","default":null,"title":"Campaign Query"},"description":"Partial campaign name to narrow `recent_campaigns`."},{"name":"audience_query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Partial list name to narrow `audiences`.","default":null,"title":"Audience Query"},"description":"Partial list name to narrow `audiences`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationContextResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"get-campaign-generation-context","summary":"Get Campaign Generation Context","x-canonical-resource":"campaign","x-internal":true,"x-mcp-tool":{"name":"get_campaign_generation_context","title":"Get Campaign Generation Context","description":"Fetch compact background account context — recent campaigns and/or contact-list\naudiences — while preparing a generate_campaign or edit_campaign prompt (for\nexample, matching an existing campaign's tone, or checking which audiences exist).\nRenders no UI component: use this instead of list_campaigns or list_lists whenever\nthe goal is background context, not letting the user browse or pick from a list.\n\nRequest only the categories you need via include. A failed category is reported in\nunavailable and never blocks the other requested category. To make a campaign send to\none of these audiences, call set_campaign_audience."}}},"/agents/mcp-gateway/campaign-generation/copy":{"post":{"description":"Start a duplication of an existing campaign and return its run handle immediately.\n\nPoll `GET /runs/{run_id}` for the result. Name the campaign to duplicate with `campaign_id`, or\n`campaign_name` as the user said it, and put any changes to apply to the duplicate in\n`copy_changes`.\n\nA copy duplicates the campaign it names, so it takes no template and no separate source: both are\nrejected rather than accepted and ignored. `urls` share the brief's character budget as on\n`/generate`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpCopyRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-campaign-copy","summary":"Copy Campaign","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"copy_campaign","title":"Copy Campaign","description":"Duplicate an existing campaign as a new draft, optionally applying changes in the same\ncall. Returns a request_id immediately; campaign_id is null until the copy finishes —\ncall poll_campaign_generation_status with request_id and wait for a real campaign_id\nbefore treating the copy as done. Eligibility (editor version, automation attachment,\nsendable state) is decided behind this call; an ineligible source campaign is reported\nas a not_supported outcome, not raised.\n\n**Renaming vs. content changes.** Pass copy_changes to apply an edit to the copy in this\nsame call, instead of a separate edit_campaign call afterward. copy_changes only affects\nthe copy's email content/design — to rename the copy itself (its campaign record's own\nname, not its subject line), call update_campaign with the new campaign_id separately."}}},"/agents/mcp-gateway/campaign-generation/edit":{"post":{"description":"Start an edit of an existing campaign and return its run handle immediately.\n\nPoll `GET /runs/{run_id}` for the result. Name the target with `campaign_id`, or `campaign_name`\nas the user said it; with neither the run asks which campaign was meant rather than guessing.\n\nAn edit acts on the target's own markup, so it takes no template, source or stock layout: those\nfields are rejected rather than accepted and ignored. `urls` share the brief's character budget as\non `/generate`.\n\nA campaign that has been sent, belongs to an automation, or moved on outside the agent reports\n`not_editable`, which no rewording of the request will change.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpEditRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpEditStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-campaign-edit","summary":"Edit Campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"edit_campaign","title":"Edit Campaign","description":"Apply an AI-driven edit to an existing campaign. The scope of the edit is derived from\nprompt itself. Returns a request_id immediately; campaign_id is the same campaign passed\nin (an edit never changes which campaign it acts on) — call\npoll_campaign_generation_status with request_id until phase is complete.\n\n**Metadata flags.** Set update_subject or update_preheader only when the user explicitly\nasks to change that specific piece of metadata (e.g. \"shorten the subject line\" sets\nupdate_subject; \"change the CTA color\" sets neither — that's content, described in\nprompt).\n\n**A page or call-to-action link goes straight into urls, in this same call.** This tool\nreads and classifies that page itself — handing it the link IS the read. Do NOT fetch\nthe page or scrape its content as a separate step first.\n\nimage_references only ever takes a content-manager image's name — never a URL,\ncontent-manager-hosted or external. For any URL the user gives, search the account's\nContent Manager images for a matching or substitute image instead of passing that URL\nthrough, and tell the user afterward which content-manager image was used in its place.\n\nWhether this campaign can be edited is decided behind this call; a campaign the engine\ncan't edit is reported as a non-success outcome (for example not_editable), not raised.\nNOT for undoing a change — use restore_campaign_version instead; an edit rebuilds the\ncampaign and is charged, a restore is not.\n\n**Backward compatibility.** subject_change, preheader_change, images, content_change,\ncta_button_url_change, cta_button_text_change, and brand_kit_id are all accepted for\ncompatibility — see each field's own description for its replacement or effect. Passing\nany of them non-default surfaces in disclosures."}}},"/agents/mcp-gateway/campaign-generation/generate":{"post":{"description":"Start a campaign generation and return its run handle immediately.\n\nPoll `GET /runs/{run_id}` for progress and then the campaign or a typed outcome; nothing about the\nresult arrives on this response beyond the handle.\n\nSetting `source_campaign_id` changes what this route does: the run becomes a refill on that\ncampaign's structure rather than a fresh design, and it bills as a generation either way. A\n`template_id` refills on that template instead. With neither, the brief alone drives the design.\n\n`urls` are appended to the brief, which is where the engine reads and scrapes them, so they share\nthe brief's character budget: once it is full the remaining URLs are not used, and the run\ndiscloses how many were dropped rather than failing.\n\n`html` imports a finished email document as the campaign exactly as it stands, on the same import\na complete document pasted into the chat takes; it refuses every input that picks a different\ndesign or content.\n\nSend `idempotency_key` on anything you might re-issue: the same key resolves to the same run, so a\nrepeat returns the original handle instead of generating and billing a second campaign.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpGenerateRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-campaign-generation","summary":"Generate Campaign","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"generate_campaign","title":"Generate Campaign","description":"Create a new AI-generated email campaign from a text prompt.\n\n**bundle_url is not supported yet** (see its own param description for what counts as\none) — decide immediately: decline outright, or call now with bundle_url set and relay\nthat outcome verbatim. Never ask the user for more information first, and never route it\ninto check 3's urls parameter below — skip the image decision too.\n\n**html imports a finished email as it stands.** When the user hands over a complete HTML\nemail document to turn into a campaign, pass the whole document in html and their request\nin prompt, skip checks 2 and 3 below, and set none of the fields html's own description\nnames: the call is refused with any of them. A fragment or plain copy is not a document;\nleave it in prompt.\n\n**Three checks happen before every call, in this order:**\n\n1. Already generated — if poll_campaign_generation_status already reported\ncampaign_persisted true earlier in this conversation, STOP — never call generate_campaign\nagain for that campaign, not even with the exact same arguments as before, and not \"to be\nsafe\" or to double-check the result stuck. This holds even when the latest message reads\nlike a change (naming an image now, turning images on/off, changing tone), a repeat of an\nearlier answer, or a fresh-sounding request for the same topic: call edit_campaign with\nthat campaign_id for an actual change, or make no call at all when nothing needs to\nchange. There is no version of calling again that this campaign's existence doesn't\nalready make pointless. Example: campaign_persisted came back true for campaign_id 42,\nthen the user names an image — call edit_campaign(campaign_id=42, ...) with that image;\ncalling generate_campaign again is always wrong here, even to \"add\" the image this run\ndidn't have yet.\n\n2. Image — exactly one of these is always true:\n- No image has been named, attached, or declined yet — search the account's Content Manager images for one to use,\n  then PAUSE: end that response asking which result to use, or whether to skip the image,\n  WITHOUT calling generate_campaign. Only call generate_campaign after the user's next\n  message answers that question — never in the same response as the search, even when\n  the results include an obvious best match. No exceptions, even for a short or\n  simple-sounding request like \"announce our new pricing\".\n- The user named, attached, or linked an image. Treat any filename, description, or URL\n  the user gives — including a link to an image hosted anywhere else — as already\n  resolvable in the content manager: search the account's Content Manager images to find\n  the matching or best-substitute image, silently. Never ask the user whether it's\n  internal or external, and never surface that distinction to them at all — resolving it\n  is this tool's job, not theirs.\n- The user explicitly wants no image.\n- The user explicitly said to pick for them (\"you decide\", \"whatever fits\", \"surprise\n  me\") — see image_search_terms under Parameter behavior below.\n\n3. Page link — unlike the image check above, never needs a lookup call at all:\n- A url the user gives — to read for content, to link the campaign to, or because the\n  request is phrased as \"write from that page\" or \"based on its content\" — goes straight\n  into this same call's urls parameter. This tool classifies and reads the page itself;\n  handing over the link IS the read. Do NOT fetch the page or scrape\n  it first — there is no scenario where reading it yourself first is the right move.\n  Exception: a design-tool link is bundle_url, not this — see the note above.\n\nOnce all three checks are done — check 2 did not end in a PAUSE — call immediately with\nthe prompt as given, even when it names only a source (a template, a past campaign, a\nurl) and no topic at all. Do not ask for a campaign name, exact offer copy, tone, or any\nother missing detail beyond check 2's image question — nothing else needs confirming; the\nengine fills in anything the prompt doesn't specify.\n\nBrand, language, and image placement are resolved automatically from the account; there\nis no brand kit or image-position parameter, and no need to list the account's brand kits before\nthis. A short prompt naming a topic or pointing at a source — a url, a template, a past\ncampaign — is already a complete brief once the image decision is settled: the engine\nwrites the subject, offer, and copy, so call rather than asking the user to draft that\ncontent first.\n\n**Parameter behavior:**\n- image_references only ever takes a content-manager image's name (the `name` field\n  from the Content Manager) — never a URL, content-manager-hosted or\n  external. For any URL the user gives, search the account's Content Manager images for a\n  matching or substitute image instead of passing that URL through, and tell the user\n  afterward which content-manager image was used in its place.\n- urls takes the page or call-to-action link itself, verbatim — never a summary of it,\n  and never text fetched or scraped from it. One call does both: no separate fetch first.\n- image_search_terms lets the engine search for and choose an image on its own, with no\n  further reply needed — use it only after the user explicitly hands the choice over\n  (\"you decide\", \"whatever fits\", \"surprise me\"). Never use it in place of the image\n  decision above just because no image was named; silence about the image is not the\n  same as handing off the choice.\n- Use template_id (from list_campaign_templates), template_name when no id is known, or\n  stock_template_name to build into a named template; omit all three for a from-scratch\n  design.\n- Use source_campaign_date to disambiguate source_campaign_id when the user names rather\n  than numbers the source campaign and more than one shares that name.\n- Pass the user's exact words as prompt — never rephrase, rewrite, or expand them.\n\n**Lifecycle.** Returns a request_id immediately — call poll_campaign_generation_status\nwith it until phase is complete, then present the result. NEVER call again immediately on\nerror; surface the failure to the user instead. Once campaign_persisted comes back true,\nsee the already-generated check above — repeating the same arguments changes nothing but\nstill costs a round-trip, and repeating with different ones starts an unwanted second\ncampaign, so neither is ever worth doing. NOT for copying or editing an existing campaign\n— use copy_campaign to duplicate one outright, or edit_campaign to change one.\n\n**Backward compatibility.** label_id, images, cta_url, brand_kit_id, summarization_uuid,\ntone, series_id, and is_asset_draft are all accepted for compatibility — see each\nfield's own description for its replacement or effect. Passing any of them non-default\nsurfaces in disclosures. user_prompt is separate: ignored outright, never disclosed."}}},"/agents/mcp-gateway/campaign-generation/history":{"post":{"description":"Report what has changed on a campaign, in the words recorded at the time.\n\nAnswers immediately: this reads history rather than generating, so there is no run to poll and\nnothing is charged.\n\nCall this before a version move when the user names one (\"go back to 2\"): the numbers in the\nlisting are what `/restore` and `/redo` both accept. Supply both `from_version` and\n`to_version` to compare two versions instead of listing all of them.\n\nA campaign created outside the agent, or whose editing session has aged out, has no history here\nand says so.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpHistoryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDirectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"get-campaign-version-history","summary":"Get Campaign History","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"get_campaign_history","title":"Get Campaign History","description":"Report what has changed on a campaign, in the words recorded at the time. Answers\nimmediately — there is no run to poll and nothing is charged. Call this before\nrestore_campaign_version when the user names a version (\"go back to 2\"): the numbers in\nthe listing are what restore_campaign_version accepts. Pass both from_version and\nto_version to compare two versions instead of listing all of them.","annotations":{"readOnlyHint":true,"idempotentHint":true}}}},"/agents/mcp-gateway/campaign-generation/import":{"post":{"description":"Start an import of an email the caller already has and return its run handle immediately.\n\nPoll `GET /runs/{run_id}` for the result. The email arrives as complete HTML in `source_html`\nand is brought over as the sender's own: its content survives rather than being rewritten.\n`/generate` given the same markup would reuse its shape and write new copy into it, which is a\ndifferent request.\n\nThe imported design becomes a new draft campaign, editable in the campaign designer. Takes no\ntemplate, source campaign or stock layout: the document IS the design.\n\nSend `idempotency_key` on anything you might re-issue: the same key resolves to the same run, so\na repeat returns the original handle instead of importing and billing a second campaign.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpImportRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"start-campaign-import","summary":"Import Campaign Design","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"import_campaign_design","title":"Import Campaign Design","description":"Bring an email the user already has into ActiveCampaign as a new draft campaign,\nkeeping what it says. Takes the email's complete HTML in source_html. Returns a\nrequest_id immediately; campaign_id is null until the import finishes — call\npoll_campaign_generation_status with request_id until phase is complete, then\nread outcome: success carries the new campaign_id, while a failed or needs_input\nimport finishes with campaign_id still null. Expect that to take 35-90 seconds and to\nreport no progress for most of it; keep polling rather than concluding it failed.\n\n**This is not generate_campaign.** generate_campaign given the same markup reuses\nits shape and writes NEW copy into it, which is a rewrite of the email rather than\nthe email. Use this route whenever the user wants the email they already have —\nmigrating off another editor, a design produced elsewhere, a template they were\nsent. The imported design lands as a draft that opens in the campaign designer.\n\nPass the whole document in source_html, styles included. Nothing is fetched on\nthe caller's behalf: an email that lives at a URL has to be read and supplied as\nHTML here.\n\nThis route reproduces a design, it does not research one. A marketing page or\narticle the user wants an email written ABOUT goes to generate_campaign's urls\nparameter, which reads and classifies the page."}}},"/agents/mcp-gateway/campaign-generation/redo":{"post":{"description":"Redo a change to a campaign that was undone, bringing it forward one version.\n\nAnswers immediately and is NOT charged, exactly as `/restore` is not: a version move travels\nthrough work already paid for, in either direction.\n\nThis is the route for every redo and \"bring that back\". Do NOT express one as an `/edit`: an\nundone change is still recorded, so redoing it is a move, while an edit rebuilds the campaign\nfrom scratch, bills for it, and produces different markup than the change that was undone.\n\nOmit `version` to step forward one. Supply it only as a number that appeared in `/history`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRedoRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDirectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"redo-campaign-version","summary":"Redo Campaign Version","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"redo_campaign_version","title":"Redo Campaign Version","description":"Bring an undone campaign change forward one version, or to a specific version from its\nhistory. Answers immediately and is NOT charged — a version move travels through work\nalready paid for. This is the tool for every redo and \"bring that back\" — never\nedit_campaign for this: an edit rebuilds the campaign and bills for it, and produces\ndifferent markup than the change that was undone. Omit version to step forward one\nchange; pass a number only if it came from get_campaign_history's output."}}},"/agents/mcp-gateway/campaign-generation/restore":{"post":{"description":"Undo a change to a campaign, or put it back to a version from its history.\n\nAnswers immediately and is NOT charged: a version move travels through work already paid for, so\nstepping back never costs a generation.\n\nThis is the route for every undo, revert, roll-back and \"go back to version N\". Do NOT express a\nrevert as an `/edit`: an edit rebuilds the campaign and bills for it, and `/edit` rejects\n`is_revert` outright for that reason.\n\nOmit `version` to step back one. Supply it only as a number that appeared in `/history`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRestoreRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDirectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"restore-campaign-version","summary":"Restore Campaign Version","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"restore_campaign_version","title":"Restore Campaign Version","description":"Undo a change to a campaign, or put it back to a version from its history. Answers\nimmediately and is NOT charged — a version move travels through work already paid for.\nThis is the tool for every undo, revert, or \"go back to version N\" — never edit_campaign\nfor this: an edit rebuilds the campaign and bills for it. Omit version to step back one\nchange; pass a number only if it came from get_campaign_history's output."}}},"/agents/mcp-gateway/campaign-generation/runs":{"get":{"description":"List this account's recent campaign runs, newest first.\n\nUse this to recover a run whose id was lost, or to tell which run a handle refers to before\npolling it: each entry names the operation and when it started.\n\nThe listing is bounded and ages out with the runs it points at, so it is a recent-activity view\nrather than a permanent audit log. It reports what was STARTED; poll `GET /runs/{run_id}` for the\noutcome of any entry.","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Zero-based pagination offset — skip this many results before returning `limit` more.","examples":[0,20],"default":0,"title":"Offset"},"description":"Zero-based pagination offset — skip this many results before returning `limit` more."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"exclusiveMinimum":0,"description":"Maximum number of runs to return.","examples":[20],"default":20,"title":"Limit"},"description":"Maximum number of runs to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRunListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"list-campaign-generation-runs","summary":"List Campaign Runs","x-canonical-resource":"campaign","x-internal":true,"x-mcp-tool":{"name":"list_campaign_runs","title":"List Campaign Runs","description":"List this account's recent generate/edit/copy/import runs, newest first. Use to recover a\nrequest_id lost from an earlier turn, or to tell which run a handle refers to before\npolling it. Reports what was started, not the outcome — call\npoll_campaign_generation_status with a listed request_id for that. Answers immediately:\nnothing is charged."}}},"/agents/mcp-gateway/campaign-generation/runs/{request_id}":{"get":{"description":"Report a run's progress, and then its campaign or its typed outcome.\n\nAn unknown run id reads as ``queued`` rather than 404: the stream is written by a task that may\nnot have produced its first frame when a fast client polls. A failed stream read reads as\n``queued`` too rather than erroring, so a caller that hits one keeps polling to see the outcome.","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","description":"Run id returned by the tool that started this run.","examples":["run-generate-1"],"title":"Request Id"},"description":"Run id returned by the tool that started this run."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRunStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"get-campaign-generation-run","summary":"Poll Campaign Generation Status","x-canonical-resource":"campaign","x-internal":true,"x-mcp-tool":{"name":"poll_campaign_generation_status","title":"Poll Campaign Generation Status","description":"Report a campaign-generation run's progress, or its finished outcome. Call repeatedly\nwith the request_id returned by generate_campaign, edit_campaign, copy_campaign, or\nimport_campaign_design, until phase is complete or cancelled. Every non-success outcome — needs_input, busy,\nnothing_changed, nothing_saved, not_editable, not_supported, partial_success,\nunconfirmed, failed, not_enabled, unrecognized, unavailable — is reported here, never\nraised.\n\n**Campaign persisted invariant.** Read campaign_persisted before deciding what to do\nnext: when it is true, a campaign already exists for this run — never call\ngenerate_campaign, copy_campaign, or import_campaign_design again for it, whatever\noutcome says; that bills the account a second time. For any further change to this same\ncampaign (a different image,\ntone, or setting), call edit_campaign with its campaign_id instead — that is the correct\nnext call, not a repeat of the one that produced it. retryable says whether re-sending\nthe same request is worth it, and is never true while campaign_persisted is true.\n\n**How long to keep polling.** These runs are slow: a generate takes roughly 15-30\nseconds and an import 35-90. Keep polling until phase is complete or cancelled\n(outcome is set once phase is complete; a cancelled run carries none). A long run is not a\nfailed one, and neither a silent phase nor a repeated identical snapshot means the\nrun died — never report failure, or start a replacement run, on the strength of\nelapsed time alone. elapsed_seconds tells you how long this run has been going;\nread it with sections_completed, which stays null through an import because that\noperation spends almost all of its time inside one model call that reports nothing.\nIf you must stop early, say the run is still in progress and give the request_id\nback, so it can be polled again later.\n\nAnswer a needs_input outcome with an ordinary follow-up generate_campaign or\nedit_campaign call using the clarified request; there is no separate resume tool."}}},"/agents/mcp-gateway/campaign-generation/runs/{request_id}/cancel":{"post":{"description":"Stop a run and report it cancelled.\n\nThe run reads the marker this writes within ``CANCEL_POLL_SECONDS`` and stops its generation\nunless the service has already saved the campaign. A saved campaign is not withdrawn: that run\nfinishes and is billed, and the campaign is named on the stream instead of an outcome.","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","description":"Run id returned by the tool that started this run.","examples":["run-generate-1"],"title":"Request Id"},"description":"Run id returned by the tool that started this run."}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRunStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"cancel-campaign-generation-run","summary":"Cancel Campaign Run","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"cancel_campaign_run","title":"Cancel Campaign Run","description":"Stop a campaign-generation run. Pass the request_id returned by generate_campaign,\nedit_campaign, copy_campaign, or import_campaign_design. Generation stops unless the campaign is already saved: a\nsaved campaign is kept and billed, and poll_campaign_generation_status then reports its\ncampaign_id. Safe to call on a run that has already finished — it reports the run as it\nended. A request_id this account has no run for — mistyped, or expired and no longer kept —\nis not an error: it reads as queued, with a message saying nothing was cancelled. NEVER report a\nrun cancelled when cancel answers queued — call list_campaign_runs to find the user's run first. Call this whenever the user asks to cancel a\nrun, whatever its last known status.","annotations":{"idempotentHint":true}}}},"/agents/mcp-gateway/campaign-generation/templates":{"get":{"description":"The account's saved campaign templates matching a name, or the most recent ones.\n\nPass a result's `id` to `/generate` as `template_id`. A Hosted refusal of the search keeps its\n4xx status; any other failure to read it is a 502.","parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Name filter. Empty string lists recent templates; non-empty filters by partial name match.","examples":["summer"],"default":"","title":"Query"},"description":"Name filter. Empty string lists recent templates; non-empty filters by partial name match."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Maximum number of templates to return.","examples":[20],"default":20,"title":"Limit"},"description":"Maximum number of templates to return."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","description":"Zero-based pagination offset — skip this many results before returning `limit` more.","examples":[0,20],"default":0,"title":"Offset"},"description":"Zero-based pagination offset — skip this many results before returning `limit` more."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"list-campaign-templates","summary":"List Campaign Templates","x-canonical-resource":"templates","x-internal":true,"x-mcp-tool":{"name":"list_campaign_templates","title":"List Campaign Templates","description":"Search or list the account's saved campaign templates. Returns template objects keyed by\nid. Pass a returned integer id to generate_campaign as template_id to build a campaign\nbased on that template — this call is optional, not a prerequisite. Call with an empty\nquery to list the most recently modified templates, or a partial name to filter by name."}}},"/agents/mcp-gateway/campaign-generation/templates/manage":{"post":{"description":"Rename, delete or duplicate a template already in the account's library.\n\nAnswers immediately and is not charged.\n\nA DELETE cannot be undone, so it requires the template's id or its exact name and never resolves\na near-miss or a reference like \"that one\"; ask the user which template they mean rather than\nguessing. `new_name` is required to rename and ignored otherwise.\n\nBrand-kit \"Made for you\" templates are read-only and are refused with their own explanation.\nA template's CONTENT cannot be changed here: generate with the template to produce a campaign\nfrom its design instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpManageTemplateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDirectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"manage-campaign-template","summary":"Manage Campaign Template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"manage_campaign_template","title":"Manage Campaign Template","description":"Rename, delete, or duplicate a template already in the account's template library.\nAnswers immediately and is not charged. A template's content cannot be changed here —\ncall generate_campaign with the template to produce a campaign from its design instead.\n\n**Delete is irreversible.** It requires the template's id or its exact name and never\nresolves a near-miss or a reference like \"that one\" — ask the user which template they\nmean rather than guessing.\n\nnew_name is required to rename and ignored otherwise. Brand-kit \"Made for you\" templates\nare read-only and are refused with their own explanation."}}},"/agents/mcp-gateway/campaign-generation/templates/save":{"post":{"description":"Save an existing campaign into the account's template library for reuse.\n\nAnswers immediately and is read-only on the campaign: saving a template never changes the\ncampaign it was made from. Omit `template_name` to keep the campaign's own name.\n\nCharged per request, and only when a template is actually saved. Do NOT retry a call whose\noutcome you did not read: a retry saves a second template and is charged again.\n\nTo build a NEW campaign from a saved template, pass its id as `template_id` on `/generate`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpSaveTemplateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDirectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"save-campaign-as-template","summary":"Save Campaign As Template","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"save_campaign_as_template","title":"Save Campaign As Template","description":"Save an existing campaign into the account's template library for reuse. Answers\nimmediately and never changes the campaign it was made from. Omit template_name to keep\nthe campaign's own name. Charged per request, and only when a template is actually saved\n— do NOT retry a call whose outcome you did not read. To build a new campaign from the\nsaved template, pass its id as template_id to generate_campaign, or its name as\ntemplate_name."}}},"/agents/mcp-gateway/campaign-send/audience":{"post":{"description":"Replace a campaign's lists and segment, after checking each id is the account's own.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAudienceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAudienceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"set-campaign-audience","summary":"Set Campaign Audience","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"set_campaign_audience","title":"Set Campaign Audience","description":"Set the lists, and optionally the segment, that a campaign sends to. Answers at once and needs no confirmation token; it never sends.\n\nlist_ids is the complete set: it replaces every list the campaign holds now, so include any list the user wants to keep. segment_id narrows those lists; leave it null to clear any segment. Every id is checked against the account first: an unknown list reports list_not_found, an unknown segment segment_not_found, and a segment on none of the lists segment_not_on_lists, with nothing changed. A campaign with no sending address also gets one: its lists' address, or the account's default.\n\nsuccess is reported only once the new lists read back; unconfirmed means the change went out but could not be confirmed yet, so check the campaign's lists with get_campaign before setting them again. Requires permission to edit campaigns. Prepare the send or schedule again afterwards so the user reviews the campaign as it now stands.","annotations":{"idempotentHint":true}}}},"/agents/mcp-gateway/campaign-send/schedule/confirm":{"post":{"description":"Schedule a prepared campaign, only if it still matches what was prepared and its time is ahead.\n\nThe token is single use.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpSendResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"confirm-campaign-schedule","summary":"Confirm Campaign Schedule","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"confirm_campaign_schedule","title":"Confirm Campaign Schedule","description":"Schedule a campaign that prepare_campaign_schedule prepared, after the user explicitly agreed to the summary it returned. Pass the same campaign_id and its confirmation_token.\n\nThe token works once and only for a short time. If the campaign changed since the prepare, nothing is scheduled and outcome is changed; send_time_passed means send_at is no longer ahead. Prepare again in either case. unconfirmed means the answer was lost: NEVER retry it; check its status with get_campaign. Use unschedule_campaign to take a schedule back."}}},"/agents/mcp-gateway/campaign-send/schedule/prepare":{"post":{"description":"Check a campaign can be scheduled for `send_at` and freeze what it would send. Never schedules.\n\n`ready` returns a summary and a token that `/schedule/confirm` takes within its lifetime.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareScheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpPrepareResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"prepare-campaign-schedule","summary":"Prepare Campaign Schedule","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"prepare_campaign_schedule","title":"Prepare Campaign Schedule","description":"Check that a one-time or A/B campaign can be scheduled for send_at, and freeze exactly what it would send. Never schedules anything.\n\nsend_at is an ISO 8601 time with its UTC offset, in the future; convert the user's local time yourself. Runs the same checks as prepare_campaign_send. outcome ready returns a summary and a confirmation_token; not_ready lists what must change in problems. Set lists, the segment or a missing sending address with set_campaign_audience, and the subject, from name, from address or reply-to with update_campaign_message, then prepare again; an unverified sender domain or a missing A/B version can only be fixed in ActiveCampaign.\n\n**Show the summary message to the user and wait for their explicit yes** before calling confirm_campaign_schedule with that token. Set predictive_send only when the user asks for it. To send immediately, use prepare_campaign_send instead."}}},"/agents/mcp-gateway/campaign-send/send/confirm":{"post":{"description":"Send a prepared campaign now, only if it still matches what was prepared.\n\nThe token is single use. A stored send date is cleared first, as the campaign page does.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpSendResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"confirm-campaign-send","summary":"Confirm Campaign Send","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"confirm_campaign_send","title":"Confirm Campaign Send","description":"Send a campaign now that prepare_campaign_send prepared, after the user explicitly agreed to the summary it returned. Pass the same campaign_id and its confirmation_token.\n\nThe token works once and only for a short time. The campaign is re-read first: if its lists or segment, content, subject, preheader, sender, reply-to, sending address, campaign type or status changed since the prepare, nothing is sent and outcome is changed; prepare again and show the user the new summary. A recipient count that only moved as contacts joined or left still sends. expired means the token was already used or ran out. submitted_for_approval means the account's approver must approve it before it sends; refused carries the campaign service's reason.\n\nunconfirmed means the send was requested but its answer was lost: it may be sending. NEVER retry after unconfirmed; check its status with get_campaign."}}},"/agents/mcp-gateway/campaign-send/send/prepare":{"post":{"description":"Check a campaign can be sent now and freeze what it would send. Never sends.\n\nRuns Hosted's pre-send checks (lists, sending address, content, subject, sender and reply-to\nwith verified domains, a modifiable status). `ready` returns a summary and a token that\n`/send/confirm` takes within its lifetime.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareSendRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpPrepareResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"prepare-campaign-send","summary":"Prepare Campaign Send","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"prepare_campaign_send","title":"Prepare Campaign Send","description":"Check that a one-time or A/B campaign can be sent now, and freeze exactly what it would send. Never sends anything.\n\nRuns the checks ActiveCampaign runs before a send: at least one list, a sending address, content, a subject, a from name and address, a reply-to address, verified sender domains, the account's contact limits and the A/B test's settings. outcome ready returns a summary (audience, recipient count, subject, preheader, sender) and a confirmation_token, and its message says when the campaign needs approval before it sends; not_ready lists what must change in problems.\n\n**Fixing problems.** Set lists, the segment or a missing sending address with set_campaign_audience, and the subject, from name, from address or reply-to with update_campaign_message, then prepare again. No tool here can verify a sender domain, add an A/B test's second version, change its winner wait or split, or lift a contact limit: tell the user to fix those in ActiveCampaign.\n\n**Show the summary message to the user and wait for their explicit yes** before calling confirm_campaign_send with that token. Never confirm in the same response as the prepare. RSS, recurring, date-based and automation campaigns are refused as not_supported, and so is a paused one. A scheduled campaign can be sent now: its send date is cleared first. To send at a later time, use prepare_campaign_schedule instead."}}},"/agents/mcp-gateway/campaign-send/unschedule":{"post":{"description":"Cancel a campaign's scheduled send, returning it to a draft. Needs edit permission.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnscheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpSendResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"operationId":"unschedule-campaign","summary":"Unschedule Campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"x-mcp-tool":{"name":"unschedule_campaign","title":"Unschedule Campaign","description":"Cancel a campaign's scheduled send and return it to a draft with no send date, so it will not send. Answers at once and needs no confirmation token. A campaign that is not scheduled reports not_scheduled and nothing changes; one already sending or sent reports not_modifiable. Requires permission to edit campaigns."}}},"/aggregateRevenue/findByType":{"get":{"summary":"List aggregate revenue rows by revenue generator type","description":"Reads the aggregate revenue rows (the revenue recorded in one currency for one campaign or other revenue generator) of one revenue generator type, grouped and sorted. With the defaults it returns one row per currency that campaigns have revenue in, the most used currency first: the campaign and revenue reports of the app call it without parameters, to fill their currency picker, and read only `currency`. The other fields of a grouped row come from one of its rows, not a total.\n\nServed by a legacy file, `api/3/aggregateRevenue/findByType.php`, which accepts only GET and answers any other method with 405, an `Allow: GET` header and an empty body. Not paginated.","operationId":"list-aggregate-revenues-by-type","x-canonical-resource":"campaign","parameters":[{"name":"revenueGeneratorType","in":"query","required":false,"description":"Class name of the revenue generator, as stored on the rows. Defaults to `Campaign`.","schema":{"type":"string","default":"Campaign"}},{"name":"groupBy","in":"query","required":false,"description":"Column of the aggregate revenue rows to group them by. Defaults to `currency`.","schema":{"type":"string","default":"currency"}},{"name":"orderBy","in":"query","required":false,"description":"What the rows are sorted by, descending, before `currency` ascending. Defaults to `count(currency)`, the number of rows in each group.","schema":{"type":"string","default":"count(currency)"}}],"responses":{"200":{"description":"The rows, possibly none","content":{"application/json":{"schema":{"type":"object","required":["aggregateRevenues"],"properties":{"aggregateRevenues":{"description":"The rows as stored, every value a string","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the row","example":"12"},"created_utc_timestamp":{"type":"string","description":"When the row was created, in UTC","example":"2026-03-01 14:00:00"},"updated_utc_timestamp":{"type":"string","description":"When the row last changed, in UTC","example":"2026-03-04 09:30:00"},"total_revenue":{"type":"string","description":"Revenue recorded for the row's revenue generator in this currency","example":"45678"},"currency":{"type":"string","description":"Currency code, in upper case","example":"USD"},"revenue_generator_type":{"type":"string","description":"Class name of the revenue generator","example":"Campaign"},"revenue_generator_id":{"type":"string","description":"ID of the revenue generator, such as a campaign ID","example":"34"}}}}}},"example":{"aggregateRevenues":[{"id":"12","created_utc_timestamp":"2026-03-01 14:00:00","updated_utc_timestamp":"2026-03-04 09:30:00","total_revenue":"45678","currency":"USD","revenue_generator_type":"Campaign","revenue_generator_id":"34"}]}}}}},"deprecated":false,"x-internal":true}},"/ai/activity-feed":{"get":{"tags":["AI"],"summary":"List the calling user's AI customization history","description":"Returns one page of the AI customization changes the calling user made on this account, newest first: account instructions, memories, resource files, brand kits and permission rules that were added, changed or removed. Changes made by other users are not included. Both limit and offset must be sent; leaving either out answers 422. A limit above 100 is lowered to 100 without an error. meta.total counts the whole feed for the calling user, so a client pages until offset reaches it.","operationId":"list-ai-activity-feed-events","parameters":[{"name":"limit","in":"query","description":"Entries per page, as a positive integer. At most 100 are returned: anything above 100 is accepted and lowered to 100 without an error. Required: an omitted limit answers 422, as does 0 or a non-digit value.","required":true,"schema":{"type":"integer","minimum":1},"example":20},{"name":"offset","in":"query","description":"Entries to skip before the first returned, as a non-negative integer. Required: an omitted offset answers 422, as does a non-digit value. An offset past the end returns an empty history with the unchanged total.","required":true,"schema":{"type":"integer","minimum":0},"example":0}],"responses":{"200":{"description":"One page of the feed. Also the answer when the user has no history yet: total 0 and an empty history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityFeedHistoryResponse"},"example":{"meta":{"total":37},"history":[{"action":"memory-detected","title":"Memory detected","description":"Memory detected","snippet":"Always respond in a friendly tone","brand_id":null,"file_id":null,"user_name":"John Smith","user_id":42,"timestamp":"2026-02-16 14:30:00"},{"action":"brand-edited","title":"Brand edited","description":"Brand edited","snippet":"Acme Co","brand_id":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","file_id":null,"user_name":"John Smith","user_id":42,"timestamp":"2026-02-15 09:12:45"}]}}}},"422":{"description":"limit or offset was omitted, is not made of digits only, or limit is 0. One error per failed check, so an omitted limit yields two.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityFeedValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Limit must be a positive integer","source":{"pointer":"/data/attributes/limit"}}]}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/agent/onboarding/automation/brandkit":{"post":{"tags":["AI"],"summary":"Apply a brand kit to one automation campaign","description":"Background job of PUT /ai/agent/onboarding/automation/brandkit/{seriesid}: re-skins one campaign message with the brand kit and records the outcome on the request it belongs to. Queued by Hosted, one call per campaign. A repeat call re-skins the message again. Answers 403 when the API user may not manage automations and 500 when the re-skin failed.","operationId":"apply-a-brandkit-to-an-automation-campaign","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBrandkitApplyRequest"}}}},"responses":{"200":{"description":"The campaign was re-skinned. message is Brandkit request completed successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingMessageResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The re-skin failed; error is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/brandkit/{seriesid}":{"get":{"tags":["AI"],"summary":"Check the brand kit request for an automation","description":"Whether the latest request made with PUT /ai/agent/onboarding/automation/brandkit/{seriesid} finished. Answers 200 with success once the request completed or failed; a request still pending after 5 minutes is marked failed and answered as success false. Answers 404 when the automation has no request, 409 while the request is pending and under 5 minutes old, and 500 when the request record could not be read. No permission is checked.","operationId":"check-an-automation-brandkit-request","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation the brand kit request was made for.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The request finished. success is false when it failed or timed out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBrandkitStatusResponse"}}}},"404":{"description":"No request was made for this automation (error: No request found for the provided series ID.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}},"409":{"description":"The request is still pending; poll again (error: The request to add a brandkit to this automation is still pending. Please wait until it completes or fails.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}},"500":{"description":"The request record could not be read. error starts with Failed to check brandkit request status: followed by the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-internal":true},"put":{"tags":["AI"],"summary":"Apply a brand kit to an automation's campaigns","description":"Re-skins every campaign behind the automation's send steps with a brand kit, the account's primary one unless brandkitUuid names another. Records a request, queues one background job per campaign (POST /ai/agent/onboarding/automation/brandkit) and answers at once; poll GET /ai/agent/onboarding/automation/brandkit/{seriesid} for the outcome. A request still pending refuses a new one with 409. Answers 403 when the API user may not manage automations, 422 when the automation has no send steps, no brand kit could be found, or the send steps have no campaigns, and 500 when every job failed to queue.","operationId":"apply-a-brandkit-to-an-automation","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation whose campaigns to re-skin.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBrandkitRequest"}}}},"responses":{"200":{"description":"The jobs were queued. message is Brandkit add initialized successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingMessageResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"409":{"description":"A brand kit request for this automation is still pending (error: The request to add a brandkit to this automation is still pending. Please wait until it completes or fails.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}},"422":{"description":"The body failed validation, or nothing can be re-skinned. error is one of: No send actions found in the automation. Please ensure there are send actions to update.; No brandkit found. Please ensure a brandkit is available to add to the automation.; No campaigns found to update with the brandkit. Please ensure there are campaigns in the send actions.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}]}}}},"500":{"description":"Every job failed to queue (error: Failed to dispatch all brandkit requests for the automation.), or the request could not be recorded; then error starts with Failed to initialize adding brandkit to automation: followed by the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/build":{"post":{"tags":["AI"],"summary":"Save an automation from a drafted schema (agent onboarding)","description":"Persists the automation described by the schema JSON string from a prior draft call. A repeated sessionId returns the existing series. A missing sessionId, or a session with no prior build, still creates one. Answers 403 when the API user may not manage automations or when entitlements block triggers or actions in the proposal, and 500 when the builder or model fails. Internal twin of the public route, reached by the automation agent during onboarding.","operationId":"build-an-automation-for-the-agent","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuildRequest"}}}},"responses":{"200":{"description":"The saved automation, including series id and any scrubbed capabilities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuildDetailsResource"}}}},"403":{"description":"The API user may not manage automations, or the account lacks entitlements for triggers or actions in the proposal.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"},{"$ref":"#/components/schemas/AutomationBuildEntitlementDeniedResponse"}]}}}},"500":{"description":"The schema builder could not persist the automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/campaign":{"put":{"tags":["AI"],"summary":"Edit an automation campaign message","description":"Changes the message of one automation campaign: has the model rewrite the body, subject or preheader from prompt as the three change flags say, re-renders it into template when given, and sets subject and preheader as sent when given. Saves the result and tells the automation builder to refresh. Answers 400 when the edit could not be generated (for example a prompt with nothing to change), 403 when the API user may not manage automations, and 500 when the save failed.","operationId":"edit-an-automation-campaign-message","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCampaignEditRequest"}}}},"responses":{"200":{"description":"The message after the edit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCampaignEditedResponse"}}}},"400":{"description":"The edit could not be generated; error says why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The edit could not be saved; error is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"post":{"tags":["AI"],"summary":"Write the email for an automation send step","description":"Background job of an automation build: has the model write the email for one send block from the description and subject the schema proposed, and saves it into the placeholder campaign the block already points at. Queued by POST /ai/agent/onboarding/automation/build, one call per send block; also called by the automation agent when it drives generation itself. A repeat call rewrites the message. Answers 403 when the API user may not manage automations and 500 when the model or the save failed.","operationId":"write-an-automation-campaign-message","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCampaignGenerationRequest"}}}},"responses":{"200":{"description":"The message was written and saved. message is Campaign added successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingMessageResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The model or the save failed; error is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/campaign/{campaignId}/brandkit":{"get":{"tags":["AI"],"summary":"Retrieve the brand kit of an automation campaign","description":"The brand kit and template an automation campaign was generated with, so the agent can offer the same look for the next step. Both are null when the campaign has no generated-content record; brandkitUuid is also null when the account has no primary brand kit. Answers 500 when the record could not be read. No permission is checked.","operationId":"retrieve-an-automation-campaign-brandkit","parameters":[{"name":"campaignId","in":"path","description":"ID of the automation campaign.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The brand kit and template, each null when unknown.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCampaignBrandkitResponse"}}}},"500":{"description":"The record could not be read (error: Failed to retrieve campaign brandkit).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/ai/agent/onboarding/automation/can-edit/{seriesid}":{"get":{"tags":["AI"],"summary":"Check whether an automation can be edited (agent onboarding)","description":"Says whether one automation can be edited. Does not change the automation. Answers 200 with allow, reason, and a link to the automation. Allow is false when the automation is turned on (ACTIVE), missing (OTHER), still being updated (IN_PROGRESS), or an import still needs mapping (NEEDS_MAPPING). Answers 403 when the API user may not manage automations. sessionId, source, and currentSeriesId are accepted and logged. They do not change allow. Internal twin of the public route, reached by the automation agent during onboarding.","operationId":"check-an-automation-can-be-edited-for-the-agent","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation to check.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"sessionId","in":"query","description":"Automation agent session identifier when the caller is continuing a chat turn. Logged only. It does not change allow.","schema":{"type":"string"},"example":"sess_01h2x3y4z5"},{"name":"source","in":"query","description":"Request source. Logged only. It does not change allow.","schema":{"type":"string"},"example":"active-intelligence"},{"name":"currentSeriesId","in":"query","description":"Series id the caller is viewing. Logged only. It does not change allow.","schema":{"type":"integer"},"example":1000438}],"responses":{"200":{"description":"Whether the automation can be edited. allow is false when it cannot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCanEditResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"500":{"description":"The check could not be completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCanEditFailureResponse"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/ai/agent/onboarding/automation/describe/{seriesid}":{"get":{"tags":["AI"],"summary":"Describe an automation in plain language","description":"Has the model describe an existing automation from its schema: a name, a description and a benefits paragraph, with the stored configuration the description was written from. The route defaults seriesid to 0, so the trailing path segment may be left off and the automation named with name instead; with both, seriesid wins. Does not change the automation. Answers 404 when no automation matches, and 500 with error_code naming the stage that failed, UNKNOWN when neither an ID nor a name was given.","operationId":"describe-an-automation","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation to describe. Leave the segment off (or send 0) to look the automation up by name instead.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"name","in":"query","description":"Name of the automation to describe, used when the path carries no seriesid (the route also matches /automation/describe). Ignored when seriesid is given.","schema":{"type":"string"},"example":"Welcome series"}],"responses":{"200":{"description":"The description, with the stored configuration it was written from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationDescribeResponse"}}}},"404":{"description":"No automation has this ID or name. error_code is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingFailureResponse"}}}},"422":{"description":"The query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The description could not be written. error_code is MODEL_REQUEST, SCHEMA_PAYLOAD, SCHEMA_BUILDER or UNKNOWN; UNKNOWN also covers a call with neither seriesid nor name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingFailureResponse"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/ai/agent/onboarding/automation/edit/{seriesid}":{"put":{"tags":["AI"],"summary":"Edit an automation from a prompt (agent onboarding)","description":"Changes one automation from a natural-language prompt. A repeat call runs the edit again. A refused edit answers 409 with allow false, reason, link, and error_code EDIT_DENIED. Reason is ACTIVE when the automation is turned on, OTHER when it is missing, and NEEDS_MAPPING when an import still needs mapping. An edit or build already in progress answers 409 with error and error_code EDIT_IN_PROGRESS. Answers 403 when the API user may not manage automations, or when the account lacks entitlements for a trigger or action in the edit. Internal twin of the public route, reached by the automation agent during onboarding.","operationId":"edit-an-automation-for-the-agent","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation to edit.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditRequest"}}}},"responses":{"200":{"description":"The automation after the edit, including any trigger or action types removed for the account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditDetailsResource"}}}},"403":{"description":"The API user may not manage automations, or the account lacks entitlements for triggers or actions in the edit.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"},{"$ref":"#/components/schemas/AutomationEditEntitlementDeniedResponse"}]}}}},"409":{"description":"The edit was refused, or an edit or build is already in progress.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationEditDeniedResponse"},{"$ref":"#/components/schemas/AutomationEditInProgressResponse"}]}}}},"500":{"description":"The edit could not be applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/schema":{"post":{"tags":["AI"],"summary":"Draft an automation from a prompt (agent onboarding)","description":"Runs the automation schema builder on a natural-language prompt and returns a workflow proposal. Nothing is saved; persisting the automation requires a separate build call. Answers 403 when the API user may not manage automations, 422 when the model returns more than one workflow in one call, and 500 when the builder or model fails. Internal twin of the public route, reached by the automation agent during onboarding.","operationId":"generate-an-automation-schema-for-the-agent","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaRequest"}}}},"responses":{"200":{"description":"A workflow proposal plus any trigger or action types removed for the account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaProposal"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The proposal must contain exactly one workflow.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}},"500":{"description":"The schema builder or model could not produce a proposal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/agent/onboarding/automation/segment":{"post":{"tags":["AI"],"summary":"Build the segment for an automation step","description":"Background job of an automation build: has the model turn the description of one condition into a segment and attaches it to the block (a wait or if/else step) or the start (trigger) named in the body. Queued by POST /ai/agent/onboarding/automation/build, one call per step that needs a segment. A repeat call builds the segment again. Answers 403 when the API user may not manage automations and 500 when the model or the save failed, or when the body named neither a block nor a start.","operationId":"build-an-automation-step-segment","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSegmentGenerationRequest"}}}},"responses":{"200":{"description":"The segment was built and attached. message is Segment added successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingMessageResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The model or the save failed, or no block or start was named; error is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOnboardingErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/async":{"post":{"tags":["AI"],"summary":"Run an onboarding recipe selection or personalization job","description":"Worker endpoint: Hosted dispatches this to itself through the queue (AiQHSClient, endpoint api/3/ai/automations/async); not a user API. POST /ai/automations/onboarding queues it with function asyncRecipeSelection, and that job queues it once per selected recipe with function asyncPersonalization. asyncRecipeSelection asks the model to pick recipe templates for the persona, stores them as queued personalized recipes, releases the onboarding lock and queues the personalization jobs. asyncPersonalization rewrites the stored recipe named by recipe_hash for the persona (its name and description when personalizeStartPoint is metadata, then its content variables) and overwrites the stored recipe with the result and status done, or error when the model call failed. That overwrite is why the operation is marked destructive although selection only adds records. The onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag, so the route currently answers 404 on every call. Behind that gate the action answers 400 when the body is not JSON or a field is missing or invalid, and 200 with message done once the job ran, whether or not it succeeded: a failed selection marks the account's recipe selection in error, so GET /ai/automations/recipes answers 400, and a failed personalization leaves the recipe with status error.","operationId":"run-an-onboarding-automation-recipe-job","requestBody":{"description":"The job to run, as the dispatcher writes it.","required":true,"content":{"application/json":{"schema":{"required":["function","persona","onboardingProcessStartTime"],"properties":{"function":{"description":"Which job to run: asyncRecipeSelection picks and stores recipes for the persona, asyncPersonalization rewrites one stored recipe.","type":"string","enum":["asyncRecipeSelection","asyncPersonalization"],"example":"asyncPersonalization"},"persona":{"description":"The persona the recipes are personalized for, as the PHP-serialized AutomationRecipesCommon\\Persona\\Persona object the dispatcher writes; the worker unserializes it.","type":"string","example":"O:64:\"ActiveCampaign\\Hosted\\AI\\AutomationRecipesCommon\\Persona\\Persona\":7:{...}"},"onboardingProcessStartTime":{"description":"Unix timestamp with microseconds at which POST /ai/automations/onboarding started the selection; used for duration metrics.","type":"number","format":"double","example":1715371017.6016},"recipe_hash":{"description":"Hash of the stored personalized recipe to rewrite. Required for asyncPersonalization and must name a stored recipe (400 Invalid recipe_hash otherwise); ignored for asyncRecipeSelection.","type":"string","example":"a1b2c3d4"},"personalizationProcessStartTime":{"description":"Unix timestamp with microseconds at which the selection job queued this personalization; used for duration metrics. Required for asyncPersonalization.","type":"number","format":"double","example":1715371019.2201},"personalizeStartPoint":{"description":"For asyncPersonalization: metadata (the default) rewrites the recipe name and description before its content variables; variables rewrites only the variables, for a recipe whose name and description are already personalized.","type":"string","enum":["metadata","variables"],"example":"metadata"}},"type":"object"},"example":{"function":"asyncPersonalization","persona":"O:64:\"ActiveCampaign\\Hosted\\AI\\AutomationRecipesCommon\\Persona\\Persona\":7:{...}","onboardingProcessStartTime":1715371017.6016,"recipe_hash":"a1b2c3d4","personalizationProcessStartTime":1715371019.2201,"personalizeStartPoint":"metadata"}}}},"responses":{"200":{"description":"The job ran. Its outcome is recorded on the stored recipes, not in this body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingAsyncDoneResponse"}}}},"400":{"description":"The body is not JSON (Incoming JSON malformed), or function, persona or onboardingProcessStartTime is missing, function is not one of the two jobs, or for asyncPersonalization recipe_hash is missing or names no stored recipe or personalizationProcessStartTime is missing."},"404":{"description":"Always, while the onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/build":{"post":{"tags":["AI"],"summary":"Save an automation from a drafted schema","description":"Persists the automation described by the schema JSON string from a prior draft call. A repeated sessionId returns the existing series. A missing sessionId, or a session with no prior build, still creates one. Answers 403 when the API user may not manage automations or when entitlements block triggers or actions in the proposal, and 500 when the builder or model fails.","operationId":"build-an-automation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuildRequest"}}}},"responses":{"200":{"description":"The saved automation, including series id and any scrubbed capabilities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuildDetailsResource"}}}},"403":{"description":"The API user may not manage automations, or the account lacks entitlements for triggers or actions in the proposal.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"},{"$ref":"#/components/schemas/AutomationBuildEntitlementDeniedResponse"}]}}}},"500":{"description":"The schema builder could not persist the automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false}},"/ai/automations/build-list":{"get":{"tags":["AI"],"summary":"List automation starts and steps for AI build","description":"Returns this account's automation start triggers and action steps, each marked buildable or not with a reason. Does not include configuration, runs, or params from the schema generator. Does not call a model or save an automation. Answers 403 when the API user may not manage automations.","operationId":"list-automation-build-list","responses":{"200":{"description":"Catalog of starts and steps for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuildListResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}}},"x-canonical-resource":"automation"}},"/ai/automations/goal/industry":{"get":{"tags":["AI"],"summary":"List the onboarding goals worded for the account's industry","description":"Returns the five onboarding goals an account can ask automation recipes for, each with a title worded for the industry the account gave at onboarding and translated into the account's language. An account with no or an unknown industry gets the generic wording. key is the value the other /ai/automations/goal endpoints take as goal.","operationId":"list-automation-industry-goals","responses":{"200":{"description":"The goals, in a fixed order.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AutomationIndustryGoal"}},"example":[{"key":"Send targeted and effective campaigns","title":"Targeted campaigns for online shoppers"},{"key":"Grow my list and generate more leads","title":"Boost leads and customer acquisition strategies"},{"key":"Convert my current leads to customers","title":"Convert leads into paying customers"},{"key":"Automate my internal processes","title":"Enhance workflow efficiency"},{"key":"Nurture my contacts for action","title":"Encourage action from leads"}]}}}},"x-canonical-resource":"automation","x-internal":true}},"/ai/automations/goal/personalize":{"post":{"tags":["AI"],"summary":"Run a queued automation recipe personalization","description":"Worker endpoint: Hosted dispatches this to itself through the queue (RecipeSelectionService::ENDPOINT_PERSONALIZE_ASYNC), once per recipe picked by POST /ai/automations/goal/select and again from POST /ai/automations/personalize; not a user API. Overwrites the stored recipe's personalization: from startpoint metadata it has a model write the personalized name and description, then the content for the template's variables; from startpoint variables it writes the variables only. Each step marks the recipe in_progress and then done, or error when the model call fails; a failure is recorded on the recipe and still answers 200 so the queue does not retry. Answers 422 when goal, starttime, personalization_starttime or hash is missing or invalid, hash names no recipe stored for the goal, or startpoint is neither metadata nor variables.","operationId":"run-an-automation-goal-recipe-personalization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipePersonalizationDispatchRequest"}}}},"responses":{"200":{"description":"The job ran; the outcome is on the stored recipe's personalizationStatus, not reported here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeDoneResponse"}}}},"422":{"description":"goal is missing or not an onboarding goal; starttime or personalization_starttime is missing or not a number; hash is missing or names no recipe stored for the goal; or startpoint is neither metadata nor variables."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/goal/recipes":{"get":{"tags":["AI"],"summary":"List the automation recipes stored for a goal","description":"Returns the recipes selected and personalized for the goal that have not been imported yet (recipes marked used are left out). Polled after POST /ai/automations/goal/recipes: answers 409 with no body while nothing is stored for the goal yet, and 400 once the selection job has recorded a failure for the goal (DELETE /ai/automations/goal/recipes clears it). A 200 can still list recipes that are queued, in progress or failed; check each personalizationStatus. Answers 422 when goal is missing or not an onboarding goal.","operationId":"list-automation-goal-recipes","parameters":[{"name":"goal","in":"query","description":"The goal whose stored recipes to list. One of the onboarding goals, as key in GET /ai/automations/goal/industry; matched case-insensitively.","required":true,"schema":{"type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"]},"example":"Send targeted and effective campaigns"}],"responses":{"200":{"description":"The recipes stored for the goal, possibly none when every one has been imported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipesResponse"},"example":{"recipes":[{"hash":"_uw6ffp","name":"Share new blog posts with your readers","description":"Email every new blog post to your subscribers to grow your readership and keep leads engaged.","originalName":"Deliver new blog posts","originalDescription":"Deliver new blog posts to your subscribers to raise awareness of your content, grow your audience and nurture leads.","touchpoints":1,"personalizationStatus":"done","personalizedVariables":{"NEW_BLOG_POST":{"name":"New post: 5 ways to grow your list","subject":"Fresh from the blog","email_text":"<p>Our latest post is live.</p>"}}}]}}}},"400":{"description":"Recipe selection failed: the selection job recorded an error for this goal. The detail is \"Recipe selection failed\"."},"409":{"description":"No recipes are stored for the goal yet. Empty body; poll again, or start selection with POST /ai/automations/goal/recipes."},"422":{"description":"goal is missing, blank, or not an onboarding goal."}},"x-canonical-resource":"automation","x-internal":true},"post":{"tags":["AI"],"summary":"Start selecting automation recipes for a goal","description":"Queues the job that picks recipe templates for the goal from the account's onboarding persona and brand kit (POST /ai/automations/goal/select), which then queues a personalization job per picked recipe. Answers 200 with status dispatched once queued, status done without queueing when recipes are already stored for the goal, and status redlocked when another request holds the selection lock for this goal. Clears a failure recorded by an earlier selection before queueing. Answers 500 with status dispatch_failed when queueing throws, and 422 when goal is missing or not an onboarding goal. Poll GET /ai/automations/goal/recipes for the result.","operationId":"select-automation-goal-recipes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipesSelectRequest"}}}},"responses":{"200":{"description":"Selection is queued (dispatched), already running (redlocked) or already finished (done).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeSelectionStartedResponse"}}}},"422":{"description":"goal is missing, blank, not a string, or not an onboarding goal."},"500":{"description":"The selection job could not be queued (status dispatch_failed). The goal's lock is released, so the call can be repeated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeSelectionFailedResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete the automation recipes stored for a goal","description":"Removes every recipe stored for the goal, whatever its personalizationStatus, along with the failure flag a selection job may have recorded for it, so POST /ai/automations/goal/recipes starts over. Without goal, the stored recipes and failure flags of every goal are removed. Answers 500 when the deletion throws, and 422 when goal is given but is not an onboarding goal.","operationId":"delete-automation-goal-recipes","parameters":[{"name":"goal","in":"query","description":"The goal whose stored recipes to delete. One of the onboarding goals, as key in GET /ai/automations/goal/industry; matched case-insensitively. Left out, the recipes of every goal are deleted.","schema":{"type":"string","enum":["Send targeted and effective campaigns","Grow my list and generate more leads","Convert my current leads to customers","Automate my internal processes","Nurture my contacts for action"]},"example":"Send targeted and effective campaigns"}],"responses":{"204":{"description":"The recipes are deleted. Empty body."},"422":{"description":"goal is given but is not an onboarding goal."},"500":{"description":"Deleting the stored recipes threw. The detail carries the message."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/automations/goal/select":{"post":{"tags":["AI"],"summary":"Run a queued automation recipe selection","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/automations/goal/recipes (RecipeSelectionService::ENDPOINT_SELECTION_ASYNC); not a user API. Asks a model to match the active recipe templates to the account's persona and brand kit, stores each picked recipe for the goal with status queued, and queues a personalization job (POST /ai/automations/goal/personalize) for each. When recipes are already stored for the goal it re-queues personalization for those instead of selecting again. A failure is recorded on the goal, which turns GET /ai/automations/goal/recipes into a 400, and still answers 200 so the queue does not retry. Answers 422 when goal or starttime is missing or invalid.","operationId":"run-an-automation-goal-recipe-selection","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeSelectionDispatchRequest"}}}},"responses":{"200":{"description":"The job ran; a failure is recorded on the goal, not reported here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeDoneResponse"}}}},"422":{"description":"goal is missing or not an onboarding goal, or starttime is missing or not a number."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/import":{"post":{"tags":["AI"],"summary":"Create an automation from a personalized goal recipe","description":"Builds the automation described by the recipe template named by recipeHash, fills its campaigns with the content personalized for the account under the goal, saves it as a new inactive automation (series) and labels it \"AI - {goal}\", plus the label named by labelId. With markUsed (the default) the stored recipe is marked used and records the new automation id, so GET /ai/automations/goal/recipes stops listing it. Answers 403 when the user may not manage automations, 400 when the stored recipe is not done (queued, in_progress, error or used) or the import itself fails (a personalized variable the template needs is missing, or the legacy import refuses the recipe), and 422 when goal or recipeHash is missing, names no onboarding goal, no template or no stored recipe, or labelId names no label.","operationId":"import-an-automation-goal-recipe","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeImportRequest"}}}},"responses":{"201":{"description":"The automation was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeImportedResponse"}}}},"400":{"description":"The stored recipe is not done (its personalizationStatus is queued, in_progress, error or used), or the import failed: the personalized content lacks a variable the template needs, or the legacy import refused the recipe. The detail names the cause."},"403":{"description":"The user lacks the manage-automations permission."},"422":{"description":"goal or recipeHash is missing or not a string, goal is not an onboarding goal, recipeHash names no recipe template or no recipe stored for the goal, or labelId is not an integer or names no label."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/onboarding":{"post":{"tags":["AI"],"summary":"Select onboarding automation recipes for a persona","description":"Starts the onboarding recipe selection for the persona in the body: locks the account against a second run, clears a previous selection error and queues a selection job to POST /ai/automations/async (function asyncRecipeSelection), which picks recipe templates for the persona and queues one personalization job per recipe. Poll GET /ai/automations/recipes for the result. The onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag, so the route currently answers 404 on every call. Behind that gate the action answers 400 when the body is not JSON (Incoming JSON malformed) or has no persona key (Missing persona object); 200 with status done when recipes are already stored for the account, redlocked while a selection job holds the lock, or dispatched when the job was queued; and 500 with an empty body when queueing fails, after releasing the lock.","operationId":"select-onboarding-automation-recipes","requestBody":{"description":"The persona the recipes are selected and personalized for. Every key of persona is optional and defaults to empty.","required":true,"content":{"application/json":{"schema":{"required":["persona"],"properties":{"persona":{"description":"Who the account belongs to, as collected during onboarding. Each key is optional; a missing key is stored as an empty string or list.","properties":{"name":{"description":"The user's name.","type":"string","example":"Jane Doe"},"email":{"description":"The user's email address.","type":"string","example":"jane@example.com"},"company":{"description":"Name of the business.","type":"string","example":"Acme Fitness"},"industry":{"description":"Industry of the business.","type":"string","example":"Health & Fitness"},"goals":{"description":"What the user wants to achieve with automations.","type":"array","items":{"type":"string"},"example":["Welcome new members","Win back inactive contacts"]},"role":{"description":"The user's role in the business.","type":"string","example":"Owner"},"target_audiences":{"description":"Who the business markets to.","type":"array","items":{"type":"string"},"example":["Gym members"]}},"type":"object"}},"type":"object"},"example":{"persona":{"name":"Jane Doe","email":"jane@example.com","company":"Acme Fitness","industry":"Health & Fitness","goals":["Welcome new members"],"role":"Owner","target_audiences":["Gym members"]}}}}},"responses":{"200":{"description":"What the server did: done when recipes are already stored, redlocked when a selection job is already running, dispatched when one was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingRecipeStatusResponse"}}}},"400":{"description":"The body is not JSON (Incoming JSON malformed) or has no persona key (Missing persona object)."},"404":{"description":"Always, while the onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag."},"500":{"description":"Queueing the selection job failed. The lock is released; the body is empty."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/personalize":{"post":{"tags":["AI"],"summary":"Personalize a failed goal recipe again","description":"Retries personalization of one stored recipe whose personalizationStatus is error: sets it back to queued and queues a personalization job (POST /ai/automations/goal/personalize) that overwrites its personalized name, description and variables. The job starts at the metadata when name or description is still null, otherwise at the variables. Answers 200 as soon as the job is queued; poll GET /ai/automations/goal/recipes for the result. Answers 400 when the recipe is queued, in_progress, done or used, 422 when goal or recipeHash is missing, names no onboarding goal, no template or no stored recipe, and 500 when updating the recipe throws (a failure to queue is recorded on the recipe as error instead).","operationId":"repersonalize-an-automation-goal-recipe","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeRepersonalizeRequest"}}}},"responses":{"200":{"description":"The recipe is queued for personalization again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationGoalRecipeDoneResponse"}}}},"400":{"description":"The stored recipe is not in error: its personalizationStatus is queued, in_progress, done or used."},"422":{"description":"goal or recipeHash is missing or not a string, goal is not an onboarding goal, or recipeHash names no recipe template or no recipe stored for the goal."},"500":{"description":"Updating the stored recipe threw. The detail carries the message."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/automations/recipes":{"get":{"tags":["AI"],"summary":"List the personalized onboarding automation recipes","description":"Returns the automation recipes the onboarding workflow selected and personalized for the account, leaving out those already imported as automations. The onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag, so the route currently answers 404 on every call. Behind that gate the action takes no parameters and answers 400 (Recipe selection failed) when the last selection job marked an error, 409 while no recipes are stored yet, which the onboarding overview long-polls on, and 200 with the stored recipes, each carrying its personalizationStatus. Empty recipes once every stored recipe has been used.","operationId":"list-onboarding-automation-recipes","responses":{"200":{"description":"The stored recipes not yet imported as automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingRecipesResponse"}}}},"400":{"description":"The last recipe selection job failed (Recipe selection failed). POST /ai/automations/onboarding clears the error and tries again."},"404":{"description":"Always, while the onboarding workflow is switched off in AutomationRecipesWorkflows::getAuthFlag."},"409":{"description":"No recipes are stored yet: selection has not been started or is still running. Poll again."}},"x-canonical-resource":"automation","x-internal":true}},"/ai/automations/schema":{"post":{"tags":["AI"],"summary":"Draft an automation from a prompt","description":"Runs the automation schema builder on a natural-language prompt and returns a workflow proposal. Nothing is saved; persisting the automation requires a separate build call. Answers 403 when the API user may not manage automations, 422 when the model returns more than one workflow in one call, and 500 when the builder or model fails.","operationId":"generate-an-automation-schema","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaRequest"}}}},"responses":{"200":{"description":"A workflow proposal plus any trigger or action types removed for the account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaProposal"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"422":{"description":"The proposal must contain exactly one workflow.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}},"500":{"description":"The schema builder or model could not produce a proposal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false}},"/ai/automations/{id}/can-edit":{"get":{"tags":["AI"],"summary":"Check whether an automation can be edited","description":"Says whether one automation can be edited. Does not change the automation. Answers 200 with allow, reason, and a link to the automation. Allow is false when the automation is turned on (ACTIVE), missing (OTHER), still being updated (IN_PROGRESS), or an import still needs mapping (NEEDS_MAPPING). Answers 403 when the API user may not manage automations. sessionId, source, and currentSeriesId are accepted and logged. They do not change allow.","operationId":"check-an-automation-can-be-edited","parameters":[{"name":"id","in":"path","description":"Id of the automation to check.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"sessionId","in":"query","description":"Automation agent session identifier when the caller is continuing a chat turn. Logged only. It does not change allow.","schema":{"type":"string"},"example":"sess_01h2x3y4z5"},{"name":"source","in":"query","description":"Request source. Logged only. It does not change allow.","schema":{"type":"string"},"example":"active-intelligence"},{"name":"currentSeriesId","in":"query","description":"Series id the caller is viewing. Logged only. It does not change allow.","schema":{"type":"integer"},"example":1000438}],"responses":{"200":{"description":"Whether the automation can be edited. allow is false when it cannot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCanEditResponse"}}}},"403":{"description":"The API user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"}}}},"500":{"description":"The check could not be completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCanEditFailureResponse"}}}}},"x-canonical-resource":"automation"}},"/ai/automations/{id}/edit":{"put":{"tags":["AI"],"summary":"Edit an automation from a prompt","description":"Changes one automation from a natural-language prompt. A repeat call runs the edit again. A refused edit answers 409 with allow false, reason, link, and error_code EDIT_DENIED. Reason is ACTIVE when the automation is turned on, OTHER when it is missing, and NEEDS_MAPPING when an import still needs mapping. An edit or build already in progress answers 409 with error and error_code EDIT_IN_PROGRESS. Answers 403 when the API user may not manage automations, or when the account lacks entitlements for a trigger or action in the edit.","operationId":"edit-an-automation","parameters":[{"name":"id","in":"path","description":"Id of the automation to edit.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditRequest"}}}},"responses":{"200":{"description":"The automation after the edit, including any trigger or action types removed for the account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditDetailsResource"}}}},"403":{"description":"The API user may not manage automations, or the account lacks entitlements for triggers or actions in the edit.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationSchemaPermissionDeniedResponse"},{"$ref":"#/components/schemas/AutomationEditEntitlementDeniedResponse"}]}}}},"409":{"description":"The edit was refused, or an edit or build is already in progress.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AutomationEditDeniedResponse"},{"$ref":"#/components/schemas/AutomationEditInProgressResponse"}]}}}},"500":{"description":"The edit could not be applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEditOperationFailureResponse"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false}},"/ai/brand":{"post":{"summary":"Create a brand kit","description":"Create a new brand kit, from a website URL or from manually supplied data.","operationId":"create-a-brand-kit","x-canonical-resource":"brand_kit","x-destructive":false,"x-bulk-operation":false,"tags":["AI"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitCreateRequest"}}}},"responses":{"201":{"description":"The created brand kit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitCreateResponse"}}}}}},"get":{"summary":"List all brand kits","description":"List every brand kit on the account. Each item has the same shape as Retrieve a brand kit; the primary kit carries brandkit.isPrimary=true.","operationId":"list-all-brand-kits","x-canonical-resource":"brand_kit","tags":["AI"],"parameters":[{"name":"orders[created_timestamp]","in":"query","required":false,"description":"Order brand kits by creation time: ASC for oldest first, DESC for newest first. Omitted, the order is unspecified. created_timestamp is the only sortable field.","schema":{"type":"string","enum":["ASC","DESC"]}}],"responses":{"200":{"description":"The account's brand kits","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BrandKit"}}}}}}}},"/ai/brand/candidates":{"get":{"tags":["AI"],"summary":"Retrieve the account's brand candidates","description":"Returns the account's current set of proposed brands and which one is applied. A set past its expiresAt is answered as no set. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"retrieve-brand-candidates","responses":{"200":{"description":"The current set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateSetResponse"}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"404":{"description":"The account has no brand candidates, or its set has expired."},"500":{"description":"The set could not be read."}},"x-canonical-resource":"brand_kit","x-internal":true},"post":{"tags":["AI"],"summary":"Write or replace the account's brand candidates","description":"Stores a set of proposed brands for the account, replacing any set it already has. Candidate ids are assigned here, so the request names the recommended and active candidates by position. Nothing is created from the set and no background work starts; a brand kit appears only when a candidate is committed. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"replace-brand-candidates","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidatesWriteRequest"}}}},"responses":{"201":{"description":"The stored set, with the ids the candidates were given.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateSetResponse"}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"409":{"description":"Another change to the account's brand candidates is still in progress."},"422":{"description":"candidates is empty, an entry is not an object, names an unknown source or has no kitBody a brand kit can be built from, recommendedIndex or activeIndex points at no submitted candidate, or expiresAt is missing, not an absolute instant, or already past."},"500":{"description":"The set could not be stored."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/candidates/active":{"patch":{"tags":["AI"],"summary":"Apply a brand candidate","description":"Makes one candidate of the current set the account's applied brand, the one generation reads. Once a candidate has been committed, only that candidate may be re-applied; the call then changes nothing. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"set-active-brand-candidate","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateActiveRequest"}}}},"responses":{"200":{"description":"The set with the candidate applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateSetResponse"}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"404":{"description":"The account has no live set, or candidateId is not in it."},"409":{"description":"A different candidate of this set has already been committed, or another change to the account's brand candidates is still in progress."},"422":{"description":"candidateId is missing."},"500":{"description":"The set could not be updated."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/candidates/from-account":{"post":{"tags":["AI"],"summary":"Propose brands from the account details","description":"Asks a model for brand looks built from what the account says about itself, seeded by the saved brand kit or the sent-campaigns candidate when there is one, and adds them to the set as llm-inferred candidates, replacing any earlier ones; the set is created when there is none. Nothing is applied and the recommendation is not moved. The body is optional: a seedCandidateId rebuilds the looks around that candidate (or saved kit) instead, count sizes the lineup, and industry is a fallback for an account whose onboarding names none. The call waits for the model. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"propose-brand-candidates-from-account","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateFromAccountRequest"}}}},"responses":{"201":{"description":"The candidates that were added, and the set they are in: the plain shape for a build from the account details, the refinement shape when the body named a seedCandidateId.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BrandCandidateFromAccountResponse"},{"$ref":"#/components/schemas/BrandCandidateRefinementResponse"}]}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"404":{"description":"seedCandidateId is not a candidate of the live set nor one of the account's saved brand kits, or there is no live set to refine."},"409":{"description":"A brand kit has already been created from the set (plain build only), or another change to the account's brand candidates is still in progress."},"422":{"description":"The model did not answer, nothing it proposed was usable, count is outside 3 to 5, seedCandidateId is blank, industry is blank or longer than 100 characters, the seed has no colours or fonts to build from, or the set already holds as many prior lineups as it keeps (canRefine is false)."},"500":{"description":"The proposal could not be made."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/candidates/from-send-history":{"post":{"tags":["AI"],"summary":"Propose a brand from the account's sent campaigns","description":"Reads the account's recent sent campaigns, leaving out duplicates, placeholders and campaigns generated by AI, and adds the palette and typefaces they agree on to the set as a past-campaigns candidate, replacing any earlier one; the set is created when there is none. Takes no body. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"propose-brand-candidate-from-send-history","responses":{"201":{"description":"The candidate that was added, and the set it is in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateFromSendHistoryResponse"}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"409":{"description":"A brand kit has already been created from the set, or another change to the account's brand candidates is still in progress."},"422":{"description":"The account has too few usable sent campaigns, the usable ones were all generated here, or they do not agree on a palette or a typeface."},"500":{"description":"The campaigns could not be read."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/candidates/from-website":{"post":{"tags":["AI"],"summary":"Propose a brand from a website","description":"Reads the given website and adds what it finds to the account's set as a website-firecrawl candidate, replacing any earlier website candidate; the set is created when there is none. One read per domain is spent and cached, so a repeat for the same domain answers from the cache without spending the account's daily scrape budget. The call waits for the read. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"propose-brand-candidate-from-website","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateFromWebsiteRequest"}}}},"responses":{"201":{"description":"The candidate that was added, and the set it is in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateFromWebsiteResponse"}}}},"403":{"description":"The account is a resold account, or the ai-agent-inferred-brand flag is off for it."},"409":{"description":"A brand kit has already been created from the set, another read of this domain or another change to the set is still in progress."},"422":{"description":"domain is missing or not a usable website address, names a social media profile or an email provider, could not be read, or was read and carried no brand; or trigger is not rebrand or use-my-website."},"429":{"description":"The account has read as many websites as it may in a day."},"500":{"description":"The brand could not be read."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/candidates/{candidateId}/commit":{"post":{"tags":["AI"],"summary":"Create a brand kit from a candidate","description":"Creates the account's brand kit from one candidate of the current set, the same way Create a brand kit does, so templates, images, competitors and tone are produced for it once. One set makes one decision: committing the same candidate again answers 200 with the same kit and creates nothing, committing a different one is refused. Available on accounts with the ai-agent-inferred-brand flag; refused for resold accounts.","operationId":"commit-a-brand-candidate","parameters":[{"name":"candidateId","in":"path","description":"Id of the candidate to commit.","required":true,"schema":{"type":"string"},"example":"018f3c2a-5b7d-7e4f-9a1b-2c3d4e5f6a7b"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateCommitRequest"}}}},"responses":{"200":{"description":"This candidate had already been committed; the same brand kit is answered and nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateCommitResponse"}}}},"201":{"description":"The brand kit was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCandidateCommitResponse"}}}},"403":{"description":"The account is a resold account, the ai-agent-inferred-brand flag is off for it, or it may not create a brand kit."},"404":{"description":"The account has no live set, or candidateId is not in it."},"409":{"description":"A different candidate of this set has already been committed, or another change to the account's brand candidates is still in progress."},"422":{"description":"A brand kit cannot be built from the candidate: its kit body is unreadable or names a social media profile or an email provider, or the account has reached its brand kit limit."},"500":{"description":"The brand kit could not be created."}},"x-canonical-resource":"brand_kit","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/primary":{"get":{"summary":"Retrieve the default (primary) brand kit","description":"Get the account's default brand kit, also called its primary brand kit: which kit is the default now, falling back to the most recently created one if none is marked primary. Use it to confirm the current default, including after Set the default (primary) brand kit.","operationId":"retrieve-primary-brand-kit","x-canonical-resource":"brand_kit","tags":["AI"],"responses":{"200":{"description":"The default (primary) brand kit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitPrimary"}}}}},"parameters":[{"name":"includeSiteSummary","in":"query","required":false,"schema":{"type":"boolean"},"description":"Include the LLM-generated site summary in the response, generating it on demand if a scraped snapshot exists but no summary has been produced yet. Never scrapes."},{"name":"includeSitePages","in":"query","required":false,"schema":{"type":"boolean"},"description":"Include the stored site page snapshots the summary is built from."}]}},"/ai/brand/{uuid}":{"get":{"summary":"Retrieve a brand kit","description":"Get a single brand kit by UUID.","operationId":"retrieve-a-brand-kit","x-canonical-resource":"brand_kit","tags":["AI"],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Brand kit UUID."}],"responses":{"200":{"description":"The requested brand kit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKit"}}}}}},"patch":{"summary":"Update a brand kit","description":"Update the properties of an existing brand kit. A property left out of brandData keeps its stored value; one sent as null, an empty string or an empty list is cleared. Objects (colors, fonts, companyLocation) are merged key by key, and a list (links, logos, industries and so on) is replaced by the list sent, so send every entry to keep. Which kit is the account's primary kit is not part of that data: isPrimary is ignored if sent, and Set the default (primary) brand kit is the operation that changes it.","operationId":"update-a-brand-kit","x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"tags":["AI"],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Brand kit UUID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitUpdateRequest"}}}},"responses":{"200":{"description":"The updated brand kit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKit"}}}}}},"delete":{"summary":"Delete a brand kit","description":"Permanently delete a brand kit together with its generated templates, preview images and brand history. Deleting the primary brand kit makes the most recently created remaining kit primary.","operationId":"delete-a-brand-kit","x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"tags":["AI"],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Brand kit UUID."}],"responses":{"204":{"description":"The brand kit was deleted"},"404":{"description":"No brand kit with this UUID exists on the account"}}}},"/ai/brand/{uuid}/brand-history":{"get":{"tags":["AI"],"summary":"Retrieve a brand kit's website history","description":"Get the latest stored snapshot of the brand's homepage as markdown and every recorded change to it, for any brand kit. When nothing has been stored yet the homepage is scraped first, so the first call takes longer. Set includeSitePages to also get the stored important pages of the website with their recent changes.","operationId":"retrieve-brand-kit-history","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},{"name":"includeSitePages","in":"query","description":"Set to true (or 1, yes, on) to also return the stored important pages of the website and their recent changes under sitePages. Anything else, or leaving it out, returns the homepage only.","schema":{"type":"string"},"example":"true"}],"responses":{"200":{"description":"The homepage snapshot and its history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandHistoryResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account, or its website could not be read and no history exists yet."},"500":{"description":"The history could not be read."}},"x-canonical-resource":"brand_kit"}},"/ai/brand/{uuid}/competitors":{"post":{"tags":["AI"],"summary":"Refresh a brand kit's competitors","description":"Queues a new competitors extraction for the brand kit and returns without waiting for it. The stored competitors are replaced when it finishes; poll Retrieve a brand kit's competitors for progress. Refused while an extraction is already pending.","operationId":"refresh-brand-kit-competitors","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"201":{"description":"The extraction was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitJobDispatchedResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"409":{"description":"A competitors extraction for this brand kit is already in progress."},"500":{"description":"The extraction could not be queued."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"tags":["AI"],"summary":"Retrieve a brand kit's competitors","description":"Get the competitors of any brand kit, not only the primary one. Competitors are stored apart from the brand kit record, so Retrieve a brand kit and List all brand kits do not return them. An empty list means the kit has no competitors only when status is complete; when status is not_started, pending or failed the competitors are not available yet.","operationId":"retrieve-brand-kit-competitors","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The brand kit's competitors and their extraction status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitCompetitorsResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account"}},"x-canonical-resource":"brand_kit"}},"/ai/brand/{uuid}/image-settings":{"get":{"tags":["AI"],"summary":"Retrieve a brand kit's image settings","description":"Get whether scheduled brand monitoring automatically adds new website images to the brand kit.","operationId":"retrieve-brand-kit-image-settings","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The brand kit's image settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitImageSettings"}}}},"404":{"description":"No brand kit with this UUID exists on the account"},"500":{"description":"The image settings could not be read"}},"x-canonical-resource":"brand_kit","x-internal":true},"put":{"tags":["AI"],"summary":"Update a brand kit's image settings","description":"Turn on or off automatically adding new website images to the brand kit during scheduled brand monitoring.","operationId":"update-brand-kit-image-settings","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitImageSettings"}}}},"responses":{"200":{"description":"The saved image settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitImageSettings"}}}},"404":{"description":"No brand kit with this UUID exists on the account"},"422":{"description":"autoAddImages is missing"},"500":{"description":"The image settings could not be saved"}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/{uuid}/primary":{"patch":{"summary":"Set the default (primary) brand kit","description":"Make one brand kit the account's default, also called its primary brand kit: the \"Set as default brand\" action. The named kit becomes primary and every other brand kit on the account stops being primary. Takes no request body and changes none of the kit's own data. Update a brand kit cannot change which kit is primary. The response body is empty; read Retrieve the default (primary) brand kit to confirm the new default.","operationId":"set-primary-brand-kit","x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"tags":["AI"],"parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the brand kit to make the account's default."}],"responses":{"200":{"description":"The brand kit is now the account's default. The body is empty."},"404":{"description":"No brand kit with this UUID exists on the account"}}}},"/ai/brand/{uuid}/scraped-images":{"get":{"tags":["AI"],"summary":"Retrieve a brand kit's website images","description":"Get where the scrape of the brand's website images stands and the images it has saved so far, most relevant first. The status is worked out from the per-image records, so it moves as images finish.","operationId":"retrieve-brand-kit-scraped-images","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The scrape status, counts and saved images.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitScrapedImagesResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"500":{"description":"The images could not be read."}},"x-canonical-resource":"brand_kit","x-internal":true},"post":{"tags":["AI"],"summary":"Refresh a brand kit's website images","description":"Marks the scrape pending and queues a fresh scrape of the brand's website images, returning without waiting for it. The stored image records are wiped when the scrape runs; poll Retrieve a brand kit's website images for progress. Refused while a scrape is already pending.","operationId":"refresh-brand-kit-scraped-images","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"201":{"description":"The scrape was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitJobDispatchedResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"409":{"description":"An image scrape for this brand kit is already in progress."},"500":{"description":"The scrape could not be queued."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/brand/{uuid}/tone":{"post":{"tags":["AI"],"summary":"Refresh a brand kit's tone","description":"Queues a new tone extraction for the brand kit and returns without waiting for it. The stored tone is replaced when it finishes; poll Retrieve a brand kit's tone for progress. Refused while an extraction is already pending.","operationId":"refresh-brand-kit-tone","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"201":{"description":"The extraction was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitJobDispatchedResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"409":{"description":"A tone extraction for this brand kit is already in progress."},"500":{"description":"The extraction could not be queued."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false},"get":{"tags":["AI"],"summary":"Retrieve a brand kit's tone","description":"Get the brand voice and tone of any brand kit, not only the primary one. Tone is stored apart from the brand kit record, so Retrieve a brand kit and List all brand kits do not return it. An empty tone means the kit has none only when status is complete; when status is not_started, pending or failed the tone is not available yet.","operationId":"retrieve-brand-kit-tone","parameters":[{"name":"uuid","in":"path","description":"Brand kit UUID.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The brand kit's tone and its extraction status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitToneResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account"}},"x-canonical-resource":"brand_kit"}},"/ai/branding/brand-history/process":{"post":{"tags":["AI"],"summary":"Run a queued brand history scrape","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Scrapes the brand's homepage and then its important pages, storing a new snapshot and the changes since the last one. Unless force is set, a brand kit whose homepage was scraped within the last 24 hours is skipped and still answered 200.","operationId":"run-brand-kit-history-scrape-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandHistoryRequest"}}}},"responses":{"200":{"description":"The scrape ran or was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingJobResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"422":{"description":"brandkit_uuid is missing or does not name a brand kit of the account."},"500":{"description":"The scrape failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/branding/brandfetch-refresh/process":{"post":{"tags":["AI"],"summary":"Run a queued Brandfetch refresh","description":"Worker endpoint that Hosted calls on itself through the queue. Reads the brand from Brandfetch again and writes the colours and fonts that changed to the brand kit. Values the customer set or confirmed are never changed. Unless force is set, a brand kit whose Brandfetch data is less than 30 days old is skipped and still answered 200.","operationId":"run-brand-kit-brandfetch-refresh-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandfetchRefreshRequest"}}}},"responses":{"200":{"description":"The refresh ran or was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandfetchRefreshResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account, or Brandfetch does not know its domain."},"422":{"description":"brandkit_uuid is missing or does not name a brand kit of the account."},"500":{"description":"The refresh failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/branding/competitors-extraction":{"post":{"tags":["AI"],"summary":"Run a queued competitors extraction","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Searches the web for the brand's competitors, extracts them with a model and stores the list and the extraction status on the brand kit, replacing what was there. Retrieve a brand kit's competitors reads the result.","operationId":"run-brand-kit-competitors-extraction-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitCompetitorsExtractionRequest"}}}},"responses":{"200":{"description":"The extraction ran.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingJobResponse"}}}},"422":{"description":"brandkit_uuid is missing or does not name a brand kit of the account."},"500":{"description":"The extraction failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/branding/competitors/backfill":{"post":{"tags":["AI"],"summary":"Backfill competitors for the account's brand kits","description":"Queues a competitors extraction for every brand kit of the account that has none yet: extraction never started, failed, or finished with an empty list. Runs once per account and version; later calls, and calls from an account excluded from the backfill, queue nothing. Takes no body.","operationId":"backfill-brand-kit-competitors","responses":{"200":{"description":"Which brand kits an extraction was queued for.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitBackfillResponse"}}}},"500":{"description":"The extractions could not be queued."}},"x-canonical-resource":"brand_kit","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/ai/branding/image-metadata":{"post":{"tags":["AI"],"summary":"Run a queued scraped-image check","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Fetches one image found on the brand's website, has a model judge whether it is safe and relevant to the brand, and when it is, saves it to the content manager and records the file on the image's scraped-image record. An image that cannot be fetched, is rejected, or is judged unsafe or irrelevant is recorded as such and still answered 200, so the queue does not retry it.","operationId":"run-brand-kit-image-metadata-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitImageMetadataRequest"}}}},"responses":{"200":{"description":"The image was judged and its record updated, whatever the verdict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingJobResponse"}}}},"422":{"description":"brandkit_uuid does not name a brand kit of the account, scraped_url is missing or not a URL, or record_id is missing or not a UUID."},"500":{"description":"The analysis or the upload failed; the record is marked failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/branding/tone-extraction":{"post":{"tags":["AI"],"summary":"Run a queued tone extraction","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Reads the brand's website, extracts its voice and tone with a model and stores the tone and the extraction status on the brand kit, replacing what was there. Retrieve a brand kit's tone reads the result.","operationId":"run-brand-kit-tone-extraction-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitToneExtractionRequest"}}}},"responses":{"200":{"description":"The extraction ran.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingJobResponse"}}}},"422":{"description":"brandkit_uuid is missing or does not name a brand kit of the account."},"500":{"description":"The extraction failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/branding/tone/backfill":{"post":{"tags":["AI"],"summary":"Backfill tone for the account's brand kits","description":"Queues a tone extraction for every brand kit of the account whose extraction never started. Runs once per account; later calls queue nothing. Takes no body.","operationId":"backfill-brand-kit-tone","responses":{"200":{"description":"Which brand kits an extraction was queued for.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitBackfillResponse"}}}},"500":{"description":"The extractions could not be queued."}},"x-canonical-resource":"brand_kit","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/ai/branding/trigger-scrape":{"post":{"tags":["AI"],"summary":"Run a queued website image scrape","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Wipes the brand kit's stored image records and scrapes its homepage and important pages for images, queueing a check of each one found. A message without force is acknowledged without doing anything and answered 200 with skipped set, so the queue does not retry it.","operationId":"run-brand-kit-image-scrape-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitImageScrapeRequest"}}}},"responses":{"200":{"description":"The scrape ran or was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingJobResponse"}}}},"404":{"description":"No brand kit with this UUID exists on the account."},"422":{"description":"brandkit_uuid is missing or does not name a brand kit of the account."},"500":{"description":"The scrape failed."}},"x-canonical-resource":"brand_kit","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/broadcast/generation/dispatchGenerate":{"post":{"tags":["AI"],"summary":"Create the generated SMS broadcast","description":"Background job of POST /ai/broadcast/generation/generate: has the model write the message in the requested tone, creates the SMS broadcast through the broadcast API under the default name New AI SMS Campaign, and marks the request record success. Answers 500 when the model or the broadcast API failed; the record is then marked error. Only Hosted queues this call.","operationId":"build-an-sms-broadcast","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerateWorkerRequest"}}}},"responses":{"201":{"description":"The broadcast was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerationResultResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The model or the broadcast API failed; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/broadcast/generation/dispatchUpdate":{"post":{"tags":["AI"],"summary":"Save the rewritten SMS broadcast","description":"Background job of PUT /ai/broadcast/generation/update: has the model rewrite the message in the requested tone, saves it and the other fields onto the broadcast through the broadcast API, and marks the request record success. Answers 404 when the request record is unknown and 500 when the model or the broadcast API failed. Only Hosted queues this call.","operationId":"apply-an-sms-broadcast-update","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastUpdateWorkerRequest"}}}},"responses":{"201":{"description":"The broadcast was updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerationResultResponse"}}}},"404":{"description":"No request has this external_identifier; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The model or the broadcast API failed; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/broadcast/generation/generate":{"post":{"tags":["AI"],"summary":"Write a new SMS broadcast from a prompt","description":"Records a generation request and queues the background job (POST /ai/broadcast/generation/dispatchGenerate) that writes the message and creates the broadcast. Answers at once with the request ID to poll with GET /ai/broadcast/generation/{requestId}. Answers 500 when the request could not be recorded or queued.","operationId":"generate-an-sms-broadcast","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerateRequest"}}}},"responses":{"201":{"description":"The request was recorded and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerationStartedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The request could not be recorded or queued; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/broadcast/generation/update":{"put":{"tags":["AI"],"summary":"Rewrite an SMS broadcast from a prompt","description":"Records an update request for an existing SMS broadcast and queues the background job (POST /ai/broadcast/generation/dispatchUpdate) that rewrites the message and saves it with the other fields sent. Answers at once with the request ID to poll with GET /ai/broadcast/generation/{requestId}. Answers 500 when the request could not be recorded or queued.","operationId":"update-an-sms-broadcast-with-ai","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerationUpdateRequest"}}}},"responses":{"201":{"description":"The request was recorded and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastGenerationStartedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The request could not be recorded or queued; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/broadcast/generation/{requestId}":{"get":{"tags":["AI"],"summary":"Poll an SMS broadcast generation","description":"The stored request record once its job finished. The path is validated first: a request that is still running answers 409, one that ended in error answers 500, an unknown or malformed ID answers 404 or 422. Answers 500 when the record could not be read.","operationId":"retrieve-an-sms-broadcast-generation","parameters":[{"name":"requestId","in":"path","description":"UUID of the request, as answered by the generate or update call.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The finished request: its source, status success and the broadcast it created or updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedBroadcastResponse"}}}},"404":{"description":"No request has this ID (detail: Not found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"The job is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"requestId is blank or not a UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The job ended in error, or the record could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_broadcast","x-internal":true}},"/ai/campaign-generation/beta-opt-in":{"get":{"tags":["AI"],"summary":"Retrieve the campaign generation beta opt-in","description":"Whether the account is opted into the new campaign generation (Stripo engine) beta. The opt-in is one setting per account, not per user, and any user of the account may read it; it reads false until the account has set it. Called by the campaigns frontend and the agents service to give accounts not yet covered by the rollout feature flag the new experience.","operationId":"retrieve-campaign-generation-beta-opt-in","responses":{"200":{"description":"The account's current opt-in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetaOptInResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true},"post":{"tags":["AI"],"summary":"Set the campaign generation beta opt-in","description":"Opts the account into, or out of, the new campaign generation (Stripo engine) beta by overwriting the account's single stored opt-in with the given value. Only the account's primary admin may call it. Answers the value as re-read from storage, so the response reflects what was saved rather than echoing the request.","operationId":"set-campaign-generation-beta-opt-in","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetaOptInRequest"}}}},"responses":{"200":{"description":"The opt-in was stored. The value as re-read from storage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetaOptInResponse"}}}},"403":{"description":"The calling user is not the account's primary admin."},"422":{"description":"enabled is missing, null, or not a boolean."}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/commit":{"post":{"tags":["AI"],"summary":"Commit an asset draft to a campaign","description":"Turns a campaign asset draft, written by a generation that ran with isAssetDraft, into a live campaign: creates the campaign and its message from the draft data, writes the content, stores the design IR carried on the draft and marks the generation record with the campaign ids. Called by the campaign agent and the campaign editor once the sender keeps a draft; needs the permission to create campaigns. Answers 403 without it, 404 when the draft is not found, 422 when id, asset_type or data is missing, data is empty or not valid draft data for the asset type, or the draft cannot be committed, and 500 when writing the campaign fails.","operationId":"commit-a-campaign-asset-draft","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitAssetDraftRequest"}}}},"responses":{"201":{"description":"The campaign was created from the draft. The campaign and message as stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationCampaignResponse"}}}},"403":{"description":"The API user may not create campaigns."},"404":{"description":"No asset draft is stored under id."},"422":{"description":"id, asset_type or data is missing; data is empty or not valid draft data for asset_type; neither external_identifier nor data.external_identifier is set; or the asset-draft service refused the commit."},"500":{"description":"Creating the campaign or writing its content failed."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/create":{"post":{"tags":["AI"],"summary":"Run a queued campaign generation","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/campaign/generation/generate; not a user API. Generates the email content with a model from the prompt, brand kit, summarization, tone and blocks, builds the layout, picks and places images, inlines the markup and writes the campaign and its message, filing the campaign under the source and label. With campaign_id and message_id the content is written into that existing message instead. When is_asset_draft is set and asset-draft creation is enabled for the account, the result is saved as an asset draft instead and no campaign row is written. The generation record is marked success or error for the poll. Needs the permission to create campaigns. Answers 403 without it, 422 when external_identifier names no generation record or a field is malformed, and 500 for any failure of the build, with the record marked error.","operationId":"run-a-campaign-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDispatchRequest"}}}},"responses":{"201":{"description":"The job ran. The campaign and message written, or the asset draft when is_asset_draft was honoured.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignGenerationCampaignResponse"},{"$ref":"#/components/schemas/CampaignGenerationAssetDraftResponse"}]}}}},"403":{"description":"The API user may not create campaigns."},"422":{"description":"external_identifier, source, campaign_name, template, prompt or lang is missing; external_identifier names no generation record; template or tone is not an allowed value; a field has the wrong type; blocks or images is malformed; brandkit_uuid or summarization_uuid names no record; or series_id, labelId, campaign_id or message_id does not exist."},"500":{"description":"Generating the content, building the layout or writing the campaign failed; the generation record is marked error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/delete":{"post":{"tags":["AI"],"summary":"Run a queued campaign delete","description":"Worker endpoint: Hosted dispatches this to itself through the queue from DELETE /ai/campaign/generation/delete/{requestId} when the generation was still running; not a user API. Re-reads the request up to five times with a growing wait until it leaves in_progress, then deletes the campaign, its message, its design IR and the record, answering deleted, or, when the generation ended in error, removes what it wrote on a best-effort basis and the record, answering partial delete. Needs the permission to delete campaigns. Answers 403 without it, 404 when no generation request is stored under request_id or its campaign no longer exists, 422 when request_id is missing, and 500 when the generation is still in progress after the retries, in which case nothing is deleted.","operationId":"run-a-generated-campaign-delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDispatchRequest"}}}},"responses":{"200":{"description":"The delete ran. deleted, or partial delete when the generation had ended in error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationDeleteStatusResponse"}}}},"403":{"description":"The API user may not delete campaigns."},"404":{"description":"No generation request is stored under request_id, or the campaign it names no longer exists."},"422":{"description":"request_id is missing or not a string."},"500":{"description":"The generation was still in progress after the retries; the delete was abandoned."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/delete/{requestId}":{"delete":{"tags":["AI"],"summary":"Delete a generated campaign","description":"Removes what a generation request produced and the request itself. When the request is success the campaign, its message, its design IR and its folder association are deleted along with the record, answering deleted. While it is in_progress the delete is queued to POST /ai/campaign/generation/delete to run once the generation finishes, answering deleting. When it is in error whatever was written is removed on a best-effort basis and the record deleted, answering partial delete. Called by the campaign editor when the sender discards a generated campaign; needs the permission to delete campaigns. Answers 403 without it, 404 when no generation request is stored under requestId or its campaign no longer exists, and 500 when the delete cannot be queued.","operationId":"delete-a-generated-campaign","parameters":[{"name":"requestId","in":"path","description":"UUID of the generation request, as answered by POST /ai/campaign/generation/generate.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"deleted, deleting or partial delete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationDeleteStatusResponse"}}}},"403":{"description":"The API user may not delete campaigns."},"404":{"description":"No generation request is stored under requestId, or the campaign it names no longer exists."},"500":{"description":"The generation is in progress and the delete could not be queued."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/from-markup":{"post":{"tags":["AI"],"summary":"Create a campaign from engine markup","description":"Persists finished HTML and CSS from the generation engine as a current-editor (ed_version 3) campaign, synchronously and with no content generation: creates the campaign and message, inlines the css into the html for delivery, stores the raw markup as the editable source, extracts the tracked links, records the first editor version point and files the campaign under the source and label. Answers 201 with the campaign and message ids so the caller can open the editor. When isTemplate is set the markup is saved into the template library instead; when isAssetDraft is set and asset-draft creation is enabled for the account it is saved as an asset draft instead, for POST /ai/campaign/generation/commit. A caller that sends idempotencyKey has the first response replayed on a retry with the same fields instead of a second campaign. Called by the campaign agent. Available only to accounts enrolled in engine campaign generation; needs the permission to create campaigns, and to create templates when isTemplate is set. Answers 403 without the permission, 404 when the account is not enrolled, 409 while a request holding the same idempotencyKey is still running or when the key was used with different fields, 422 when html or source is missing or a field is malformed, and 500 when persisting fails.","operationId":"create-a-campaign-from-markup","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromMarkupRequest"}}}},"responses":{"201":{"description":"The markup was persisted. The campaign and message written; the asset draft when isAssetDraft was honoured; or the library template when isTemplate was set. A replayed idempotencyKey answers the first call's body again.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignGenerationCampaignResponse"},{"$ref":"#/components/schemas/CampaignGenerationMarkupAssetDraftResponse"},{"$ref":"#/components/schemas/CampaignGenerationMarkupTemplateResponse"}]}}}},"403":{"description":"The API user may not create campaigns, or may not create templates when isTemplate is set."},"404":{"description":"The account is not enrolled in engine campaign generation; the body carries error_code FEATURE_NOT_ENABLED."},"409":{"description":"A request holding the same idempotencyKey is still running, or the key was already used with different fields (error_code CAMPAIGN_CREATION_KEY_REUSED)."},"422":{"description":"html or source is missing; source is not agent or initiatives-detail; html, css, templateName, designIr or idempotencyKey is too long; designIr is not a JSON object or array; a field has the wrong type; or labelId or seriesId does not exist."},"500":{"description":"Creating the campaign, draft or template or writing the markup failed."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/generate":{"post":{"tags":["AI"],"summary":"Start an AI campaign generation","description":"Queues the generation of a campaign from a brief: creates the generation request record, picks a layout for the prompt and brand kit when template is omitted, selects additional blocks from the prompt and dispatches the build to POST /ai/campaign/generation/create. Answers 201 with the requestId at once; poll GET /ai/campaign/generation/poll/{requestId} and read the result from GET /ai/campaign/generation/{requestId}. With campaignId and messageId the content is written into that existing message instead of a new campaign, and the record already stored for that campaign and source is reused. Called by the campaign agent and the campaign editor; needs the permission to create campaigns. Answers 403 without it, 409 while the chosen summarization is still in progress, 422 when a field is malformed, brandkitUuid or summarizationUuid names no record of the account, seriesId, labelId, campaignId or messageId does not exist, the message already has editor markup, or the summarization errored, and 500 when picking the layout or the blocks or queueing the build fails, in which case the record is marked error.","operationId":"start-a-campaign-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectRequest"}}}},"responses":{"201":{"description":"The generation was queued. Its requestId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationRequestIdResponse"}}}},"403":{"description":"The API user may not create campaigns."},"409":{"description":"The chosen content summarization is still in progress."},"422":{"description":"prompt or source is missing; a field has the wrong type; template or tone is not an allowed value; images is malformed or longer than 7; brandkitUuid or summarizationUuid names no record of the account; seriesId, labelId, campaignId or messageId does not exist; the message already has editor markup; or the summarization is in error."},"500":{"description":"Picking the layout or the blocks failed, or the build could not be queued; the request record is marked error."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/lease/capabilities":{"get":{"tags":["AI"],"summary":"Retrieve what the campaign turn lease store can promise","description":"Report what the campaign turn lease store guarantees: whether a lease held here is seen by every worker and the longest hold a caller may ask for. Called once by the generation engine (ac-agents) at startup, so it can refuse to bind a lease store that cannot cover a turn rather than discover mid-turn that its lease lapsed or never excluded anything. Requires enrollment in campaign generation (else 404 \"Not found\") and the create campaigns permission.","operationId":"retrieve-campaign-turn-lease-capabilities","responses":{"200":{"description":"The store's capabilities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTurnLeaseCapabilities"}}}},"403":{"description":"The API user may not create campaigns."},"404":{"description":"The account is not enrolled in campaign generation (detail \"Not found\")."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/generation/poll/{requestId}":{"get":{"tags":["AI"],"summary":"Poll a campaign generation or update","description":"Where a generation or update request stands, polled after POST /ai/campaign/generation/generate or PUT /ai/campaign/generation/update/{requestId}. The HTTP status follows the record: 200 once it is success, 409 while it is in_progress, and on error 504 when the model timed out, 413 when its output was truncated, else 500; every answer carries the same body, with step for progressive loading. changesSummary and hasChanges are meaningful only when status is success and are tri-state: null means not yet known or not recorded, never false. errorCode is meaningful only when status is error. Called by the campaign agent and the campaign editor. Answers 404 when no generation request is stored under requestId.","operationId":"retrieve-campaign-generation-status","parameters":[{"name":"requestId","in":"path","description":"UUID of the generation request, as answered by POST /ai/campaign/generation/generate.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The request is success: the campaign or asset draft is written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStatusResponse"}}}},"404":{"description":"No generation request is stored under requestId."},"409":{"description":"The request is in_progress; poll again. Same body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStatusResponse"}}}},"413":{"description":"The request is error with errorCode content_too_large: the model's output was truncated. Same body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStatusResponse"}}}},"500":{"description":"The request is error with no errorCode: a step failed. Same body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStatusResponse"}}}},"504":{"description":"The request is error with errorCode timeout: the model did not answer in time. Same body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStatusResponse"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/generation/request/{campaignId}":{"get":{"tags":["AI"],"summary":"Retrieve the generation request of a campaign","description":"The generation request stored for a campaign, looked up by campaign id: the requestId to poll or update it by, and the record as stored, with its status, step, inputs and content. Called by the campaign agent to pick up a generated campaign it did not start. Answers 404 when no generation record names the campaign and 500 when the stored record cannot be decoded.","operationId":"retrieve-a-campaign-generation-request","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign the generation wrote or edited.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The stored request and its id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationStoredRequestResponse"}}}},"404":{"description":"No generation record names campaignId."},"500":{"description":"The stored record cannot be decoded."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/generation/templates":{"get":{"tags":["AI"],"summary":"List the templates available for campaign generation","description":"Lists the base templates the campaign generation engine can compose a campaign from: each template's key, as the generation endpoints accept it, with its display name translated into the account's language. The list is fixed in code and the same for every account; no feature gate or permission applies. Backs the template picker of the campaign-from-prompt flow in the campaigns app.","operationId":"list-campaign-generation-templates","responses":{"200":{"description":"Every template available for generation, in picker order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationTemplatesResponse"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/generation/update":{"post":{"tags":["AI"],"summary":"Run a queued campaign update","description":"Worker endpoint: Hosted dispatches this to itself through the queue from PUT /ai/campaign/generation/update/{requestId}, and from the template-to-campaign, campaign-edits and content-remapping flows for their own records; not a user API. Rewrites the stored campaign with a model according to the prompt, layout, brand kit, summarization, blocks and images, writes the new markup, subject, preheader and name, records changesSummary and hasChanges on the request, marks it success and emits CampaignEditCompletedEvent. A model timeout or truncation is recorded on the request and answered 422 with error and errorCode so the queue does not retry; poll then answers 504 or 413. Needs the permission to update campaigns. Answers 403 without it, 422 when request_id names no record, nothing would change, the rewritten XML is invalid, or a field is malformed, and 500 for any other failure, with the request marked error.","operationId":"run-a-generated-campaign-update","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDispatchRequest"}}}},"responses":{"200":{"description":"The job ran and the campaign was rewritten. The campaign and message as now stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationCampaignResponse"}}}},"403":{"description":"The API user may not update campaigns."},"422":{"description":"Not retried by the queue. A classified model failure answers the error body shown, with the request marked error. Otherwise a standard error: request_id is missing or names no campaign generation, template-to-campaign, campaign edits or content-remapping record; nothing would change (the request is marked error); the rewritten XML failed validation; a field has the wrong type; blocks, images or callback_context is malformed; brandkit_uuid or summarization_uuid names no record; or labelId does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationUpdateFailedResponse"}}}},"500":{"description":"The stored request could not be resolved, or the rewrite failed for a reason other than a model timeout or truncation; the request is marked error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/update/{requestId}":{"put":{"tags":["AI"],"summary":"Update a generated campaign","description":"Queues an AI update of a generated campaign: a new layout, brand kit or content summarization, a free-text prompt, blocks to place or images, applied by rewriting the stored campaign. At least one of a changed template, a changed brandkitUuid, a changed summarizationUuid, an editPrompt, blocks or images must be given. Marks the generation record in_progress and dispatches the rewrite to POST /ai/campaign/generation/update; poll GET /ai/campaign/generation/poll/{requestId} and read the result from GET /ai/campaign/generation/{requestId}. Called by the campaign editor, for instance to switch layouts, and by the campaign agent; needs the permission to update campaigns. Answers 403 without it, 404 when no generation request is stored under requestId or its campaign no longer exists, 409 while the request is in_progress or the chosen summarization is still in progress, 422 when the campaign has already been sent, nothing would change, the summarization errored, or a field is malformed, and 500 when the request is in error or queueing fails.","operationId":"update-a-generated-campaign","parameters":[{"name":"requestId","in":"path","description":"UUID of the generation request, as answered by POST /ai/campaign/generation/generate.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequest"}}}},"responses":{"200":{"description":"The update was queued. The same requestId, to poll.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignGenerationRequestIdResponse"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"No generation request is stored under requestId, or the campaign it names no longer exists."},"409":{"description":"The request is still in_progress, or the chosen content summarization is still in progress."},"422":{"description":"The campaign has already been sent (error_code CAMPAIGN_NOT_EDITABLE); nothing would change; the summarization is in error; template is missing or not an allowed value; a field has the wrong type; blocks or images is malformed; brandkitUuid or summarizationUuid names no record; or labelId does not exist."},"500":{"description":"The request is in error, or the rewrite could not be queued, in which case the record is marked error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/{campaignId}/design-ir":{"get":{"tags":["AI"],"summary":"Retrieve the design IR of a campaign","description":"Read the design IR stored for a campaign: the opaque JSON document the generation engine keeps so it can reload the campaign's editable structure across sessions, returned verbatim with the revision that identifies it. Called by the generation engine (ac-agents) before it edits a campaign. The read is exact-key: it never falls back to a split message's document. Answers 404 for three reasons the detail string distinguishes: \"Not found\" when the account is not enrolled in campaign generation, \"Campaign not found: {id}\" when the campaign is missing or belongs to another account, and \"Design IR not found\" when the campaign exists but has no design IR stored.","operationId":"retrieve-a-campaign-design-ir","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign whose design IR to read.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The stored design IR and its revision.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrDocument"}}}},"404":{"description":"Nothing to return. detail is one of three stable strings: \"Not found\" (the account is not enrolled), \"Campaign not found: {id}\" (missing or another account's campaign) or \"Design IR not found\" (the campaign exists, nothing is stored).","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer","example":404},"title":{"type":"string","example":"Not Found"},"detail":{"description":"Which of the three reasons applies.","type":"string","example":"Design IR not found"},"error_code":{"type":"string","enum":["FEATURE_NOT_ENABLED","CAMPAIGN_NOT_FOUND","DESIGN_IR_NOT_FOUND"],"example":"DESIGN_IR_NOT_FOUND"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The stored row could not be read (detail \"Design IR could not be read\"), or it holds something that is not a JSON object or array (detail \"Stored design IR is not valid JSON\")."}},"x-canonical-resource":"campaign","x-internal":true},"put":{"tags":["AI"],"summary":"Store the design IR of a campaign","description":"Store the design IR for a campaign, replacing whatever was stored before. The design IR is an opaque JSON document owned by the generation engine; hosted stores the ir value verbatim keyed by campaign id and never inspects its shape. Called by the generation engine (ac-agents) after it composes or edits a campaign. The write is read back before it is acknowledged: a verified write answers 204, and a write whose read-back found no row answers 200 with verified false so the caller records it as unverified rather than stored. Send expectedRevision from a previous GET or PUT to refuse the write with 409 when another writer has changed the document since; omit it for last-writer-wins. Requires enrollment in campaign generation (else 404 \"Not found\") and the create campaigns permission.","operationId":"store-a-campaign-design-ir","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign the design IR belongs to.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"The design IR in an {\"ir\": ...} envelope.","required":true,"content":{"application/json":{"schema":{"required":["ir"],"properties":{"ir":{"description":"The design IR document to store verbatim: a non-empty JSON object or array the engine owns. Its JSON encoding must not exceed 4,000,000 bytes.","example":{"root":{"type":"container","blocks":[{"type":"text","text":"Hello"}]}},"oneOf":[{"type":"object"},{"type":"array","items":{}}]},"expectedRevision":{"description":"The revision the caller believes it is overwriting, from a previous GET or PUT. Present, the write is refused with 409 when the stored document has since changed; the empty string asserts that nothing is stored yet. Omitted or null, the write is last-writer-wins.","type":["string","null"],"example":"0f1d2c3b4a5e4f609b7c8d9e0f1a2b3c"}},"type":"object"}}}},"responses":{"200":{"description":"The write committed but the read-back found no row, so it is unverified; reason says whether the read-back query found nothing or failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrUnverifiedWrite"}}}},"204":{"description":"Stored and read back: the row holds the document that was written."},"403":{"description":"The API user may not create campaigns."},"404":{"description":"detail is \"Not found\" when the account is not enrolled in campaign generation, or \"Campaign not found: {id}\" when the campaign is missing or belongs to another account."},"409":{"description":"Another request is writing this campaign's design IR (error_code DESIGN_IR_LOCKED), or expectedRevision is not the stored revision (error_code DESIGN_IR_REVISION_MISMATCH, with current_revision on the error)."},"422":{"description":"The body is not a JSON object with an ir key, ir is empty or not an object or array, ir encodes to more than 4,000,000 bytes, or expectedRevision is not a string."},"500":{"description":"The existing row could not be read before writing (detail \"Design IR could not be read\"), or the row read back cannot be a copy of what was written (detail \"Design IR write could not be verified\")."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/{campaignId}/design-ir/message/{messageId}":{"get":{"tags":["AI"],"summary":"Retrieve the design IR of a split campaign message","description":"Read the design IR stored for one message of a split campaign: the opaque JSON document the generation engine keeps for that variant, returned verbatim with the revision that identifies it. Called by the generation engine (ac-agents) before it edits the variant. The read is exact-key: it never falls back to the campaign's own document. Answers 404 for four reasons the detail string distinguishes: \"Not found\" when the account is not enrolled in campaign generation, \"Campaign not found: {id}\" when the campaign is missing or belongs to another account, \"Message not found on campaign {campaignId}: {messageId}\" when the message is not one of that campaign's, and \"Design IR not found\" when nothing is stored for the message.","operationId":"retrieve-a-campaign-message-design-ir","parameters":[{"name":"campaignId","in":"path","description":"Id of the split campaign the message belongs to.","required":true,"schema":{"type":"integer"}},{"name":"messageId","in":"path","description":"Id of the campaign's message whose design IR to read.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The stored design IR and its revision.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrDocument"}}}},"404":{"description":"Nothing to return. detail is one of four stable strings: \"Not found\" (the account is not enrolled), \"Campaign not found: {id}\" (missing or another account's campaign), \"Message not found on campaign {campaignId}: {messageId}\" (not that campaign's message) or \"Design IR not found\" (nothing is stored for the message).","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer","example":404},"title":{"type":"string","example":"Not Found"},"detail":{"description":"Which of the four reasons applies.","type":"string","example":"Design IR not found"},"error_code":{"type":"string","enum":["FEATURE_NOT_ENABLED","CAMPAIGN_NOT_FOUND","DESIGN_IR_MESSAGE_NOT_FOUND","DESIGN_IR_NOT_FOUND"],"example":"DESIGN_IR_NOT_FOUND"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The stored row could not be read (detail \"Design IR could not be read\"), or it holds something that is not a JSON object or array (detail \"Stored design IR is not valid JSON\")."}},"x-canonical-resource":"campaign","x-internal":true},"put":{"tags":["AI"],"summary":"Store the design IR of a split campaign message","description":"Store the design IR for one message of a split campaign, replacing whatever was stored for that message before. Each split variant keeps its own document; the campaign's own document is untouched. Called by the generation engine (ac-agents) after it composes or edits the variant. Behaves exactly like storing a campaign's design IR: the write is read back, a verified write answers 204, an unverified one answers 200 with verified false, and expectedRevision makes the write conditional. Requires enrollment in campaign generation (else 404 \"Not found\") and the create campaigns permission.","operationId":"store-a-campaign-message-design-ir","parameters":[{"name":"campaignId","in":"path","description":"Id of the split campaign the message belongs to.","required":true,"schema":{"type":"integer"}},{"name":"messageId","in":"path","description":"Id of the campaign's message to store the design IR against.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"The design IR in an {\"ir\": ...} envelope.","required":true,"content":{"application/json":{"schema":{"required":["ir"],"properties":{"ir":{"description":"The design IR document to store verbatim: a non-empty JSON object or array the engine owns. Its JSON encoding must not exceed 4,000,000 bytes.","example":{"root":{"type":"container","blocks":[{"type":"text","text":"Hello"}]}},"oneOf":[{"type":"object"},{"type":"array","items":{}}]},"expectedRevision":{"description":"The revision the caller believes it is overwriting, from a previous GET or PUT. Present, the write is refused with 409 when the stored document has since changed; the empty string asserts that nothing is stored yet. Omitted or null, the write is last-writer-wins.","type":["string","null"],"example":"0f1d2c3b4a5e4f609b7c8d9e0f1a2b3c"}},"type":"object"}}}},"responses":{"200":{"description":"The write committed but the read-back found no row, so it is unverified; reason says whether the read-back query found nothing or failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrUnverifiedWrite"}}}},"204":{"description":"Stored and read back: the row holds the document that was written."},"403":{"description":"The API user may not create campaigns."},"404":{"description":"detail is \"Not found\" when the account is not enrolled in campaign generation, \"Campaign not found: {id}\" when the campaign is missing or belongs to another account, or \"Message not found on campaign {campaignId}: {messageId}\" when the message is not one of that campaign's."},"409":{"description":"Another request is writing this campaign's design IR (error_code DESIGN_IR_LOCKED), or expectedRevision is not the stored revision (error_code DESIGN_IR_REVISION_MISMATCH, with current_revision on the error)."},"422":{"description":"The body is not a JSON object with an ir key, ir is empty or not an object or array, ir encodes to more than 4,000,000 bytes, or expectedRevision is not a string."},"500":{"description":"The existing row could not be read before writing (detail \"Design IR could not be read\"), or the row read back cannot be a copy of what was written (detail \"Design IR write could not be verified\")."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/{campaignId}/lease":{"post":{"tags":["AI"],"summary":"Acquire or renew a campaign's generation turn lease","description":"Take or renew the campaign's generation turn for the caller's owner token, so one campaign runs one turn at a time however many workers serve the account. Called by the generation engine (ac-agents) before it starts a turn and again to extend one that overruns. Always answers 200 with a status: acquired when the campaign was free and is now this owner's for ttlSeconds, renewed when this owner already held it and the hold was extended, or held_by_other when someone else holds it, in which case owner and expiresInSeconds say who and for how long and nothing was changed. The lease is transient state in the shared cache, not a stored record, and another owner's lease is never overwritten. Requires enrollment in campaign generation (else 404 \"Not found\") and the create campaigns permission.","operationId":"acquire-a-campaign-turn-lease","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign the turn runs on.","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTurnLeaseRequest"}}}},"responses":{"200":{"description":"The lease state after the call: status is acquired, renewed or held_by_other.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTurnLeaseState"}}}},"403":{"description":"The API user may not create campaigns."},"404":{"description":"detail is \"Not found\" when the account is not enrolled in campaign generation, or \"Campaign not found: {id}\" when the campaign is missing or belongs to another account."},"409":{"description":"Another lease call for this campaign is mid-flight (error_code CAMPAIGN_TURN_LEASE_LOCKED); try again."},"422":{"description":"owner is missing, not a string or longer than 200 characters, or ttlSeconds is not an integer from 1 to 900."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Release a campaign's generation turn lease","description":"Give up the campaign's generation turn, which only the owner token that took it can do. Called by the generation engine (ac-agents) when a turn finishes. The owner rides the query string because a DELETE body is not validated. Always answers 200 with a status: released when this owner held the lease and no longer does, expired when nobody held it because the turn ran past its own lease, or held_by_other when another owner holds it and it was left alone. Releasing removes the caller's own lease from the shared cache; it is transient state, not a stored record. Requires enrollment in campaign generation (else 404 \"Not found\") and the create campaigns permission.","operationId":"release-a-campaign-turn-lease","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign the turn ran on.","required":true,"schema":{"type":"integer"}},{"name":"owner","in":"query","description":"The owner token the lease was acquired with, 1 to 200 characters. Another owner's lease is left alone.","required":true,"schema":{"type":"string","maxLength":200,"minLength":1},"example":"worker-a:turn-7f3c"}],"responses":{"200":{"description":"The lease state after the call: status is released, expired or held_by_other.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTurnLeaseState"}}}},"403":{"description":"The API user may not create campaigns."},"404":{"description":"detail is \"Not found\" when the account is not enrolled in campaign generation, or \"Campaign not found: {id}\" when the campaign is missing or belongs to another account."},"409":{"description":"Another lease call for this campaign is mid-flight (error_code CAMPAIGN_TURN_LEASE_LOCKED); try again."},"422":{"description":"owner is missing from the query string, empty or longer than 200 characters (detail \"Missing or invalid owner\")."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/{campaignId}/template":{"post":{"tags":["AI"],"summary":"Save a generated campaign as a template","description":"Save an existing campaign into the template library as a reusable template: the campaign's v3 markup is copied into a new em_template row, with the campaign's design IR copied alongside it so the generation engine can edit the template later. The source campaign is never modified. Called from the campaign generation UI (ac-frontend) when a user keeps a generated design. Only v3 designer campaigns with stored markup can be saved; others answer 422 with detail \"Campaign cannot be saved as a template\". Requires enrollment in campaign generation (else 404 \"Not found\") and the create email templates permission.","operationId":"create-a-template-from-a-campaign","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign to copy into a template.","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateFromCampaignRequest"}}}},"responses":{"201":{"description":"The template was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateFromCampaignResponse"}}}},"403":{"description":"The API user may not create templates."},"404":{"description":"detail is \"Not found\" when the account is not enrolled in campaign generation, or \"Campaign not found: {id}\" when the campaign is missing or belongs to another account."},"422":{"description":"The campaign is not a v3 designer campaign or has no stored markup (detail \"Campaign cannot be saved as a template\"), or name is not a string or longer than 500 characters."},"500":{"description":"The campaign's content could not be read or the template could not be saved (detail \"Failed to save campaign as template\")."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/generation/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve the result of a campaign generation","description":"The outcome of a finished generation or update request: the campaign and message as stored, with the brand kit, summarization, layout, blocks and summary the content was generated from. When the request wrote an asset draft and asset-draft creation is enabled for the account, the same fields are read from the draft instead, without campaign or message ids. Called by the campaign agent and the campaign editor after the poll answers success. Answers 404 when no generation request is stored under requestId or its asset draft is gone, 409 while the request is in_progress, and 500 when it is in error, holds no campaign id, or its campaign or message cannot be read.","operationId":"retrieve-a-generated-campaign","parameters":[{"name":"requestId","in":"path","description":"UUID of the generation request, as answered by POST /ai/campaign/generation/generate.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The request is success. The campaign and message written, or the draft's data when the request wrote an asset draft.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignGenerationResultResponse"},{"$ref":"#/components/schemas/CampaignGenerationAssetDraftResultResponse"}]}}}},"404":{"description":"No generation request is stored under requestId, or the asset draft it wrote no longer exists."},"409":{"description":"The request is still in_progress; poll again."},"500":{"description":"The request is in error, holds no campaign id, or its campaign or message cannot be read."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/sets":{"post":{"tags":["AI"],"summary":"Reserve a cohort set","description":"Reserve a cohort set before its cohorts are composed, taking one of the account's daily slots, which sets of takes share. Creates no campaign: each cohort is composed by the generation engine as an asset draft labelled {cohortSetId}:{cohortKey} and recorded on this set afterwards. Reserving again under the same cohortSetId answers 200 with the existing set and takes no second slot. Answers 403 when the account is not enrolled or the API user may not create campaigns, 422 when cohortSetId is not a lowercase UUID, and 429 when the account has reserved as many sets as it may in a day.","operationId":"reserve-a-cohort-set","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSetReserveRequest"}}}},"responses":{"200":{"description":"The set was already reserved. The record as stored, plus created: false; no slot was taken."},"201":{"description":"The set was reserved. The record, with no cohorts yet, plus created: true.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CohortSet"},{"required":["created"],"properties":{"created":{"description":"True when this call made the reservation; false when the set was already reserved and is returned as stored.","type":"boolean","example":true}},"type":"object"}]}}}},"403":{"description":"Cohort sets are not available for this account, or the API user may not create campaigns."},"409":{"description":"Another change to this set, or another reservation for this account, is in progress; try again."},"422":{"description":"cohortSetId is not a lowercase UUID."},"429":{"description":"The account has reserved as many sets as it may in a day; the window resets at midnight UTC."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/sets/{cohortSetId}":{"get":{"tags":["AI"],"summary":"Retrieve a cohort set","description":"The record of a cohort set as stored: its state, and for each cohort its key, state, asset draft and, once promoted, its campaign. A reopened conversation reloads the set from here. Answers 404 when nothing is recorded under the id.","operationId":"retrieve-a-cohort-set","parameters":[{"name":"cohortSetId","in":"path","description":"The id the set was reserved under.","required":true,"schema":{"type":"string","pattern":"^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CohortSet"}}}},"403":{"description":"Cohort sets are not available for this account."},"404":{"description":"No set is recorded under that id."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/sets/{cohortSetId}/cohorts":{"put":{"tags":["AI"],"summary":"Record the cohorts of a set","description":"Record a reserved set's cohorts once the generation engine has answered: each cohort's key and the asset draft it was composed as, or a failure code where it failed. Puts the set up for review and creates no campaign. Idempotent on the list: the same cohorts recorded again answer 200 with the stored set; a different list is refused with 409. Answers 404 for an unknown set and 422 when the list has fewer than 2 or more than 5 cohorts, keys other than c1, c2 and so on in order, or no composed cohort.","operationId":"record-cohort-set-cohorts","parameters":[{"name":"cohortSetId","in":"path","description":"The id the set was reserved under.","required":true,"schema":{"type":"string","pattern":"^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSetCohortsRequest"}}}},"responses":{"200":{"description":"The record with the cohorts on it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CohortSet"}}}},"403":{"description":"Cohort sets are not available for this account, or the API user may not create campaigns."},"404":{"description":"No set is recorded under that id."},"409":{"description":"Different cohorts were already recorded for this set, or the set is no longer composing."},"422":{"description":"The list of cohorts is invalid."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/variant-sets":{"post":{"tags":["AI"],"summary":"Reserve a set of campaign takes","description":"Reserve a set of AI-composed takes of one campaign brief before composing them, taking one of the account's daily slots. The takes themselves are composed by the generation engine as asset drafts and recorded on this set afterwards; none becomes a campaign until one is picked. Reserving again under the same requestId answers 200 with the existing set and takes no second slot, so a caller that lost the first answer is not charged twice against its day. Answers 403 when the account is not enrolled, 422 when requestId or expiresAt is malformed or expiresAt has passed, and 429 when the account has reserved as many sets as it may in a day.","operationId":"reserve-a-campaign-variant-set","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantSetReserveRequest"}}}},"responses":{"200":{"description":"The requestId was already reserved. The existing record, plus created: false; no slot was taken."},"201":{"description":"The set was reserved. The record, with no takes yet, plus created: true.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CampaignVariantSet"},{"required":["created"],"properties":{"created":{"description":"True when this call made the reservation; false when the requestId was already reserved and the existing set is returned.","type":"boolean","example":true}},"type":"object"}]}}}},"403":{"description":"Sets of takes are not available for this account, or the API user may not create campaigns."},"422":{"description":"requestId or expiresAt is malformed, or expiresAt has already passed."},"429":{"description":"The account has reserved as many sets as it may in a day; the window resets at midnight UTC."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/variant-sets/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a set of campaign takes","description":"The choice record for a set of takes as stored, whether or not its pick window has passed: what was shown, which take was picked and the campaign it became. A reloaded picker reads expiresAt and pickedVariantKey off it. Answers 404 when nothing is recorded under the requestId.","operationId":"retrieve-a-campaign-variant-set","parameters":[{"name":"requestId","in":"path","description":"The key the set was reserved under.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9][A-Za-z0-9_.:-]{3,127})$"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignVariantSet"}}}},"403":{"description":"Sets of takes are not available for this account."},"404":{"description":"No set is recorded under that requestId."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaign/variant-sets/{requestId}/pick":{"post":{"tags":["AI"],"summary":"Pick a take and create its campaign","description":"Commit the picked take's asset draft to the one campaign this set is allowed. The campaign is created with the AI source label and, when the take was styled under a brand candidate, that candidate recorded on it. Exactly one campaign per set: the same take picked again answers 200 with the campaign already created, whether or not the pick window has passed, so a caller that lost the first answer can recover the ids; a different take is refused with 409 from the moment the first pick is claimed. Answers 404 for an unknown set, 409 while no takes are recorded, 410 when the pick window has passed or the draft is no longer in the draft store, 422 when the take is not in the set or was never composed, and 503 when the draft store cannot be reached.","operationId":"pick-a-campaign-variant","parameters":[{"name":"requestId","in":"path","description":"The key the set was reserved under.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9][A-Za-z0-9_.:-]{3,127})$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantSetPickRequest"}}}},"responses":{"200":{"description":"The same take was already picked. The existing campaign's ids, created: false, and the record; nothing was created."},"201":{"description":"The campaign was created. Its ids, created: true, and the record with the pick on it.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CampaignVariantSet"},{"required":["campaignId","messageId","created"],"properties":{"campaignId":{"description":"Id of the campaign the pick created.","type":"integer","example":4821},"messageId":{"description":"Id of that campaign's message.","type":"integer","example":9134},"created":{"description":"True when this call created the campaign; false when the same take had already been picked and the existing ids are returned.","type":"boolean","example":true}},"type":"object"}]}}}},"403":{"description":"Sets of takes are not available for this account, or the API user may not create campaigns."},"404":{"description":"No set is recorded under that requestId."},"409":{"description":"A different take from this set was already picked, or no takes have been recorded yet."},"410":{"description":"The pick window has passed, or the draft is no longer in the draft store. Generate the takes again."},"422":{"description":"The take is not in this set, or was never composed."},"503":{"description":"The draft store is not answering; try again."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaign/variant-sets/{requestId}/variants":{"put":{"tags":["AI"],"summary":"Record the takes of a set","description":"Record the takes the sender was shown on a reserved set, once the generation engine has answered: one entry per take with its angle and the asset draft it became, or no draft where it failed. Idempotent on the list: the same takes recorded again answer 200 with the stored set, a different list is refused with 409, since a regenerate is a new set and never a rewrite of this one. Answers 404 for an unknown set, 410 once the set's pick window has passed, and 422 when the list is empty, longer than 3, repeats a key, or has no composed take.","operationId":"record-campaign-variant-set-takes","parameters":[{"name":"requestId","in":"path","description":"The key the set was reserved under.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9][A-Za-z0-9_.:-]{3,127})$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantSetVariantsRequest"}}}},"responses":{"200":{"description":"The record with the takes on it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignVariantSet"}}}},"403":{"description":"Sets of takes are not available for this account, or the API user may not create campaigns."},"404":{"description":"No set is recorded under that requestId."},"409":{"description":"Different takes were already recorded for this set."},"410":{"description":"The set's pick window has passed."},"422":{"description":"The list of takes is invalid."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/content-remapping/layout":{"post":{"tags":["AI"],"summary":"Remap a campaign into a built-in layout","description":"Starts a job that pours the campaign's existing content into one of the built-in XML layouts, styled by a brand kit, and queues the worker that rewrites the campaign. The campaign is read and decompiled now; the rewrite happens in the worker, so poll GET /ai/campaigns/content-remapping/{requestId} for the outcome. Requires the permission to update campaigns. Left out, brandkitUuid falls back to the account's primary brand kit. With no brandkitUuid and no primary brand kit, the job is created without brand context.","operationId":"remap-a-campaign-into-a-layout","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingLayoutRequest"}}}},"responses":{"201":{"description":"The job was stored and queued. Its id, the campaign, and status in_progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingJobSummary"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"brandkitUuid names a brand kit the brand kit service cannot find.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}},"422":{"description":"The body is invalid: campaignId or layout is missing or does not name an existing record the API user may use, the campaign is sent or sending, or it was not built in the current designer with blocks the XML flow supports."},"500":{"description":"Reading the campaign, building the target or storing the job failed. Nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/content-remapping/process":{"post":{"tags":["AI"],"summary":"Run a queued content remapping job","description":"Worker endpoint: Hosted dispatches this to itself through the queue when a remapping job is created; not a user API. Under the campaign's process lock it asks the model to fill the target design with the campaign's content, post-processes images, compiles the result and overwrites the campaign's markup and message (every variant of a split), records a version point and requests a screenshot, then marks the job success. Any failure marks the job failed with the reason, so the poll endpoint reports it. Requires the permission to update campaigns.","operationId":"process-a-campaign-content-remapping","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessContentRemappingRequest"}}}},"responses":{"200":{"description":"The campaign was rewritten. Status success with the job and campaign ids.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingJobSummary"}}}},"403":{"description":"The API user may not update campaigns."},"409":{"description":"Another request held the campaign's lock for longer than the worker was willing to wait; the job is marked failed and nothing was rewritten. The API's errors array with error_code CAMPAIGN_LOCKED."},"422":{"description":"The job already finished (success or failed), answered as this body; or requestId does not name a stored job; or the campaign stopped being editable or compatible with the XML flow since the job was created, answered as the API's errors array with error_code CAMPAIGN_NOT_EDITABLE or the compatibility code, and the job is marked failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}},"500":{"description":"The pipeline failed and the job is marked failed with this reason, or the job record could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/content-remapping/stock-template":{"post":{"tags":["AI"],"summary":"Remap a campaign into a stock template","description":"Starts a job that pours the campaign's existing content into an ActiveCampaign stock template, placing the brand kit's logo, and queues the worker that rewrites the campaign. The campaign is read and decompiled now; the rewrite happens in the worker, so poll GET /ai/campaigns/content-remapping/{requestId} for the outcome. Requires the permission to update campaigns. Left out, brandkitUuid falls back to the account's primary brand kit. With no brandkitUuid and no primary brand kit, the job is created without brand context.","operationId":"remap-a-campaign-into-a-stock-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingStockTemplateRequest"}}}},"responses":{"201":{"description":"The job was stored and queued. Its id, the campaign, and status in_progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingJobSummary"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"brandkitUuid names a brand kit the brand kit service cannot find.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}},"422":{"description":"The body is invalid: campaignId or hash is missing or does not name an existing record the API user may use, the campaign is sent or sending, or it was not built in the current designer with blocks the XML flow supports."},"500":{"description":"Reading the campaign, building the target or storing the job failed. Nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/content-remapping/template":{"post":{"tags":["AI"],"summary":"Remap a campaign into a saved template","description":"Starts a job that pours the campaign's existing content into one of the account's saved templates, placing the brand kit's logo, and queues the worker that rewrites the campaign. The campaign is read and decompiled now; the rewrite happens in the worker, so poll GET /ai/campaigns/content-remapping/{requestId} for the outcome. Requires the permission to update campaigns. Left out, brandkitUuid falls back to the account's primary brand kit. With no brandkitUuid and no primary brand kit, the job is created without brand context.","operationId":"remap-a-campaign-into-a-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingTemplateRequest"}}}},"responses":{"201":{"description":"The job was stored and queued. Its id, the campaign, and status in_progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingJobSummary"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"brandkitUuid names a brand kit the brand kit service cannot find.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}},"422":{"description":"The body is invalid: campaignId or templateId is missing or does not name an existing record the API user may use, the campaign is sent or sending, or it was not built in the current designer with blocks the XML flow supports."},"500":{"description":"Reading the campaign, building the target or storing the job failed. Nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/content-remapping/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve the status of a content remapping job","description":"Where a content remapping job stands. Answers 200 with status in_progress while the worker is running, success once the campaign was rewritten, or failed with the reason in error; step names the stage the worker last reported, and degradations lists what a finished job could not do. Only the user who started the job can read it: a job another user started, like an unknown id, answers 404. Requires the permission to update campaigns.","operationId":"retrieve-a-campaign-content-remapping","parameters":[{"name":"requestId","in":"path","description":"UUID of the job, as returned when it was created.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The job, in progress or finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingJobStatus"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"No content remapping job is stored under that id, or it was started by another user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentRemappingErrorResponse"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/edit":{"post":{"tags":["AI"],"summary":"Prepare a campaign email for AI edits","description":"Starts an AI edit of a campaign email: parses the message markup into text blocks, labels each block with a data-ai-block-id attribute in the saved markup, creates an edit request record holding the block list, subject and preheader, and queues the classification of the blocks. The request is answered as classifying; poll GET /ai/campaigns/edit/{requestId} for classified. Called by the campaign editor and the campaign agent. Answers 403 when the message is not built in the current editor, 422 when campaignId is missing or names no campaign, message or markup, and 500 when parsing, saving or queueing fails, in which case the record is marked error.","operationId":"prepare-a-campaign-for-ai-edits","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepRequest"}}}},"responses":{"200":{"description":"The edit request was created and classification queued. status is classifying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditStatusResponse"}}}},"403":{"description":"The campaign's message is not built in the current editor (ed_version 3)."},"422":{"description":"campaignId is missing, not an integer, or names no campaign, message or message markup."},"500":{"description":"Parsing the email, saving the markup or queueing the classification failed. The edit request, if created, is marked error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/categorize":{"post":{"tags":["AI"],"summary":"Run a queued text block classification","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/campaigns/edit; not a user API. Classifies the text blocks of the email by group and functionality with a model, writes the labels into the saved markup, stores the original HTML on the edit request and marks it classified. A failure of the classification itself is answered 200 with an error body, so the queue does not retry, and the request is marked error. Answers 403 when the message is not built in the current editor, 409 while the request is still pending, 422 when requestid or textblocks is missing or invalid or the stored request cannot be read, and 500 when the request is already in error.","operationId":"run-campaign-edit-classification","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategorizeRequest"}}}},"responses":{"200":{"description":"The job ran. The classified blocks when it succeeded; an error body when classifying or saving failed, with the request marked error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CategorizedBlocksResponse"},{"$ref":"#/components/schemas/CampaignEditWorkerErrorResponse"}]}}}},"403":{"description":"The campaign's message is not built in the current editor (ed_version 3)."},"409":{"description":"The edit request is still pending."},"422":{"description":"requestid is missing, not a UUID or names no edit request; textblocks is missing, empty or malformed; or the stored request or its campaign, message or markup cannot be read."},"500":{"description":"The edit request is already in error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/revert":{"post":{"tags":["AI"],"summary":"Run a queued revert once the edit settles","description":"Worker endpoint: Hosted dispatches this to itself through the queue from DELETE /ai/campaigns/edit/{requestId}/revert when an edit was still running; not a user API. Re-reads the edit request up to five times, sleeping longer between reads, until it is done or in error, then restores the original markup, subject and preheader and returns the request to classified. Builds its own error bodies: 400 when the request is still editing after the last read, 404 when no edit request is stored under request_id, 500 when restoring fails. Answers 422 when request_id is missing.","operationId":"run-a-queued-campaign-edit-revert","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollRevertRequest"}}}},"responses":{"200":{"description":"The original email is back in place. status is reverted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditRevertStatusResponse"}}}},"400":{"description":"The edit request was still running after the last read; the revert is cancelled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditRevertErrorResponse"}}}},"404":{"description":"No edit request is stored under request_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditRevertErrorResponse"}}}},"422":{"description":"request_id is missing or blank."},"500":{"description":"Restoring the message failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditRevertErrorResponse"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/run":{"post":{"tags":["AI"],"summary":"Run a queued AI edit","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/campaigns/edit/{requestId}/initialize; not a user API. Rewrites the classified text blocks of the email with a model according to the prompt, brand kit, summarization and images, saves the new markup, subject and preheader on the message, records the summarization on the edit request and marks it done. A failure of the rewrite is answered 200 with an error body, so the queue does not retry, and the request is marked error. Answers 400 when nothing is changed, marking the request error; 403 when the message is not built in the current editor; 409 while the request is pending or classifying or the summarization is in progress; 422 when request_id is missing or names no edit request, a field is malformed, or the brand kit or summarization is unknown; 500 when the request or summarization already errored.","operationId":"run-a-campaign-edit","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditDispatchRequest"}}}},"responses":{"200":{"description":"The job ran. status Successful when the message was rewritten and the request marked done; an error body when the rewrite failed, with the request marked error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignEditWorkerDoneResponse"},{"$ref":"#/components/schemas/CampaignEditWorkerErrorResponse"}]}}}},"400":{"description":"Nothing to change: no new brand kit or summarization, no prompt and no images. The request is marked error."},"403":{"description":"The campaign's message is not built in the current editor (ed_version 3)."},"409":{"description":"The edit request is pending or classifying, or the summarization is still in progress."},"422":{"description":"request_id is missing, not a UUID or names no edit request; a field has the wrong type; images is malformed or longer than 7; brandkit_id or summarization_id names no record; or the stored request or its campaign, message or markup cannot be read."},"500":{"description":"The edit request or the summarization is already in error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/swap-template":{"post":{"tags":["AI"],"summary":"Run a queued template swap","description":"Worker endpoint: Hosted dispatches this to itself through the queue from PUT /ai/campaigns/edit/{requestId}/swap-template; not a user API. Classifies the text blocks of the new layout, moves the current email's classified content into the matching blocks, saves the resulting markup and the new css on the message and marks the edit request done. A failure at either step is answered 200 with an error body, so the queue does not retry, and the request is marked error. Answers 403 when the message is not built in the current editor, 409 while the request is pending or classifying, 422 when request_id, html or css is missing or request_id names no edit request, and 500 when the request already errored.","operationId":"run-a-campaign-edit-template-swap","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapTemplateDispatchRequest"}}}},"responses":{"200":{"description":"The job ran. status Successful when the message was moved onto the new layout and the request marked done; an error body when classifying the new layout or swapping failed, with the request marked error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignEditWorkerDoneResponse"},{"$ref":"#/components/schemas/CampaignEditWorkerErrorResponse"}]}}}},"403":{"description":"The campaign's message is not built in the current editor (ed_version 3)."},"409":{"description":"The edit request is pending or classifying."},"422":{"description":"request_id, html or css is missing; request_id is not a UUID or names no edit request; or the stored request or its campaign, message or markup cannot be read."},"500":{"description":"The edit request is already in error."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve the classification status of an edit request","description":"Polled after POST /ai/campaigns/edit until the text blocks are classified. Answers 200 with the request id and its status once classification is complete: classified when the email is ready to edit, or editing or done when an edit was started since. Answers 409 while the request is pending or classifying, 500 when a step errored, 404 when no edit request is stored under requestId and 422 when requestId is not a UUID. The classified blocks themselves are not returned; the labels live in the saved markup.","operationId":"retrieve-campaign-edit-classification-status","parameters":[{"name":"requestId","in":"path","description":"UUID of the edit request, as answered by POST /ai/campaigns/edit.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Classification is complete. status is classified, editing or done.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditStatusResponse"}}}},"404":{"description":"No edit request is stored under requestId."},"409":{"description":"The request is still pending or classifying; poll again."},"422":{"description":"requestId is missing or not a UUID."},"500":{"description":"A step of the request errored, or the stored request cannot be read."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/edit/{requestId}/initialize":{"post":{"tags":["AI"],"summary":"Start an AI edit of a classified email","description":"Queues an AI rewrite of a classified campaign email: a brand kit to style with, a content summarization to draw on, a free-text prompt, a new subject or preheader, and images to place. At least one of a changed brandkitUuid, a changed summarizationUuid, an editPrompt or images must be given, or the call is refused with 400. Marks the edit request editing and dispatches the rewrite to POST /ai/campaigns/edit/run; poll GET /ai/campaigns/edit/{requestId}/results for the outcome. Called by the campaign editor and the campaign agent. Answers 404 when no edit request is stored under requestId, 409 while the request is pending, classifying or already editing, or while the summarization is still in progress, 422 when a field is malformed or brandkitUuid or summarizationUuid names no record, and 500 when the request or the summarization errored.","operationId":"start-a-campaign-edit","parameters":[{"name":"requestId","in":"path","description":"UUID of the edit request, as answered by POST /ai/campaigns/edit.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditRequest"}}}},"responses":{"200":{"description":"The rewrite was queued. status is editing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditStatusResponse"}}}},"400":{"description":"Nothing to change: no new brand kit or summarization, no prompt and no images."},"404":{"description":"No edit request is stored under requestId."},"409":{"description":"The edit request is pending, classifying or already editing, or the summarization is still in progress."},"422":{"description":"requestId is not a UUID; a body field has the wrong type; images is malformed or longer than 7; or brandkitUuid or summarizationUuid names no record of the account."},"500":{"description":"The edit request or the summarization is in error, or the stored request cannot be read."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/{requestId}/results":{"get":{"tags":["AI"],"summary":"Retrieve the result of an AI edit","description":"Polled after POST /ai/campaigns/edit/{requestId}/initialize or PUT /ai/campaigns/edit/{requestId}/swap-template until the edit is applied. Answers 200 only once the request is done: the campaign and the message as now stored, with the brand kit and summarization recorded on the request. Answers 409 while the request is pending, classifying or editing, 400 when it is classified, meaning no edit has been started, 500 when a step errored, 404 when no edit request is stored under requestId, 403 when the message is not built in the current editor and 422 when requestId is not a UUID or the request's campaign, message or markup no longer exists.","operationId":"retrieve-campaign-edit-results","parameters":[{"name":"requestId","in":"path","description":"UUID of the edit request, as answered by POST /ai/campaigns/edit.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The edit is done. The campaign and message as stored, plus the brand kit and summarization used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditResultsResponse"}}}},"400":{"description":"The request is classified: no edit has been started on it."},"403":{"description":"The campaign's message is not built in the current editor (ed_version 3)."},"404":{"description":"No edit request is stored under requestId."},"409":{"description":"The request is still pending, classifying or editing; poll again."},"422":{"description":"requestId is missing or not a UUID, or the request's campaign, message or markup no longer exists or does not match."},"500":{"description":"A step of the request errored, or the stored request cannot be read."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/edit/{requestId}/revert":{"delete":{"tags":["AI"],"summary":"Undo the AI edits of an email","description":"Puts the message markup, subject and preheader back to what was stored on the edit request when it was classified, and returns the request to classified so it can be edited again. When the request is done or in error the revert runs now and answers reverted; while an edit is still running it is queued to POST /ai/campaigns/edit/revert and answers reverting. Called by the campaign editor. Answers 400 when the request holds no original HTML to restore, 404 when no edit request is stored under requestId or its campaign, markup or message is gone, 422 when requestId is not a UUID and 500 when restoring or queueing fails.","operationId":"revert-a-campaign-edit","parameters":[{"name":"requestId","in":"path","description":"UUID of the edit request, as answered by POST /ai/campaigns/edit.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"reverted when the original email is back in place; reverting when the revert waits on a running edit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditRevertStatusResponse"}}}},"400":{"description":"The edit request holds no original HTML to restore."},"404":{"description":"No edit request is stored under requestId, or its campaign, markup or message no longer exists."},"422":{"description":"requestId is missing or not a UUID."},"500":{"description":"Restoring the message or queueing the revert failed."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/edit/{requestId}/swap-template":{"put":{"tags":["AI"],"summary":"Move an edited email onto another layout","description":"Queues a template swap for a classified campaign email: the classified content of the current message is carried over into the layout of another message, a saved template, a stock template or a purchased template, exactly one of which the body names. The server reads the html and css of that source. Marks the edit request editing and dispatches the swap to POST /ai/campaigns/edit/swap-template; poll GET /ai/campaigns/edit/{requestId}/results for the outcome. Called by the campaign editor. Answers 404 when no edit request is stored under requestId, 409 while the request is pending, classifying or already editing, 422 when none or more than one source is named or the source does not exist or is not a current editor layout, and 500 when the request errored or queueing failed.","operationId":"swap-a-campaign-edit-template","parameters":[{"name":"requestId","in":"path","description":"UUID of the edit request, as answered by POST /ai/campaigns/edit.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapTemplateRequest"}}}},"responses":{"200":{"description":"The swap was queued. status is editing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEditStatusResponse"}}}},"404":{"description":"No edit request is stored under requestId."},"409":{"description":"The edit request is pending, classifying or already editing."},"422":{"description":"requestId is not a UUID; none or more than one of messageId, templateId, stockTemplateId and purchasedTemplateId is set; or the source named does not exist or is not a current editor layout."},"500":{"description":"The edit request is in error, the stored request cannot be read, or queueing the swap failed. After a queueing failure the request stays marked editing."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/followup":{"post":{"tags":["AI"],"summary":"Create a followup automation for a campaign","description":"Creates an automation that follows up a sent campaign: a new series named after the campaign, with a start and an empty send block, then queues the generation of the followup email (POST /ai/campaigns/followup/generate), which fills the send block. The request is in_progress until that worker finishes; poll GET /ai/campaigns/followup/status/{seriesId}. Needs the manage automations permission (pg_automation_manage). Answers 403 without it, 422 when campaignId names no campaign or prompt is blank, and 500 when the automation cannot be built or the generation cannot be queued, in which case the half-built automation is removed again.","operationId":"create-a-campaign-followup-automation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequest"}}}},"responses":{"201":{"description":"The automation was created and the email generation queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignFollowupCreatedResponse"}}}},"403":{"description":"The user may not manage automations."},"422":{"description":"campaignId is missing, not a string or names no campaign, or prompt is blank."},"500":{"description":"The automation could not be created, or the email generation could not be queued (for instance brandkitUuid names no brand kit); the automation was rolled back."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/followup/generate":{"post":{"tags":["AI"],"summary":"Generate the followup email of an automation","description":"Worker step of a campaign followup. Hosted dispatches this to itself through the queue after POST /ai/campaigns/followup; not a user API. Writes the followup email with the model in the requested tone and language, styled with the brand kit when one is named, creates the campaign in the send block and marks the request completed. Needs the manage automations permission (pg_automation_manage). When the generation fails the request is marked error and the automation is removed: 422 when the model request is refused as unprocessable, 504 when it times out, 500 otherwise. Answers 422 as well when blockId names no send block, outputLang is missing or brandkitUuid names no brand kit.","operationId":"run-campaign-followup-email-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateRequest"}}}},"responses":{"200":{"description":"The email was generated and placed in the send block; the request is completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignFollowupGeneratedResponse"}}}},"403":{"description":"The user may not manage automations."},"422":{"description":"blockId names no send block, prompt, name or outputLang is missing, brandkitUuid names no brand kit, or the model refused the generation as unprocessable."},"500":{"description":"The generation failed; the request is marked error and the automation removed."},"504":{"description":"The model request timed out; the request is marked error and the automation removed."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/followup/status/{seriesId}":{"get":{"tags":["AI"],"summary":"Retrieve the status of a campaign followup","description":"Reports whether the followup email of the automation created by POST /ai/campaigns/followup is ready. Answers 409 while the generation is in_progress, 200 with an empty body once it is completed, at which point the caller opens the automation, and 500 when it failed. A seriesId with no followup request on record also answers 500, not 404.","operationId":"retrieve-campaign-followup-status","parameters":[{"name":"seriesId","in":"path","description":"Id of the automation (series) answered by POST /ai/campaigns/followup.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The followup email is generated and in the send block. No body."},"409":{"description":"The email generation is still in progress."},"500":{"description":"The email generation failed, or no followup request is recorded for this automation."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/from-stock-template/create":{"post":{"tags":["AI"],"summary":"Create a campaign from a stock template","description":"Creates a campaign for the current user from a stock template's content, then queues a background job that has the model rewrite the campaign's body, subject, preheader and name to the prompt. Answers 201 at once with the campaign id and the job id; the campaign holds the unchanged template until the job completes. Called by the campaign generation agent when the user picks a stock template.","operationId":"create-a-campaign-from-stock-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignFromStockTemplateRequest"}}}},"responses":{"201":{"description":"The campaign was created and the job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateToCampaignJobStartedResponse"}}}},"422":{"description":"A field is missing or invalid; see the errors list."},"500":{"description":"The campaign could not be created, or it was created but the job could not be queued.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Which step failed. \"Failed to create campaign. Please try again or contact support.\" when no campaign was created; \"Campaign created but failed to initiate processing. Please contact support.\" when the campaign exists but the job could not be stored or queued.","type":"string","example":"Failed to create campaign. Please try again or contact support."}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/from-stock-template/process":{"post":{"tags":["AI"],"summary":"Run a queued stock template to campaign job","description":"Worker endpoint: Hosted dispatches this to itself through the queue after Create a campaign from a stock template; not a user API. Runs the editing pipeline for the job: rewrites the campaign's content, subject, preheader and name to the stored prompt, applies the brand kit logo and any supplied images, and stores the outcome on the job. A job that already finished is refused with 422 so a redelivered message does not rewrite the campaign again.","operationId":"process-a-campaign-from-stock-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessTemplateToCampaignRequest"}}}},"responses":{"200":{"description":"The job ran and the campaign holds the rewritten content.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateToCampaignJobResultResponse"}}}},"413":{"description":"The model's output was truncated; the job is stored as failed with errorCode content_too_large.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"Processing failed.\"; the cause is only logged.","type":"string","example":"Processing failed."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}},"422":{"description":"requestId is missing, is not a UUID or names no stored job; or the job already finished, so it is not run twice.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Present when the job already finished: \"Job already completed, current status: success\" or \"... failed\". A failed body-level validation answers the standard errors list instead.","type":"string","example":"Job already completed, current status: success"}},"type":"object"}}}},"500":{"description":"The job was not found or the pipeline failed for a reason other than a model timeout or truncation; the job is stored as failed with errorCode generation_failed.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"Processing failed.\"; the cause is only logged.","type":"string","example":"Processing failed."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}},"504":{"description":"A model request timed out; the job is stored as failed with errorCode timeout.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"Processing failed.\"; the cause is only logged.","type":"string","example":"Processing failed."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/from-template/create":{"post":{"tags":["AI"],"summary":"Create a campaign from a template","description":"Creates a campaign for the current user from one of the account's Email Designer templates, recording source on it, then queues a background job that has the model rewrite the campaign's body, subject, preheader and name to the prompt and apply the brand kit logo. Answers 201 at once with the campaign id and the job id; the campaign holds the unchanged template until the job completes. Called by the campaign generation agent when the user picks one of their templates.","operationId":"create-a-campaign-from-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignFromTemplateRequest"}}}},"responses":{"201":{"description":"The campaign was created and the job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateToCampaignJobStartedResponse"}}}},"422":{"description":"A field is missing or invalid; see the errors list."},"500":{"description":"The campaign could not be created, or it was created but the job could not be queued.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Which step failed. \"Failed to create campaign. Please try again or contact support.\" when no campaign was created; \"Campaign created but failed to initiate processing. Please contact support.\" when the campaign exists but the job could not be stored or queued.","type":"string","example":"Failed to create campaign. Please try again or contact support."}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/from-template/process":{"post":{"tags":["AI"],"summary":"Run a queued template to campaign job","description":"Worker endpoint: Hosted dispatches this to itself through the queue after Create a campaign from a template; not a user API. Runs the editing pipeline for the job: rewrites the campaign's content, subject, preheader and name to the stored prompt, applies the brand kit logo and any supplied images, and stores the outcome on the job. A job that already finished is refused with 422 so a redelivered message does not rewrite the campaign again.","operationId":"process-a-campaign-from-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessTemplateToCampaignRequest"}}}},"responses":{"200":{"description":"The job ran and the campaign holds the rewritten content.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateToCampaignJobResultResponse"}}}},"413":{"description":"The model's output was truncated; the job is stored as failed with errorCode content_too_large.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"An error occurred during processing.\"; the cause is only logged.","type":"string","example":"An error occurred during processing."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}},"422":{"description":"requestId is missing, is not a UUID or names no stored job; or the job already finished, so it is not run twice.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Present when the job already finished: \"Job already completed, current status: success\" or \"... failed\". A failed body-level validation answers the standard errors list instead.","type":"string","example":"Job already completed, current status: success"}},"type":"object"}}}},"500":{"description":"The job was not found or the pipeline failed for a reason other than a model timeout or truncation; the job is stored as failed with errorCode generation_failed.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"An error occurred during processing.\"; the cause is only logged.","type":"string","example":"An error occurred during processing."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}},"504":{"description":"A model request timed out; the job is stored as failed with errorCode timeout.","content":{"application/json":{"schema":{"required":["error","errorCode"],"properties":{"error":{"description":"Always \"An error occurred during processing.\"; the cause is only logged.","type":"string","example":"An error occurred during processing."},"errorCode":{"description":"Why the run failed: timeout when the model request timed out, content_too_large when the model output was truncated, generation_failed for anything else.","type":"string","enum":["timeout","content_too_large","generation_failed"],"example":"generation_failed"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/reports/insights":{"get":{"tags":["AI"],"summary":"Retrieve an AI insight for campaign reporting","description":"Answers one of the Copilot insights shown on campaign reports: a model-written reading of the account's or one campaign's email metrics, returned with the metrics it was based on. The insight parameter picks which one; campaign_comparison, future_improvements and campaign_success read one campaign and need campaignId, while business_comparison, subject_line_recommendation and recent_campaigns read the account's campaigns. The answer is generated anew on every call. Gated on the reporting-copilot-ai feature flag. Answers 403 when the flag is off, 422 when insight is unknown or campaignId is missing, not an integer or names no campaign, 400 when the insight has no service behind it, and 500 when the model request fails or its answer does not fit the insight's schema.","operationId":"retrieve-campaign-report-insights","parameters":[{"name":"insight","in":"query","description":"Which insight to generate.","required":true,"schema":{"type":"string","enum":["business_comparison","subject_line_recommendation","recent_campaigns","campaign_comparison","future_improvements","campaign_success"]},"example":"campaign_success"},{"name":"campaignId","in":"query","description":"Id of the campaign to read, as a string of digits. Required for campaign_comparison, future_improvements and campaign_success; the other insights ignore it. Must name a campaign of the account when given.","schema":{"type":"string"},"example":"4821"}],"responses":{"200":{"description":"The generated insight.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignReportInsightsResponse"}}}},"400":{"description":"The insight has no service behind it."},"403":{"description":"The reporting Copilot is not enabled for this account."},"422":{"description":"insight is missing or not one of the known insights, or campaignId is missing for an insight that needs it, not an integer, or names no campaign."},"500":{"description":"The model request failed, or its answer did not match the insight's schema."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/scope-assessment/analyze":{"post":{"tags":["AI"],"summary":"Identify the campaign elements an edit request targets","description":"Asks the model which elements of a campaign's message an edit request is about: it converts the stored message markup to an XML outline, has the model pick the matching elements with a confidence score, and keeps only those whose id really exists in the markup. Nothing is changed or stored. Answers an empty list with isAmbiguous when the request is too vague to point at specific elements, 403 when the message is not an Email Designer message, 404 when the campaign has no stored message markup, and 422 when the markup cannot be converted.","operationId":"analyze-campaign-edit-scope","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeScopeRequest"}}}},"responses":{"200":{"description":"The elements identified for the edit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeAssessmentResponse"}}}},"403":{"description":"The campaign's message is not an Email Designer (ed_version 3) message."},"404":{"description":"No message markup is stored for the campaign's message.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Always \"Campaign not found\".","type":"string","example":"Campaign not found"}},"type":"object"}}}},"422":{"description":"campaignId or userPrompt is missing or invalid, the campaign or its message does not exist, or the stored markup could not be converted for analysis.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Present when the markup could not be converted: always \"Campaign content is invalid and cannot be processed\". A failed body-level validation answers the standard errors list instead.","type":"string","example":"Campaign content is invalid and cannot be processed"}},"type":"object"}}}},"500":{"description":"Reading the markup or the model call failed.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Always \"Internal server error\"; the cause is only logged.","type":"string","example":"Internal server error"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/split":{"post":{"tags":["AI"],"summary":"Start generating a split campaign message","description":"Starts an asynchronous request that writes a new version of an existing campaign message from a prompt, to serve as another message of a split campaign. Stores a request record, finds the text blocks of the original markup and queues the classification step (POST /ai/campaigns/split/classify), which queues the generation step in turn. The original message is not changed; poll GET /ai/campaigns/split/{requestId} for the result. Answers 400 when the original markup has no text block AI can edit, 422 when the body is invalid or origMessageId names no message with stored markup, and 500 when the request record cannot be stored or the classification cannot be queued.","operationId":"initialize-a-split-campaign-message-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitRequest"}}}},"responses":{"200":{"description":"The request record was stored and the classification step queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitCampaignRequestIdResponse"}}}},"400":{"description":"AI editing is not supported for this email: the original markup has no text block to rewrite. The request record is marked error."},"422":{"description":"origMessageId names no message with stored markup, prompt is blank, or components is empty or holds a value other than content, subject or preheader."},"500":{"description":"The request record could not be stored, the markup could not be read, or the classification step could not be queued."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/split/classify":{"post":{"tags":["AI"],"summary":"Classify the text blocks of a split campaign request","description":"Worker step of a split campaign message generation. Hosted dispatches this to itself through the queue after POST /ai/campaigns/split; not a user API. Asks the model what kind of text each labelled block of the original message is, moves the request record from classifying to classified and queues the generation step (POST /ai/campaigns/split/generate). When the classification or that dispatch fails the record is marked error, which the poll reports as 500. Answers 400 when the record is not in the classifying status and 422 when requestid names no split message request record or the payload is incomplete.","operationId":"run-split-campaign-message-classification","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncClassifyRequest"}}}},"responses":{"200":{"description":"The text blocks were classified and the generation step queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitCampaignRequestIdResponse"}}}},"400":{"description":"The request record is not in the classifying status: the step already ran, or the request is pending, done or failed."},"422":{"description":"requestid names no split message request record, its stored data cannot be read, or markup or text_blocks is missing."},"500":{"description":"The model could not classify the text blocks, or the generation step could not be queued; the request record is marked error."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/split/generate":{"post":{"tags":["AI"],"summary":"Generate the markup of a split campaign message","description":"Worker step of a split campaign message generation. Hosted dispatches this to itself through the queue after the classification step; not a user API. Rewrites the requested components (content, subject, preheader) of the original message with the model, marking the request record editing while it runs and done when it finishes, and stores the new subject, preheader and markup on the record for GET /ai/campaigns/split/{requestId} to answer. The original message is not changed. Answers 400 when the record is not in the classified status, 422 when requestid names no split message request record, the record's message no longer exists or markup is missing, and 500 when the generation fails, in which case the record is marked error.","operationId":"run-split-campaign-message-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncGenerateRequest"}}}},"responses":{"200":{"description":"The new message was generated and stored on the request record, now done.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitCampaignRequestIdResponse"}}}},"400":{"description":"The request record is not in the classified status: the step already ran, or the request is pending, classifying, done or failed."},"422":{"description":"requestid names no split message request record, its stored data cannot be read, the original message no longer exists, or markup is missing."},"500":{"description":"The model could not generate the message; the request record is marked error."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/campaigns/split/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a generated split campaign message","description":"Reads the outcome of a split campaign message generation started with POST /ai/campaigns/split. While the request record is pending, classifying, classified or editing it answers 409 with a message naming the step that is running. Once the record is done it answers 200 with the message fields: each component that was requested (content, subject, preheader) carries the generated value and every other field the original message's value, and the HTML is compiled from the markup for display. A record marked error answers 500. Answers 404 when requestId names no split message request record and 422 when the original message or its stored markup no longer exists.","operationId":"retrieve-a-split-campaign-message-generation","parameters":[{"name":"requestId","in":"path","description":"The requestId answered by POST /ai/campaigns/split.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The generation is done. The message with the requested components generated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitCampaignMessageResponse"}}}},"404":{"description":"No split message request record exists under that requestId."},"409":{"description":"The request is still running: pending, classifying, classified (the message is being generated) or editing."},"422":{"description":"The original message or its stored markup no longer exists."},"500":{"description":"The request failed to generate (status error), its stored data cannot be read, or the message could not be compiled."}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/campaigns/{campaignId}/edit":{"put":{"tags":["AI"],"summary":"Queue an AI edit of a campaign by its id","description":"Queues an AI edit of an existing campaign named by its id rather than by a generation request id: a brand kit, a template, summarized external content, an edit prompt, blocks or images. A temporary endpoint for testing brand kit application on arbitrary campaigns. Checks the campaign and its message exist, that the campaign is not sent, and that it was built in the current designer with blocks the XML flow supports; creates a generation record for the edit, then queues the update the same way the generation flow does. Answers 200 at once with the record's id; poll GET /ai/campaign/generation/poll/{requestId} for the outcome. Requires the permission to update campaigns.","operationId":"edit-a-campaign-by-id","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign to edit.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditByCampaignIdRequest"}}}},"responses":{"200":{"description":"The edit was queued. The id to poll it by.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditByCampaignIdAccepted"}}}},"403":{"description":"The API user may not update campaigns."},"404":{"description":"No campaign, or no message of the campaign, exists under campaignId."},"409":{"description":"A generation or edit of this campaign is already in progress."},"422":{"description":"The campaign has already been sent (error_code CAMPAIGN_NOT_EDITABLE); or it is not compatible with the XML flow (error_code names the reason, such as UNSUPPORTED_EDITOR_VERSION or UNSUPPORTED_BLOCKS); or an edit of it is already in progress; or the chosen external content is still processing or in error; or nothing in the body differs from what the campaign already has; or the body is invalid."},"500":{"description":"The generation record could not be reloaded after a status reset, or queueing the update failed."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/compose":{"post":{"tags":["AI"],"summary":"Generate marketing copy from a prompt","description":"Has the model write resultCount versions of the text the prompt asks for, in the given tone and, when a brand kit is named, in its voice. Nothing is stored. A model failure still answers 200, with error set and results empty. Answers 403 when the account lacks the AI content generator entitlement, and 422 when the body fails validation or brandkitUuid names no stored brand kit (the latter with an empty object body).","operationId":"compose-content","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentComposeRequest"}}}},"responses":{"200":{"description":"The generated texts, or error with an empty results when the model failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCompletionResponse"}}}},"403":{"description":"The account lacks the ai-content-generator entitlement (detail: Unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation (standard error list), or brandkitUuid names no stored brand kit: that case answers an empty JSON object, because the result object built for it has no public fields and no JSON serializer, so its Invalid brandkit UUID message is lost.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"description":"An empty object: the unknown brand kit case.","maxProperties":0,"type":"object"}]}}}}},"x-canonical-resource":"content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/consumption":{"get":{"tags":["AI"],"summary":"Retrieve the account's AI consumption","description":"Returns the account's monthly AI allowance, how much of it has been used and whether it is exhausted. An account with no AI entitlement reads as a limit and usage of 0 and over_limit true.","operationId":"retrieve-ai-consumption","responses":{"200":{"description":"The account's AI allowance and usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmConsumptionResponse"}}}},"500":{"description":"The consumption could not be read."}},"x-canonical-resource":"agent_consumption","x-internal":true}},"/ai/contact-model/search":{"get":{"tags":["AI"],"summary":"Search this account's lists, tags, and fields by name","description":"Returns at most 10 lists, 10 tags, and 10 fields on this account whose names contain every word in q. Lists and tags are largest stored contact count first; fields are ordered by title. For a restricted user, lists and fields are limited to those they can access. A missing or blank q is 400. The contact-model flag off is 404 and does not query. A q that is not valid UTF-8 returns empty arrays and does not query. This does not read contact field values.","operationId":"search-contact-model","parameters":[{"name":"q","in":"query","description":"Words to match. Every word must appear in the name. Example: interest drums matches INTEREST - Drums.","required":true,"schema":{"type":"string"},"example":"interest drums"}],"responses":{"200":{"description":"Matching lists, tags, and fields for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactModelSearchResponse"}}}},"400":{"description":"q is missing or blank."},"404":{"description":"The contact-model flag is off."}},"x-canonical-resource":"contact","x-internal":true}},"/ai/conversions/performance/dead-letter-queue/delete":{"post":{"tags":["AI"],"summary":"Delete or preview messages in a Generative Marketing dead letter queue","description":"Operations tooling for the SQS queues behind business goal initiatives, performance summaries and recommendations. Given the URL of one of those source queues, the call reads its redrive policy to find the dead letter queue, receives up to maxReceiveCount messages from it, and deletes them for good; with isDryRun true it returns them instead so the deletion can be previewed. With messageId it acts on that one message only. The call always answers 200 once the body is valid: a refused queue (one not among the three configured Generative Marketing queues), a queue without a redrive policy, or an SQS failure come back as success false with the cause in errors, and a message SQS would not delete adds an error of its own. The queues are shared by every account, so messages of other accounts can be deleted; x-internal only hides the operation from the public documentation and is not access control.","operationId":"delete-dead-letter-queue-messages","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMessagesRequest"},"example":{"sourceQueueUrl":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives","maxReceiveCount":10,"isDryRun":true}}}},"responses":{"200":{"description":"The outcome. Check success: a refused queue or an SQS failure is reported here, not as an error status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueDeleteResponse"},"example":{"success":true,"messages_processed":1,"messages_deleted":0,"messages":[{"MessageId":"e5f6a7b8-1234-4c3d-9e8f-0a1b2c3d4e5f","ReceiptHandle":"AQEB7xk2...","Body":"{\"accountId\":1234,\"goalId\":2228,\"conversionId\":23}","MessageAttributes":{"endpoint":{"DataType":"String","StringValue":"api/3/ai/initiatives/recipes/prepopulate"}}}],"errors":[],"dry_run":true,"dead_letter_queue_url":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives-dlq"}}}},"422":{"description":"sourceQueueUrl is missing, blank or not a URL, maxReceiveCount is outside 1 to 100, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/sourceQueueUrl"}}]}}}},"500":{"description":"The call failed outside the service's own error handling. Rare, since SQS and queue failures are reported in the 200 body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal Server Error","detail":"Failed to delete messages: Connection reset by peer"}]}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/conversions/performance/dead-letter-queue/redrive":{"post":{"tags":["AI"],"summary":"Redrive or preview messages in a Generative Marketing dead letter queue","description":"Operations tooling for the SQS queues behind business goal initiatives, performance summaries and recommendations. Given the URL of a source queue, the call reads its redrive policy to find the dead letter queue, receives up to maxReceiveCount messages from it, sends each back to the source queue with its body and attributes, and removes it from the dead letter queue; with isDryRun true nothing is sent or removed and the messages a real run would redrive are only counted. With messageId it acts on that one message only. The call always answers 200 once the body is valid: a queue without a redrive policy, or an SQS failure, comes back as success false with the cause in errors, and a message that could not be sent back or removed adds an error of its own. Unlike dead-letter-queue/delete, the source queue is not checked against the three configured Generative Marketing queues: any syntactically valid URL is used, so the call acts on whichever queue it is given, limited only by what Hosted's AWS role is allowed to do on it. The configured queues are shared by every account, so messages of other accounts are redriven too; x-internal only hides the operation from the public documentation and is not access control.","operationId":"redrive-dead-letter-queue-messages","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedriveDeadLetterQueueRequest"},"example":{"sourceQueueUrl":"https://sqs.us-east-1.amazonaws.com/123456789012/gen-marketing-initiatives","maxReceiveCount":10,"isDryRun":true}}}},"responses":{"200":{"description":"The outcome. Check success: a queue without a redrive policy or an SQS failure is reported here, not as an error status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueRedriveResponse"},"example":{"success":true,"messages_processed":2,"messages_redriven":2,"errors":[],"dry_run":false}}}},"422":{"description":"sourceQueueUrl is missing, blank or not a URL, maxReceiveCount is outside 1 to 100, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/sourceQueueUrl"}}]}}}},"500":{"description":"The call failed outside the service's own error handling. Rare, since SQS and queue failures are reported in the 200 body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterQueueErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal Server Error","detail":"Failed to redrive dead letter queue: Connection reset by peer"}]}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/conversions/performance/summary":{"post":{"tags":["AI"],"summary":"Create or read the AI performance summary of a conversion for a business goal","description":"Returns the AI-generated performance summary of one conversion within one business goal, generating it when needed. The goals dashboard calls this when the conversion's card is expanded and then polls this same operation. Behaviour depends on what is stored for the goal and conversion pair: when a finished summary (status success or error) exists and is younger than expirationHours, it is returned as is; when the stored summary is still in progress, the answer is 409; otherwise a new record is created with status in_progress, the per-goal-and-conversion lock is taken for up to 90 seconds, and a generation request is queued to POST /ai/conversions/performance/summary/generate, which releases the lock when it finishes. While that lock is held, before anything is read, the answer is 200 with message done and status redlocked. The record and lock are per account. Answers 422 when goalId or conversionId is missing or does not exist on the account, or intervalDays, expirationHours or tone is out of range, and 500 when the generation request cannot be queued (the record is then stored with status error) or anything else fails.","operationId":"create-conversion-performance-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversionSummaryRequest"},"example":{"goalId":2228,"conversionId":23,"intervalDays":7,"expirationHours":24,"tone":"friendly"}}}},"responses":{"200":{"description":"The summary record (created now, or the stored finished one), or a redlocked notice when another request holds the lock.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ConversionsPerformanceSummaryCreateResponse"},{"$ref":"#/components/schemas/ConversionsPerformanceSummaryRedlockedResponse"}]},"example":{"id":"ai-conversions-performance-summary-2228-23","status":"in_progress","summary":null}}}},"409":{"description":"The stored summary for this goal and conversion is still being generated. Keep polling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"Conversions Performance Summary is in progress"}]}}}},"422":{"description":"goalId or conversionId is missing or names nothing on the account, intervalDays is not 1 to 30, expirationHours is not 1 to 168, tone is not one of the available tones, or a field has the wrong JSON type. One error per failed check.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title","detail","source"],"properties":{"status":{"type":"integer","enum":[422]},"title":{"type":"string","enum":["Invalid attribute"]},"detail":{"description":"Which check failed: \"This value should not be blank.\" or \"The entity does not exist\" for goalId and conversionId, \"intervalDays must be between 1 and 30.\", \"expirationHours must be between 1 and 168.\", \"Invalid tone. Valid tone choices are: ...\" listing them, or \"Unexpected type\".","type":"string"},"source":{"required":["pointer"],"properties":{"pointer":{"description":"The field, as /data/attributes/<field name>.","type":"string"}},"type":"object"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/conversionId"}}]}}}},"500":{"description":"The generation request could not be queued (the new record is stored with status error and the lock released; the detail is the queueing failure's message), the stored record could not be read, or anything else failed (detail Unexpected Error Occurred, cause only logged).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Unexpected Error Occurred"}]}}}}},"x-canonical-resource":"conversion","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/conversions/performance/summary/generate":{"post":{"tags":["AI"],"summary":"Generate the AI performance summary of a conversion (background worker)","description":"Background worker target, not a client API: Hosted's own dispatcher calls it after POST /ai/conversions/performance/summary stores an in-progress record and queues generation. It gathers the conversion's performance for the goal over intervalDays, asks the AI model for a summary in the given tone, saves the result on the stored record, and releases the per-goal-and-conversion lock. It answers 200 with the final status: success, or error when the model call failed (the record is then stored with status error). An already successful record is answered success without generating again. When the conversion is no longer linked to the goal, or has no data in either period, the record is stored as a success with a fixed text and the model is not called. A summaryId with no stored record is answered 200 with status error and message Summary record not found, not 404. Answers 422 when a field is missing or out of range and 500 when something fails outside the model call; the cause is only logged.","operationId":"generate-conversion-performance-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionsPerformanceSummaryGenerateRequest"},"example":{"summaryId":"ai-conversions-performance-summary-2228-23","tone":"friendly","intervalDays":7}}}},"responses":{"200":{"description":"The generation finished (success or error), or there was no stored record to generate (status error with a message).","content":{"application/json":{"schema":{"required":["status"],"properties":{"status":{"description":"success when the summary was saved. error when the model call failed, or when no record is stored for the summaryId.","type":"string","enum":["success","error"],"example":"success"},"message":{"description":"Present only when no record is stored for the summaryId, with the text Summary record not found.","type":"string","example":"Summary record not found"}},"type":"object"},"example":{"status":"success"}}}},"422":{"description":"summaryId or tone is missing or blank, tone is not an available tone, intervalDays is missing or not 1 to 30, or a field has the wrong JSON type. One error per failed check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"intervalDays must be between 1 and 30","source":{"pointer":"/data/attributes/intervalDays"}}]}}}},"500":{"description":"Something failed outside the model call, for example while gathering the performance data. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Unexpected Error Occurred"}]}}}}},"x-canonical-resource":"conversion","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/conversions/performance/{conversionId}/summary/{goalId}":{"get":{"tags":["AI"],"summary":"Retrieve the performance summary of a conversion linked to a goal","description":"Returns the summary of how one conversion linked to a business goal performed, as last stored by POST /ai/conversions/performance/summary, which starts generation. A summary is stored per goal and conversion, not per user, so every user of the account reads the same one. This call only reads: it never starts, refreshes or expires a summary, so it returns the stored one however old it is. Answers 404 until a summary has been requested for this goal and conversion, and again once the stored summary is cleared. Hosted clears it on some changes to the goal, the conversion or the link between them (for example archiving or deleting the goal, removing the conversion from it, or changing its target), and when a segment trigger fires for new contacts. While status is in_progress, summary is null. Poll with a time limit: a summary whose generation stopped without recording a result stays in_progress, and POST does not replace it, until it is cleared. The read can go to a database replica that lags, so right after a POST this call can briefly answer 404 or the previous summary.","operationId":"retrieve-a-conversion-performance-summary","parameters":[{"name":"conversionId","in":"path","description":"ID of the conversion.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"},"example":23},{"name":"goalId","in":"path","description":"ID of the business goal the conversion is linked to.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"},"example":2228}],"responses":{"200":{"description":"The stored summary and its status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionsPerformanceSummary"},"example":{"goalId":2228,"conversionId":23,"status":"success","summary":"There are no updates at this time. Add a conversion and goal to generate a summary!"}}}},"404":{"description":"No summary is stored for this goal and conversion: none was requested yet, or it was cleared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Summary record not found for ai-conversions-performance-summary-2228-23"}]}}}},"500":{"description":"Reading the stored summary failed, or its goalId, conversionId or status is missing, empty or zero (errors, with the cause in detail). The body is message instead when the stored goalId or conversionId is a non-numeric string or a JSON array or object, status is a non-empty JSON array or object, or summary is any JSON array or object, and when an ID in the path is larger than 9223372036854775807.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},{"$ref":"#/components/schemas/ServerErrorResponse"}]},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Invalid ConversionsPerformanceSummary data"}]}}}}},"x-canonical-resource":"conversion","x-internal":true}},"/ai/customization/account-instructions":{"put":{"tags":["AI"],"summary":"Update the AI instruction of the account","description":"Replaces the text of the instruction the AI agent follows for every user on the account. It is 404 when the account has no instruction yet; use the create operation first. Only admin users of the account can update it.","operationId":"update-ai-account-instruction","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionRequest"}}}},"responses":{"200":{"description":"The instruction after the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountInstructionRecord"}}}},"400":{"description":"The instruction was rejected by the content guardrail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionGuardrailViolationResponse"}}}},"403":{"description":"The caller is not an admin user of the account."},"404":{"description":"The account has no instruction to update."},"422":{"description":"content is missing, longer than 4000 characters, or contains an emoji."}},"x-canonical-resource":"custom_instruction","x-destructive":true,"x-bulk-operation":false},"post":{"tags":["AI"],"summary":"Create the AI instruction of the account","description":"Saves the instruction the AI agent follows for every user on the account. An account has at most one, so this is 409 when one already exists; use the update operation to change it. Only admin users of the account can create it.","operationId":"create-ai-account-instruction","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionRequest"}}}},"responses":{"201":{"description":"The instruction that was saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountInstructionRecord"}}}},"400":{"description":"The instruction was rejected by the content guardrail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionGuardrailViolationResponse"}}}},"403":{"description":"The caller is not an admin user of the account."},"409":{"description":"The account already has an instruction."},"422":{"description":"content is missing, longer than 4000 characters, or contains an emoji."}},"x-canonical-resource":"custom_instruction","x-destructive":false,"x-bulk-operation":false},"delete":{"tags":["AI"],"summary":"Delete the AI instruction of the account","description":"Removes the instruction the AI agent follows for every user on the account. Only admin users of the account can delete it.","operationId":"delete-ai-account-instruction","responses":{"204":{"description":"The instruction was deleted."},"403":{"description":"The caller is not an admin user of the account."},"404":{"description":"The account has no instruction to delete."}},"x-canonical-resource":"custom_instruction","x-destructive":true,"x-bulk-operation":false}},"/ai/customization/instructions":{"get":{"tags":["AI"],"summary":"List the AI instructions of the account","description":"Returns the instruction the account has given the AI agent, which the agent follows for every user on the account. The instructions array is empty when the account has not set one. Any user of the account can read it.","operationId":"list-ai-instructions","responses":{"200":{"description":"The account's instruction, if it has one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionListResponse"}}}}},"x-canonical-resource":"custom_instruction"}},"/ai/customization/memories":{"get":{"tags":["AI"],"summary":"List the calling user's AI memories","description":"Returns a page of the memories the AI agent holds for the user making the request, newest first.","operationId":"list-ai-memories","parameters":[{"name":"limit","in":"query","description":"How many memories to return. A value below 1 returns 20, and anything above 100 returns 100.","required":false,"schema":{"type":"integer","default":20},"example":20},{"name":"offset","in":"query","description":"How many of the newest memories to skip. A negative value counts as 0.","required":false,"schema":{"type":"integer","default":0},"example":0}],"responses":{"200":{"description":"One page of the user's memories.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryListResponse"}}}}},"x-canonical-resource":"agent_memory","x-internal":true},"post":{"tags":["AI"],"summary":"Create an AI memory for the calling user","description":"Adds one memory to those the AI agent holds for the user making the request. The id and timestamps are set by the server.","operationId":"create-ai-memory","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRequest"}}}},"responses":{"201":{"description":"The memory that was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryItemResponse"}}}},"400":{"description":"The content was rejected by the content guardrail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryGuardrailViolationResponse"}}}},"409":{"description":"The user's memories would come to more than 1000 characters in total. Nothing is saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryLimitExceededResponse"}}}},"422":{"description":"content is missing, longer than 4000 characters, or contains an emoji."}},"x-canonical-resource":"agent_memory","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/customization/memories/bulk":{"put":{"tags":["AI"],"summary":"Replace all of the calling user's AI memories","description":"Saves the memories in the body as the complete set the AI agent holds for the user making the request, replacing what was there. A memory with a memoryId keeps that id, and its createdAt is kept when the body omits it or the memory is unchanged; one without a memoryId takes the id of an unchanged stored memory with the same content, or a new id. Stored memories missing from the body are deleted. Responds 201 with the saved set.","operationId":"replace-ai-memories","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkMemoryRequest"}}}},"responses":{"201":{"description":"The memories the user now has.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryBulkResponse"}}}},"400":{"description":"The content was rejected by the content guardrail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryGuardrailViolationResponse"}}}},"409":{"description":"The user's memories would come to more than 1000 characters in total. Nothing is saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryLimitExceededResponse"}}}},"422":{"description":"content is missing, longer than 4000 characters, or contains an emoji."}},"x-canonical-resource":"agent_memory","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/customization/memories/{memoryId}":{"put":{"tags":["AI"],"summary":"Update one of the calling user's AI memories","description":"Replaces the content of one memory the AI agent holds for the user making the request and sets its updatedAt. Only content is read from the body.","operationId":"update-ai-memory","parameters":[{"name":"memoryId","in":"path","description":"Id of the memory to update.","required":true,"schema":{"type":"string"},"example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRequest"}}}},"responses":{"200":{"description":"The memory after the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryItemResponse"}}}},"400":{"description":"The content was rejected by the content guardrail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryGuardrailViolationResponse"}}}},"404":{"description":"The user has no memory with this id."},"409":{"description":"The user's memories would come to more than 1000 characters in total. Nothing is saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryLimitExceededResponse"}}}},"422":{"description":"content is missing, longer than 4000 characters, or contains an emoji."}},"x-canonical-resource":"agent_memory","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete one of the calling user's AI memories","description":"Removes one memory the AI agent holds for the user making the request.","operationId":"delete-ai-memory","parameters":[{"name":"memoryId","in":"path","description":"Id of the memory to delete.","required":true,"schema":{"type":"string"},"example":"3f9c2a7be1d44f0c9a6b5d8e7c1a2b34"}],"responses":{"204":{"description":"The memory was deleted."},"404":{"description":"The user has no memory with this id."}},"x-canonical-resource":"agent_memory","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/customization/permissions":{"get":{"tags":["AI"],"summary":"List the calling user's AI permission rules","description":"Returns the rules the user making the request has stored about what the AI agent may do on their behalf. A user with no rules gets an empty list, which means the agent asks before acting.","operationId":"list-ai-permission-rules","responses":{"200":{"description":"The calling user's permission rules.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionRulesResponse"}}}}},"x-canonical-resource":"agent_permission_rule","x-internal":true},"put":{"tags":["AI"],"summary":"Save AI permission rules for the calling user","description":"Merges the rules in the body into those the user making the request has stored, and returns the full resulting set. A rule is identified by its resource and operation: one already stored takes the new verdict, one not stored is added, and stored rules the body does not mention are kept. A body may hold at most 200 rules, and a user may have at most 200 in total.","operationId":"upsert-ai-permission-rules","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPermissionRulesRequest"}}}},"responses":{"200":{"description":"Every rule the user now has.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionRulesResponse"}}}},"400":{"description":"The merged set would have more than 200 rules."},"422":{"description":"The body has more than 200 rules, or a rule has a missing or invalid resource, operation, verdict or scope."}},"x-canonical-resource":"agent_permission_rule","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/customization/permissions/{ruleId}":{"delete":{"tags":["AI"],"summary":"Delete one of the calling user's AI permission rules","description":"Removes one rule, which returns that resource and operation to being asked about.","operationId":"delete-ai-permission-rule","parameters":[{"name":"ruleId","in":"path","description":"Id of the rule to delete, as returned in ruleId.","required":true,"schema":{"type":"string"},"example":"8b1a6dc4b72dba6a7a0e3b17da0bb0ed"}],"responses":{"204":{"description":"The rule was deleted."},"404":{"description":"The user has no rule with this id."}},"x-canonical-resource":"agent_permission_rule","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/customization/user-profile":{"get":{"tags":["AI"],"summary":"Retrieve the calling user's AI profile","description":"Returns the AI-generated profile of the user making the request. A user with no profile yet gets an empty one. Reading the profile records the time it was last read. A stored profile that cannot be read is 404.","operationId":"retrieve-ai-user-profile","responses":{"200":{"description":"The calling user's profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileResponse"}}}},"404":{"description":"The stored profile is corrupt and cannot be read."}},"x-canonical-resource":"agent_user_profile","x-internal":true},"post":{"tags":["AI"],"summary":"Regenerate the calling user's AI profile","description":"Rebuilds the profile of the user making the request from their last 30 days of AI conversations, replacing the stored one, and returns it. The call waits for the rebuild. A call made while a rebuild for the same user started within the last 60 seconds is 429 with a Retry-After header. A user with no recent conversations gets an empty profile.","operationId":"refresh-ai-user-profile","responses":{"200":{"description":"The regenerated profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileResponse"}}}},"429":{"description":"A refresh for this user started within the last 60 seconds. Retry-After gives the wait in seconds."},"500":{"description":"The profile could not be regenerated."}},"x-canonical-resource":"agent_user_profile","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/customization/user-profile/backfill":{"post":{"tags":["AI"],"summary":"Queue a first AI profile for the calling user","description":"Queues a job that builds the profile of the user making the request from their AI conversation history, and returns without waiting for it. Nothing is queued when the user already has a profile or has no recent conversations.","operationId":"backfill-ai-user-profile","responses":{"200":{"description":"Whether a job was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileBackfillResponse"}}}},"500":{"description":"The job could not be queued."}},"x-canonical-resource":"agent_user_profile","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/customization/user-profile/refresh-async":{"post":{"tags":["AI"],"summary":"Run a queued AI profile refresh","description":"Worker endpoint that Hosted calls on itself through the queue; it is not meant to be called directly. Rebuilds the profile of one user from their last 30 days of AI conversations, replacing the stored one. A user who no longer exists, or one whose refresh is already running, is skipped and still answered 200 so the queue does not retry. An account_id that is not the calling account's is 403.","operationId":"run-ai-user-profile-refresh-job","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileRefreshRequest"}}}},"responses":{"200":{"description":"The job ran or was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileRefreshJobResponse"}}}},"403":{"description":"account_id is not the calling account's."},"422":{"description":"account_id or user_id is missing or not a positive integer."},"500":{"description":"The refresh failed."}},"x-canonical-resource":"agent_user_profile","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic-data/finish":{"post":{"tags":["AI"],"summary":"Complete an AI content automation block with the generated content","description":"Final step of an AI content (dynamic data) automation block. The Bedrock processing service posts it back once it has generated the content for a contact (its callback URL is api/3/ai/dynamic-data/finish), and Hosted dispatches it to itself through the queue after POST /ai/dynamic-data/generate; not a user API. With generated_content set it writes the text to the field the block targets (name, first or last name, phone, customer account, or a custom field; a prompt action result is decoded from its JSON first) and restarts the automation at the block. With generated_content null it skips the block, recording a guardrail violation when guardrail_policy is set and a content generation failure otherwise; a field that cannot be written skips the block too. Every outcome answers 200 and the message says whether the block was processed or skipped. Answers 422 when blockid or contactseriesid names no record or the block is not an aidynamicdata block.","operationId":"finish-an-ai-dynamic-data-block","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizeRequest"}}}},"responses":{"200":{"description":"The block was completed: the content was written to the field (processed), or the block was skipped and the reason recorded in the automation history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataBlockProcessingResponse"}}}},"422":{"description":"blockid or contactseriesid names no record, the block is not an aidynamicdata block, or a field has the wrong type."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic-data/generate":{"post":{"tags":["AI"],"summary":"Generate the content of an AI content automation block inside Hosted","description":"Temporary endpoint: runs the model for an AI content (dynamic data) automation block inside Hosted and dispatches POST /ai/dynamic-data/finish to itself through the queue with the result. Only the AWS dynamic data processing system calls it, as the callback URL Hosted hands it in the dev environment (api/3/ai/dynamic-data/generate) instead of the finish URL; it exists only until processing is fully moved to that system. Not a user API. A model error or a guardrail intervention skips the block and restarts the automation, still answering 200. Answers 422 when blockId or subscriberSeriesId names no record, the block is not an aidynamicdata block, or personalizedContent or processStartTime is missing.","operationId":"generate-ai-dynamic-data-block-content","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataGenerateRequest"}}}},"responses":{"200":{"description":"The content was generated and the finish step dispatched (processed), or the generation failed and the block was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataBlockProcessingResponse"}}}},"422":{"description":"blockId or subscriberSeriesId names no record, the block is not an aidynamicdata block, a required field is missing, or a field has the wrong type."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic-data/preview":{"post":{"tags":["AI"],"summary":"Start a preview of an AI content block prompt","description":"Starts a preview of the prompt of an AI content (dynamic data) automation block on sample contacts. Finds the personalization tags in the prompt, starts the search for contacts that have a value for every tag and stores a preview record keyed by the tags, answering its id for POST /ai/dynamic-data/preview/{requestId}. A record for the same tags created less than 30 seconds ago that still has contacts not yet shown is reused and its id answered again; an older one, one whose contacts are all used, or one whose tags differ is deleted and replaced. Answers 422 when prompt is blank, or holds no personalization tag or more than 3, and 500 when the tags cannot be read from the prompt or the record cannot be read or stored.","operationId":"initiate-an-ai-dynamic-data-preview","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewRequest"}}}},"responses":{"201":{"description":"The preview record was created or a fresh one reused. Its id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataPreviewRequestIdResponse"}}}},"422":{"description":"prompt is blank, or holds no personalization tag or more than 3."},"500":{"description":"The personalization tags could not be read from the prompt, or the preview record could not be read or stored."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic-data/preview/{requestId}":{"post":{"tags":["AI"],"summary":"Generate a preview of an AI content block prompt for a sample contact","description":"Generates the text an AI content (dynamic data) automation block would write for one sample contact. On the first call the preview record started by POST /ai/dynamic-data/preview is filled with up to 10 contacts that have a value for every personalization tag in the prompt; each call then picks one not yet shown, fills its values into the prompt, runs the model and marks the contact used. A record older than 30 seconds or with no contact left is replaced and the preview built on the new one. Answers 201 with the contact and the generated text; 400 with type general when no contact has a value for every tag, or type guardrail_violation when the model's guardrail blocked the generation; 404 when requestId names no preview record; 409 when the contact search behind the record has not finished; 422 when prompt is blank or its tags are not the ones the record was started with; 500 when the tags cannot be read, a record cannot be read or stored, or the model fails.","operationId":"generate-an-ai-dynamic-data-preview","parameters":[{"name":"requestId","in":"path","description":"The requestId answered by POST /ai/dynamic-data/preview: the md5 of the personalization tags in the prompt.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewRequest"}}}},"responses":{"201":{"description":"A preview was generated for one contact of the record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataPreviewResponse"}}}},"400":{"description":"No preview could be generated: no contact has a value for every tag in the prompt (type general), or the guardrail blocked the generation (type guardrail_violation).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataPreviewErrorResponse"}}}},"404":{"description":"No preview record exists under that requestId."},"409":{"description":"The contact search behind the preview record has not finished; try again."},"422":{"description":"prompt is blank, or the personalization tags in it are not the ones the record was started with."},"500":{"description":"The personalization tags could not be read, a preview record could not be read or stored, or the model could not generate the content."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic-data/process":{"post":{"tags":["AI"],"summary":"Process an AI content automation block for a contact","description":"Second step of an AI content (dynamic data) automation block. Hosted dispatches this to itself through the queue from AIDynamicDataBlock::runProcessing when a contact enters the block; not a user API. Checks the account's AI consumption limit, fills the contact's values into the block's prompt (and tool input) and hands the generation to the Bedrock processing pipeline, which posts the result back to POST /ai/dynamic-data/finish; for a prompt action block (promptdata.type other than generic) it builds that action's processing payload instead. The automation stays waiting at the block until the finish step. Every failure, including the consumption limit, a prompt the contact cannot personalize or a personalized prompt over 3000 characters, also answers 200: the block is skipped with the reason recorded in the automation history and the automation restarted. Answers 422 when blockid or contactseriesid names no record, the block is not an aidynamicdata block, starttime is missing or promptdata misses the fields its type needs.","operationId":"process-an-ai-dynamic-data-block","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessRequest"}}}},"responses":{"200":{"description":"The step ran. The message says whether the generation was handed to the pipeline (processing) or the block was skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataBlockProcessingResponse"}}}},"422":{"description":"blockid or contactseriesid names no record, the block is not an aidynamicdata block, a field has the wrong type, or promptdata misses a field its type requires."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic/preview":{"post":{"tags":["AI"],"summary":"Start a dynamic content preview","description":"Finds contacts a message with personalization tags can be previewed on. Reads the tags in prompt, stores a preview record and, when the tags give the preview segment conditions, starts matching contacts in the background; answers the record ID to poll with GET /ai/dynamic/preview/{recordId}. A prompt previewed before answers its existing record while its segment still exists. Answers 422 when prompt carries no tag or more than maxTags, and 500 when the record or segment could not be stored.","operationId":"start-a-dynamic-content-preview","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicPreviewSearchRequest"}}}},"responses":{"201":{"description":"The preview record to poll.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicPreviewStartedResponse"}}}},"422":{"description":"The body failed validation, or prompt carries no personalization tag or more than maxTags (detail: Invalid number of tags found in prompt).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}]}}}},"500":{"description":"The preview record or its segment could not be stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/dynamic/preview/{recordId}":{"get":{"tags":["AI"],"summary":"Retrieve contacts for a dynamic content preview","description":"Answers up to maxContacts contacts for a preview started with POST /ai/dynamic/preview, each with the prompt's personalization tags rendered from that contact. Contacts come from the preview segment when the prompt gave it conditions, from the account at random otherwise. Answers 404 when the record is unknown or no contact matched, 409 while the match is still running (detail: Match all response is not ready), and 500 when the record or contacts could not be read.","operationId":"retrieve-dynamic-content-preview-contacts","parameters":[{"name":"recordId","in":"path","description":"ID of the preview record answered by POST /ai/dynamic/preview.","required":true,"schema":{"type":"string"}},{"name":"maxContacts","in":"query","description":"The most contacts to answer.","schema":{"type":"integer","default":10},"example":10}],"responses":{"200":{"description":"Contacts to preview the prompt on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicPreviewContactsResponse"}}}},"404":{"description":"No preview record has this ID (detail: Dynamic preview record not found), or no contact matched the prompt (detail: No matching contacts found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"The contact match is still running; poll again (detail: Match all response is not ready).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The query failed validation, or the stored prompt could not be rendered for the contacts.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}]}}}},"500":{"description":"The record or its contacts could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"contact","x-internal":true}},"/ai/ecom/customerBehaviorSummary":{"get":{"tags":["Ecommerce"],"summary":"Retrieve an ecommerce customer behavior summary","description":"Customers with completed or recovered orders in a date window, split per connection (store) into new (one order in the window), repeat (more than one order in the window) and inactive (latest order in the window is more than 90 days before the end of the window). Inactivity is measured from endDate, not from today, and only orders inside the window are looked at, so a window of 90 days or less, including the default 30-day window, never has inactive customers. The three groups do not overlap, so they add up to that connection total_customers. Because a customer who shops at two stores is counted once for each, the grand total_customers is not a count of distinct people. Pass behaviorType to add figures for one group.","operationId":"retrieve-ecom-customer-behavior-summary","parameters":[{"name":"startDate","in":"query","description":"First day of the window, as YYYY-MM-DD, counted from 00:00:00. Send it together with endDate or not at all. When both are omitted the window is the last 30 days.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-01"}},{"name":"endDate","in":"query","description":"Last day of the window, as YYYY-MM-DD, counted through 23:59:59. Send it together with startDate or not at all, and never before startDate. When both are omitted the window ends today.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-30"}},{"name":"connectionId","in":"query","description":"Restrict the result to one ecommerce connection (store) by its id, as listed by GET /connections. A positive integer. When omitted the result covers every connection.","required":false,"schema":{"type":"string","example":"3"}},{"name":"behaviorType","in":"query","description":"Add additional_metrics for one group: repeat_customers, new_customers or inactive_customers. When omitted there is no additional_metrics.","required":false,"schema":{"type":"string","enum":["repeat_customers","new_customers","inactive_customers"]}}],"responses":{"200":{"description":"The customer behavior summary for the window.","content":{"application/json":{"schema":{"properties":{"date_range":{"description":"The window the summary covers, after defaults were applied.","properties":{"start_date":{"description":"Window start, as YYYY-MM-DD HH:MM:SS.","type":"string","example":"2026-04-01 14:03:11"},"end_date":{"description":"Window end, as YYYY-MM-DD HH:MM:SS.","type":"string","example":"2026-09-30 14:03:11"}},"type":"object"},"total_customers":{"description":"Sum of total_customers over by_connection. A customer active at several connections is counted once per connection.","type":"integer","example":310},"by_connection":{"description":"One entry per connection with customers in the window.","type":"array","items":{"properties":{"connection_id":{"description":"Id of the connection (store).","type":"string","example":"3"},"store_name":{"description":"Name of the connection, when it has one.","type":["string","null"],"example":"Example Store"},"total_customers":{"description":"Customers at this connection in the window.","type":"integer","example":310},"customer_count":{"description":"Customers in each group.","properties":{"new_customers":{"description":"Customers with one order in the window who are not inactive.","type":"integer","example":180},"repeat_customers":{"description":"Customers with more than one order in the window who are not inactive.","type":"integer","example":90},"inactive_customers":{"description":"Customers whose latest order in the window is more than 90 days before the end of the window.","type":"integer","example":40}},"type":"object"},"percentage":{"description":"Each group as a percentage of total_customers, as a string with two decimals.","properties":{"new_customers":{"description":"Share of new customers.","type":"string","example":"58.06"},"repeat_customers":{"description":"Share of repeat customers.","type":"string","example":"29.03"},"inactive_customers":{"description":"Share of inactive customers.","type":"string","example":"12.90"}},"type":"object"}},"type":"object"}},"additional_metrics":{"description":"Figures for the group named by behaviorType. Present only when behaviorType was sent. The keys are the same for every group.","properties":{"customer_type":{"description":"The behaviorType that was requested.","type":"string","example":"repeat_customers"},"total_revenue_usd_segment_orders_in_period":{"description":"Revenue of the group's orders in the window, in major units (total_price divided by 100, rounded to two decimals). Currencies are not converted, so despite the name it is only US dollars when every order is in USD.","type":"number","example":4250.5},"total_orders_in_period":{"description":"Completed and recovered orders in the window from every customer.","type":"integer","example":420},"orders_from_segment_customers_in_period":{"description":"Of those orders, the ones placed by customers in the group.","type":"integer","example":230},"lifetime_unique_customers":{"description":"Contacts with at least one completed or recovered order ever. Ignores the date window but honours connectionId; a contact who is a customer at several connections is counted once.","type":"integer","example":1500},"lifetime_repeat_customers":{"description":"Of those contacts, the ones with more than one completed or recovered order ever.","type":"integer","example":400}},"type":"object","example":{"customer_type":"repeat_customers","total_revenue_usd_segment_orders_in_period":4250.5,"total_orders_in_period":420,"orders_from_segment_customers_in_period":230,"lifetime_unique_customers":1500,"lifetime_repeat_customers":400}}},"type":"object"},"example":{"date_range":{"start_date":"2026-04-01 14:03:11","end_date":"2026-09-30 14:03:11"},"total_customers":310,"by_connection":[{"connection_id":"3","store_name":"Example Store","total_customers":310,"customer_count":{"new_customers":180,"repeat_customers":90,"inactive_customers":40},"percentage":{"new_customers":"58.06","repeat_customers":"29.03","inactive_customers":"12.90"}}]}}}},"422":{"description":"A query parameter failed validation: a date that is not YYYY-MM-DD, only one of startDate and endDate, an endDate before startDate, or a connectionId that is not a positive integer, or a behaviorType other than repeat_customers, new_customers or inactive_customers.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per validation failure.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the error.","type":"string","example":"Invalid attribute"},"detail":{"description":"The validation message.","type":"string"},"source":{"description":"Where the failure is. The pointer names the query parameter that was rejected.","properties":{"pointer":{"description":"Which query parameter was rejected.","type":"string","example":"/data/attributes/behaviorType"}},"type":"object"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request failed validation","value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid attribute\",\"detail\":\"The value you selected is not a valid choice.\",\"source\":{\"pointer\":\"/data/attributes/behaviorType\"}}]}"}}}}},"500":{"description":"The summary could not be computed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed, in a fixed sentence that names the summary.","type":"string","example":"Unexpected error while getting customer behavior summary"}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers"}},"/ai/ecom/orderStatusSummary":{"get":{"tags":["Ecommerce"],"summary":"Retrieve an ecommerce order status summary","description":"How many ecommerce orders are in each state in a date window, with completion and abandonment rates. Unlike the revenue summary this counts every state, abandoned and pending carts included, so its total_orders is not comparable with the revenue summary order_count. completion_rate and abandonment_rate exclude open carts from the denominator; the two _effective_percent rates include them. Rates are percentages returned as strings with two decimals.","operationId":"retrieve-ecom-order-status-summary","parameters":[{"name":"startDate","in":"query","description":"First day of the window, as YYYY-MM-DD, counted from 00:00:00. Send it together with endDate or not at all. When both are omitted the window is the last 30 days.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-01"}},{"name":"endDate","in":"query","description":"Last day of the window, as YYYY-MM-DD, counted through 23:59:59. Send it together with startDate or not at all, and never before startDate. When both are omitted the window ends today.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-30"}},{"name":"connectionId","in":"query","description":"Restrict the result to one ecommerce connection (store) by its id, as listed by GET /connections. A positive integer. When omitted the result covers every connection.","required":false,"schema":{"type":"string","example":"3"}}],"responses":{"200":{"description":"The order status summary for the window.","content":{"application/json":{"schema":{"properties":{"orders_by_state":{"description":"Order count for every state, zero when none. The keys are pending, completed, abandoned, recovered, waiting, cancelled, refunded, failed, returned and pending_payment; an order in a state outside those is counted under unknown.","type":"object","example":{"pending":3,"completed":40,"abandoned":11,"recovered":2,"waiting":0,"cancelled":1,"refunded":0,"failed":0,"returned":0,"pending_payment":0},"additionalProperties":{"type":"integer"}},"total_orders":{"description":"Orders in every state in the window.","type":"integer","example":57},"completion_rate":{"description":"Completed plus recovered orders as a percentage of total_orders, with two decimals.","type":"string","example":"73.68"},"abandonment_rate":{"description":"Abandoned orders as a percentage of completed, recovered and abandoned orders, with two decimals. Open carts are not in the denominator.","type":"string","example":"20.75"},"completion_rate_effective_percent":{"description":"Completed plus recovered orders as a percentage of completed, recovered, abandoned and open carts, with two decimals.","type":"string","example":"76.36"},"abandonment_rate_effective_percent":{"description":"Abandoned orders plus open carts as a percentage of completed, recovered, abandoned and open carts, with two decimals.","type":"string","example":"25.45"}},"type":"object"},"example":{"orders_by_state":{"pending":3,"completed":40,"abandoned":11,"recovered":2,"waiting":0,"cancelled":1,"refunded":0,"failed":0,"returned":0,"pending_payment":0},"total_orders":57,"completion_rate":"73.68","abandonment_rate":"20.75","completion_rate_effective_percent":"76.36","abandonment_rate_effective_percent":"25.45"}}}},"422":{"description":"A query parameter failed validation: a date that is not YYYY-MM-DD, only one of startDate and endDate, an endDate before startDate, or a connectionId that is not a positive integer.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per validation failure.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the error.","type":"string","example":"Invalid attribute"},"detail":{"description":"The validation message.","type":"string"},"source":{"description":"Where the failure is. The pointer names the query parameter that was rejected.","properties":{"pointer":{"description":"Which query parameter was rejected.","type":"string","example":"/data/attributes/endDate"}},"type":"object"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request failed validation","value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid attribute\",\"detail\":\"endDate is required when startDate is provided\",\"source\":{\"pointer\":\"/data/attributes/endDate\"}}]}"}}}}},"500":{"description":"The summary could not be computed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed, in a fixed sentence that names the summary.","type":"string","example":"Unexpected error while getting order status summary"}},"type":"object"}}}}},"x-canonical-resource":"ecomOrders"}},"/ai/ecom/productRankings":{"get":{"tags":["Ecommerce"],"summary":"Retrieve ranked ecommerce products","description":"Products ranked by revenue, units sold or order frequency over a date window, counting only completed and recovered orders (abandoned and pending carts are excluded), aggregated across orders by the product external id within each connection, so the same product sold through two connections is two entries. Page through the ranking with limit and offset; total_products_found is the size of the whole ranking, not of the page.","operationId":"retrieve-ecom-product-rankings","parameters":[{"name":"startDate","in":"query","description":"First day of the window, as YYYY-MM-DD, counted from 00:00:00. Send it together with endDate or not at all. When both are omitted the window is the last 30 days.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-01"}},{"name":"endDate","in":"query","description":"Last day of the window, as YYYY-MM-DD, counted through 23:59:59. Send it together with startDate or not at all, and never before startDate. When both are omitted the window ends today.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-30"}},{"name":"connectionId","in":"query","description":"Restrict the result to one ecommerce connection (store) by its id, as listed by GET /connections. A positive integer. When omitted the result covers every connection.","required":false,"schema":{"type":"string","example":"3"}},{"name":"rankBy","in":"query","description":"What to rank by: revenue, quantity (units sold) or frequency (number of orders containing the product). Defaults to revenue.","required":false,"schema":{"type":"string","default":"revenue","enum":["revenue","quantity","frequency"]}},{"name":"limit","in":"query","description":"Maximum products to return, from 1 to 100. Defaults to 10.","required":false,"schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"offset","in":"query","description":"Products to skip before the first returned, for paging. Defaults to 0.","required":false,"schema":{"type":"integer","default":0,"minimum":0}}],"responses":{"200":{"description":"One page of the product ranking.","content":{"application/json":{"schema":{"properties":{"total_products_found":{"description":"Entries in the whole ranking for the window, before limit and offset. One per product per connection.","type":"integer","example":128},"products":{"description":"The requested page, best first.","type":"array","items":{"properties":{"name":{"description":"Product name.","type":["string","null"],"example":"Classic T-Shirt"},"description":{"description":"Product description.","type":["string","null"],"example":"Soft cotton tee"},"sku":{"description":"Product SKU.","type":["string","null"],"example":"TS-001"},"total_revenue":{"description":"Sum of the product's line prices over its orders in the window, in minor units of the order currency.","type":"integer","example":480000},"total_revenue_formatted":{"description":"total_revenue formatted for display in the order currency.","type":"string","example":"$4,800.00"},"quantity":{"description":"Units sold in the window.","type":"integer","example":160},"frequency":{"description":"Orders in the window that contain the product.","type":"integer","example":95},"image_url":{"description":"Product image URL.","type":["string","null"],"example":"https://store.example.com/images/ts-001.jpg"},"product_url":{"description":"Product page URL.","type":["string","null"],"example":"https://store.example.com/products/ts-001"},"brand":{"description":"Product brand.","type":["string","null"],"example":"Example"},"tags":{"description":"Product tags; empty when it has none.","type":"array","items":{"type":"string"},"example":["apparel"]},"on_sale_count":{"description":"Order lines in the window on which the product was on sale.","type":"integer","example":12}},"type":"object"}}},"type":"object"},"example":{"total_products_found":128,"products":[{"name":"Classic T-Shirt","description":"Soft cotton tee","sku":"TS-001","total_revenue":480000,"total_revenue_formatted":"$4,800.00","quantity":160,"frequency":95,"image_url":null,"product_url":null,"brand":"Example","tags":["apparel"],"on_sale_count":12}]}}}},"422":{"description":"A query parameter failed validation: a date that is not YYYY-MM-DD, only one of startDate and endDate, an endDate before startDate, or a connectionId that is not a positive integer, a rankBy other than revenue, quantity or frequency, a limit outside 1 to 100, or a negative offset.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per validation failure.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the error.","type":"string","example":"Invalid attribute"},"detail":{"description":"The validation message.","type":"string"},"source":{"description":"Where the failure is. The pointer names the query parameter that was rejected.","properties":{"pointer":{"description":"Which query parameter was rejected.","type":"string","example":"/data/attributes/limit"}},"type":"object"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request failed validation","value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid attribute\",\"detail\":\"This value should be between 1 and 100.\",\"source\":{\"pointer\":\"/data/attributes/limit\"}}]}"}}}}},"500":{"description":"The summary could not be computed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed, in a fixed sentence that names the summary.","type":"string","example":"Unexpected error while getting product rankings"}},"type":"object"}}}}},"x-canonical-resource":"ecomOrderProducts"}},"/ai/ecom/revenueSummary":{"get":{"tags":["Ecommerce"],"summary":"Retrieve an ecommerce revenue summary","description":"Revenue for completed and recovered ecommerce orders in a date window: the order count and the number of distinct customers who placed them, broken down by currency and, when no connectionId is given, by connection (store). Already-formatted money strings are returned beside the raw amounts. Orders in any other state, such as abandoned or pending carts, are not counted; use the order status summary for those. A window of orders is chosen by the date the order was created in the store, not the date it reached ActiveCampaign. Counts and raw amounts are returned as numeric strings, exactly as the database reports them.","operationId":"retrieve-ecom-revenue-summary","parameters":[{"name":"startDate","in":"query","description":"First day of the window, as YYYY-MM-DD, counted from 00:00:00. Send it together with endDate or not at all. When both are omitted the window is the last 30 days.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-01"}},{"name":"endDate","in":"query","description":"Last day of the window, as YYYY-MM-DD, counted through 23:59:59. Send it together with startDate or not at all, and never before startDate. When both are omitted the window ends today.","required":false,"schema":{"type":"string","format":"date","example":"2026-09-30"}},{"name":"connectionId","in":"query","description":"Restrict the result to one ecommerce connection (store) by its id, as listed by GET /connections. A positive integer. When omitted the result covers every connection.","required":false,"schema":{"type":"string","example":"3"}},{"name":"currency","in":"query","description":"Restrict the result to one currency, as a three-letter upper-case ISO 4217 code such as USD. When omitted every currency is included and reported separately.","required":false,"schema":{"type":"string","pattern":"^[A-Z]{3}$","example":"USD"}}],"responses":{"200":{"description":"The revenue summary for the window.","content":{"application/json":{"schema":{"properties":{"order_count":{"description":"Distinct completed and recovered orders in the window, as a numeric string.","type":"string","example":"42"},"customer_count":{"description":"Distinct customers who placed those orders, as a numeric string.","type":"string","example":"37"},"by_currency":{"description":"One entry per currency that has orders in the window.","type":"array","items":{"properties":{"currency":{"description":"The currency these totals are in.","type":"string","example":"usd"},"total_revenue":{"description":"Revenue for the currency in minor units, such as cents.","type":"string","example":"1250000"},"total_revenue_formatted":{"description":"total_revenue formatted for display in the currency.","type":"string","example":"$12,500.00"},"average_order_price":{"description":"Average order value for the currency in minor units.","type":"string","example":"29761.9048"},"average_order_price_formatted":{"description":"average_order_price formatted for display in the currency.","type":"string","example":"$297.62"},"order_count":{"description":"Orders in this currency.","type":"string","example":"42"},"customer_count":{"description":"Distinct customers who ordered in this currency.","type":"string","example":"37"}},"type":"object"}},"by_connection":{"description":"One entry per connection and currency that has orders in the window. Absent when connectionId was sent, because the whole result is then that one connection.","type":"array","items":{"properties":{"connectionid":{"description":"Id of the connection (store).","type":"string","example":"3"},"store_name":{"description":"Name of the connection, when it has one.","type":["string","null"],"example":"Example Store"},"currency":{"description":"The currency these totals are in.","type":"string","example":"usd"},"total_revenue":{"description":"Revenue for the connection and currency in minor units.","type":"string","example":"1250000"},"total_revenue_formatted":{"description":"total_revenue formatted for display in the currency.","type":"string","example":"$12,500.00"},"average_order_price":{"description":"Average order value for the connection and currency in minor units.","type":"string","example":"29761.9048"},"average_order_price_formatted":{"description":"average_order_price formatted for display in the currency.","type":"string","example":"$297.62"},"order_count":{"description":"Orders for the connection and currency.","type":"string","example":"42"},"customer_count":{"description":"Distinct customers who ordered through the connection in the currency.","type":"string","example":"37"}},"type":"object"}}},"type":"object"},"example":{"order_count":"42","customer_count":"37","by_currency":[{"currency":"usd","total_revenue":"1250000","total_revenue_formatted":"$12,500.00","average_order_price":"29761.9048","average_order_price_formatted":"$297.62","order_count":"42","customer_count":"37"}],"by_connection":[{"connectionid":"3","store_name":"Example Store","currency":"usd","total_revenue":"1250000","total_revenue_formatted":"$12,500.00","average_order_price":"29761.9048","average_order_price_formatted":"$297.62","order_count":"42","customer_count":"37"}]}}}},"422":{"description":"A query parameter failed validation: a date that is not YYYY-MM-DD, only one of startDate and endDate, an endDate before startDate, a connectionId that is not a positive integer, or a currency that is not three upper-case letters.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per validation failure.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Short name of the error.","type":"string","example":"Invalid attribute"},"detail":{"description":"The validation message.","type":"string"},"source":{"description":"Where the failure is. The pointer names the query parameter that was rejected.","properties":{"pointer":{"description":"Which query parameter was rejected.","type":"string","example":"/data/attributes/currency"}},"type":"object"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The request failed validation","value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid attribute\",\"detail\":\"This value is not valid.\",\"source\":{\"pointer\":\"/data/attributes/currency\"}}]}"}}}}},"500":{"description":"The summary could not be computed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What failed, in a fixed sentence that names the summary.","type":"string","example":"Unexpected error while getting revenue summary"}},"type":"object"}}}}},"x-canonical-resource":"ecomOrders"}},"/ai/edit":{"post":{"tags":["AI"],"summary":"Rewrite marketing copy from instructions","description":"Has the model rewrite the given texts as the instructions say, resultCount times. Nothing is stored. A model failure still answers 200, with error set and results empty. Answers 400 listing what is wrong when resultCount is not 1 to 8, editInstructions is empty or originalContent is empty, and 403 when the account lacks the AI content generator entitlement.","operationId":"edit-content","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentEditRequest"}}}},"responses":{"200":{"description":"The rewritten texts, or error with an empty results when the model failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCompletionResponse"}}}},"400":{"description":"The body is unusable. detail starts with Fix the following errors: followed by the messages that apply, joined without a separator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"403":{"description":"The account lacks the ai-content-generator entitlement (detail: Unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}}},"x-canonical-resource":"content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/eml/extract":{"post":{"tags":["AI"],"summary":"Extract the HTML from an email file","description":"Reads the HTML part of an uploaded .eml message so it can be imported as a template. Inline images referenced by cid: are uploaded to the account's content manager and the references rewritten to their URLs; an image that cannot be stored keeps its cid: reference. Nothing else is saved. Answers 403 when the API user may not create email templates, 422 when the upload is missing, over 10MB, not a .eml file, has no HTML part or an empty one, and 500 when the file could not be parsed.","operationId":"extract-html-from-an-eml-file","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"required":["file"],"properties":{"file":{"description":"The email as a .eml file, 10MB at most.","type":"string","format":"binary"}},"type":"object"}}}},"responses":{"200":{"description":"The HTML part of the email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmlExtractedHtmlResponse"}}}},"403":{"description":"The API user may not create email templates (detail: You do not have permission to create email templates).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The upload was refused. error is one of: Email file is required; File size exceeds maximum allowed (10MB); Invalid file extension. Only .eml files are allowed; HTML part not found in email file; HTML content is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmlExtractionErrorResponse"}}}},"500":{"description":"The file could not be parsed (error: Failed to process email file).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmlExtractionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/enrich/map":{"post":{"tags":["AI"],"summary":"List the URLs of a web site","description":"Discovers the URLs of a public web site through the web-scraping provider, optionally filtered by a search text. A proxy for the AI agents service, not a product API: Hosted forwards the request and counts the credits it uses against the enrich proxy. It persists no data of its own, but the request and response bodies are written to the application log, truncated. Only public HTTPS sites are mapped. Failures answer with a single error envelope whose category says whether to retry.","operationId":"map-web-site","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichMapRequest"}}}},"responses":{"200":{"description":"The site was mapped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichMapResponse"}}}},"400":{"description":"The provider refused the request as malformed (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"401":{"description":"The provider refused our credentials (category client_error). Not something the caller can fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"403":{"description":"The provider refused the request as forbidden (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"404":{"description":"The provider could not find the site (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"422":{"description":"Either a body field failed validation (the errors list one entry per failed check), or the target was refused before anything was sent: it is not a public HTTPS address, or its domain is blocked by policy (category invalid_url).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/EnrichErrorResponse"}]}}}},"429":{"description":"The provider is rate limiting us (category rate_limited, retryable). Wait retry_after seconds, also sent as the Retry-After header, then retry.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Present when the provider sent one.","schema":{"type":"integer","example":30}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"500":{"description":"Something unexpected failed. detail says only which call failed; the cause is logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"502":{"description":"The provider timed out, answered with a server error, could not be reached, reported success false, or answered with something unreadable (category transient, which is retryable, or decode_error, which is not).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"503":{"description":"The provider account is out of credits (category credits_exhausted). Not retryable until credits are added.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}}},"x-canonical-resource":"web_content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/enrich/scrape":{"post":{"tags":["AI"],"summary":"Scrape a web page","description":"Fetches one public web page through the web-scraping provider and returns it in the formats asked for (markdown by default). A proxy for the AI agents service, not a product API: Hosted forwards the request and counts the credits it uses against the enrich proxy. It persists no data of its own, but the request and response bodies are written to the application log, truncated. Only public HTTPS pages are scraped. Failures answer with a single error envelope whose category says whether to retry. A page that loads but is itself an error, such as a 404, is still a 200: read data.metadata.statusCode.","operationId":"scrape-web-page","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichScrapeRequest"}}}},"responses":{"200":{"description":"The page was scraped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichScrapeResponse"}}}},"400":{"description":"The provider refused the request as malformed (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"401":{"description":"The provider refused our credentials (category client_error). Not something the caller can fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"403":{"description":"The provider refused the request as forbidden (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"404":{"description":"The provider could not find the page (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"422":{"description":"Either a body field failed validation (the errors list one entry per failed check), or the target was refused before anything was sent: it is not a public HTTPS address, or its domain is blocked by policy (category invalid_url).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/EnrichErrorResponse"}]}}}},"429":{"description":"The provider is rate limiting us (category rate_limited, retryable). Wait retry_after seconds, also sent as the Retry-After header, then retry.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Present when the provider sent one.","schema":{"type":"integer","example":30}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"500":{"description":"Something unexpected failed. detail says only which call failed; the cause is logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"502":{"description":"The provider timed out, answered with a server error, could not be reached, reported success false, or answered with something unreadable (category transient, which is retryable, or decode_error, which is not).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"503":{"description":"The provider account is out of credits (category credits_exhausted). Not retryable until credits are added.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}}},"x-canonical-resource":"web_content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/enrich/search":{"post":{"tags":["AI"],"summary":"Search the web","description":"Runs a web search through the web-scraping provider and returns the results, optionally scraping each one. A proxy for the AI agents service, not a product API: Hosted forwards the request and counts the credits it uses against the enrich proxy. It persists no data of its own, but the request and response bodies are written to the application log, truncated. Personal data is redacted from scraped results, and domains blocked by policy are excluded unless includeDomains is set. Failures answer with a single error envelope whose category says whether to retry.","operationId":"search-web","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichSearchRequest"}}}},"responses":{"200":{"description":"The search ran.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichSearchResponse"}}}},"400":{"description":"The provider refused the request as malformed (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"401":{"description":"The provider refused our credentials (category client_error). Not something the caller can fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"403":{"description":"The provider refused the request as forbidden (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"404":{"description":"The provider could not find the search (category client_error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"422":{"description":"Either a body field failed validation (the errors list one entry per failed check), or the target was refused before anything was sent: it is not a public HTTPS address, or its domain is blocked by policy (category invalid_url).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/EnrichErrorResponse"}]}}}},"429":{"description":"The provider is rate limiting us (category rate_limited, retryable). Wait retry_after seconds, also sent as the Retry-After header, then retry.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Present when the provider sent one.","schema":{"type":"integer","example":30}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"500":{"description":"Something unexpected failed. detail says only which call failed; the cause is logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"502":{"description":"The provider timed out, answered with a server error, could not be reached, reported success false, or answered with something unreadable (category transient, which is retryable, or decode_error, which is not).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}},"503":{"description":"The provider account is out of credits (category credits_exhausted). Not retryable until credits are added.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichErrorResponse"}}}}},"x-canonical-resource":"web_content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/fieldMapping/asyncCreate":{"post":{"tags":["AI"],"summary":"Generate a suggested field mapping (background worker)","description":"Background worker target, not a client API: Hosted's own queue calls it on itself after POST /ai/fieldMapping/asyncGenerate stores an in-progress request. It asks the model for the pairings and replaces the stored request with the result, marked success. When generation fails the stored request is marked error and the call answers 500. The pairings are read with GET /ai/fieldMapping/results/{requestId}.","operationId":"create-field-mapping-suggestion","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingAsyncRequest"}}}},"responses":{"200":{"description":"The pairings were generated and stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingSuggestionsResponse"}}}},"422":{"description":"record_id is missing or does not name a stored suggested field mapping request, or source_fields or target_fields is empty or not a list, or integration_name is not a string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The pairings could not be generated or stored; the stored request is marked error. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"There was an error while creating suggested field mapping."}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/fieldMapping/asyncGenerate":{"post":{"tags":["AI"],"summary":"Start generating a suggested field mapping","description":"Starts generating a suggested pairing of source and target fields without making the caller wait for the model. Hosted stores an in-progress request and queues the generation, then answers at once with its id as recordId. Poll GET /ai/fieldMapping/poll/{requestId} until it stops answering 409, then read the suggestions with GET /ai/fieldMapping/results/{requestId}. The same work as POST /ai/fieldMapping/generate, off the request.","operationId":"start-field-mapping-suggestion","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingRequest"}}}},"responses":{"200":{"description":"The request was stored and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingDispatchedResponse"}}}},"422":{"description":"sourceFields or targetFields is empty or not a list, or integrationName is not a string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The request could not be stored or queued. If queuing failed after the request was stored, the stored request is marked error. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"There was an error while dispatching request."}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/fieldMapping/feedback":{"post":{"tags":["AI"],"summary":"Record whether a suggested field mapping was useful","description":"Counts one vote on whether the user found a suggested field mapping useful. It increases an aggregate metric only: nothing is stored about the account, the user or the mapping.","operationId":"send-field-mapping-feedback","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingFeedbackRequest"}}}},"responses":{"200":{"description":"The vote was counted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"Metric was increased successfully"}}}},"422":{"description":"useful is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The metric could not be increased. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"An exception occur while increasing metrics."}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/fieldMapping/generate":{"post":{"tags":["AI"],"summary":"Generate a suggested field mapping","description":"Asks the model to pair source fields with target fields and answers with the pairings, so the call lasts as long as the model takes. Only pairings whose two field ids are among the submitted fields are returned, and the model is asked to leave out pairings it is not confident about. Nothing is stored. To avoid waiting, use POST /ai/fieldMapping/asyncGenerate instead.","operationId":"generate-field-mapping-suggestion","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingRequest"}}}},"responses":{"200":{"description":"The suggested pairings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMatchesResponse"}}}},"422":{"description":"sourceFields or targetFields is empty or not a list, or integrationName is not a string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The mapping could not be generated, for any reason. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"There was an error while generating a suggested mapping."}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/fieldMapping/poll/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve the status of a suggested field mapping request","description":"Tells whether a request started with POST /ai/fieldMapping/asyncGenerate has finished. Poll this call: it answers 409 while the request is being generated and 200 once it succeeded, so keep polling until the 409s stop. A request that failed answers 500 and will not recover, so start a new one. The pairings themselves are not part of this response: read them with GET /ai/fieldMapping/results/{requestId}.","operationId":"retrieve-field-mapping-suggestion-status","parameters":[{"name":"requestId","in":"path","description":"The recordId that asyncGenerate returned.","required":true,"schema":{"type":"string","format":"uuid"},"example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}],"responses":{"200":{"description":"The request succeeded; its pairings can be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingStatusResponse"}}}},"404":{"description":"No request with this id is stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"Suggested mapping with given ID was not found."}}}},"409":{"description":"The request is still being generated. Poll again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"Suggested mapping is still in progress, please try again later."}}}},"500":{"description":"The request failed. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMessageResponse"},"example":{"message":"There was an error while fetching suggested mapping."}}}}},"x-canonical-resource":"import","x-internal":true}},"/ai/fieldMapping/results/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a suggested field mapping","description":"Returns the pairings generated for a request started with POST /ai/fieldMapping/asyncGenerate, in the same form as POST /ai/fieldMapping/generate. This call does not check the request's status: a request that is still running or has failed has no pairings yet and answers 200 with an empty matches list, which looks the same as a finished request with no usable suggestion. Poll GET /ai/fieldMapping/poll/{requestId} until it answers 200 first. An id that is not stored answers 500.","operationId":"retrieve-field-mapping-suggestion","parameters":[{"name":"requestId","in":"path","description":"The recordId that asyncGenerate returned.","required":true,"schema":{"type":"string","format":"uuid"},"example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}],"responses":{"200":{"description":"The suggested pairings, empty when the request has none yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingMatchesResponse"}}}},"500":{"description":"The request is not stored, or its stored mapping could not be read. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldMappingResultsErrorResponse"}}}}},"x-canonical-resource":"import","x-internal":true}},"/ai/files/summary/conversation":{"get":{"tags":["AI"],"summary":"List the summaries of files uploaded in AI conversations","description":"Returns every conversation file summary the calling user has saved, without the summary text. Read one by id to get its summary.","operationId":"list-ai-conversation-file-summaries","responses":{"200":{"description":"The calling user's conversation file summaries, as a plain array.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FileSummaryListItem"}}}}},"403":{"description":"The caller is not a valid user of the account."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-internal":true},"post":{"tags":["AI"],"summary":"Save the summary of a file uploaded in an AI conversation","description":"Records the summary of a file the calling user uploaded in an AI conversation. The file itself is not uploaded by this call; stored_file_path says where it already is.","operationId":"create-ai-conversation-file-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreConversationRequest"}}}},"responses":{"201":{"description":"The summary that was saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of the account."},"422":{"description":"A required field is missing, not a string, or longer than allowed."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/files/summary/conversation/{id}":{"get":{"tags":["AI"],"summary":"Retrieve the summary of a file uploaded in an AI conversation","description":"Returns one conversation file summary, including its summary text. Only the user who saved it can read it.","operationId":"retrieve-ai-conversation-file-summary","parameters":[{"name":"id","in":"path","description":"Id of the conversation file summary.","required":true,"schema":{"type":"integer"},"example":101}],"responses":{"200":{"description":"The conversation file summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of the account."},"404":{"description":"The calling user has no conversation file summary with this id."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-internal":true}},"/ai/files/summary/resource":{"get":{"tags":["AI"],"summary":"List the AI resource file summaries","description":"Returns every resource the calling user saved, each with its summary text.","operationId":"list-ai-resource-file-summaries","responses":{"200":{"description":"The calling user's resource file summaries, as a plain array.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FileSummaryResource"}}}}},"403":{"description":"The caller is not a valid user of the account."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-internal":true},"post":{"tags":["AI"],"summary":"Upload a file as an AI resource","description":"Uploads a file, has it summarised, and saves the summary as a resource of the calling user. Accepts PDF, DOCX, JPEG, PNG, GIF and WebP files up to 100 MB.","operationId":"upload-ai-resource-file","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"required":["file"],"properties":{"file":{"description":"The file to upload.","type":"string","format":"binary"}},"type":"object"}}}},"responses":{"201":{"description":"The resource summary that was saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of the account."},"413":{"description":"The file is larger than 100 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUploadErrorResponse"}}}},"422":{"description":"The file is missing or is not a PDF, DOCX or image file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUploadErrorResponse"}}}},"500":{"description":"The file could not be summarised or its summary could not be saved."}},"x-canonical-resource":"agent_file_summary","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/files/summary/resource/from-conversation":{"post":{"tags":["AI"],"summary":"Save a file uploaded in an AI conversation as a resource","description":"Turns a file the calling user uploaded in an AI conversation into a resource. If the upload was already saved as a resource, that resource is returned with 200 and nothing is created; otherwise the upload is summarised and saved, and the response is 201.","operationId":"create-ai-resource-file-from-conversation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreResourceFromConversationRequest"}}}},"responses":{"200":{"description":"The upload had already been saved as a resource; this is that resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"201":{"description":"The resource summary that was saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of a valid account."},"404":{"description":"The upload was not found in the conversation."},"413":{"description":"The upload is larger than 100 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUploadErrorResponse"}}}},"422":{"description":"conversation_id or file_id is missing or invalid, original_file_name is missing when the upload has no existing summary, or the upload is not a PDF, DOCX or image file. The last two have a { \"error\": ... } body; the others use the standard error body."},"500":{"description":"The file could not be summarised or its summary could not be saved."}},"x-canonical-resource":"agent_file_summary","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/files/summary/resource/{id}":{"get":{"tags":["AI"],"summary":"Retrieve an AI resource file summary","description":"Returns one resource the calling user saved, including its summary text.","operationId":"retrieve-ai-resource-file-summary","parameters":[{"name":"id","in":"path","description":"Id of the resource file summary.","required":true,"schema":{"type":"integer"},"example":101}],"responses":{"200":{"description":"The resource file summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of the account."},"404":{"description":"The calling user has no resource file summary with this id."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-internal":true},"put":{"tags":["AI"],"summary":"Update an AI resource file summary","description":"Changes the summary text and/or the name of one resource the calling user saved. Fields left out are kept. The file, its path and its MIME type are not changed.","operationId":"update-ai-resource-file-summary","parameters":[{"name":"id","in":"path","description":"Id of the resource file summary.","required":true,"schema":{"type":"integer"},"example":101}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateResourceRequest"}}}},"responses":{"200":{"description":"The resource file summary after the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSummaryResource"}}}},"403":{"description":"The caller is not a valid user of the account."},"404":{"description":"The calling user has no resource file summary with this id."},"422":{"description":"Neither summary nor original_file_name was given, or one of them is blank or too long."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete an AI resource file summary","description":"Removes one resource the calling user saved.","operationId":"delete-ai-resource-file-summary","parameters":[{"name":"id","in":"path","description":"Id of the resource file summary.","required":true,"schema":{"type":"integer"},"example":101}],"responses":{"204":{"description":"The resource was deleted."},"403":{"description":"The caller is not a valid user of the account."},"404":{"description":"The calling user has no resource file summary with this id."},"500":{"description":"The request could not be completed."}},"x-canonical-resource":"agent_file_summary","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/folders":{"get":{"tags":["AI"],"summary":"List the Content Manager folders the AI features use","description":"The IDs of the four Content Manager folders the AI features store images in: brand logos, generated images, stock photos and website images. On accounts with the new Content Manager the folders are looked up by name; otherwise they come from the configured IDs. Each is null when the folder does not exist yet.","operationId":"list-ai-content-manager-folders","responses":{"200":{"description":"The folder IDs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentManagerFoldersResponse"}}}}},"x-canonical-resource":"content_manager_folder","x-internal":true}},"/ai/fonts":{"get":{"tags":["AI"],"summary":"List the fonts a font picker may offer","description":"Without q, answers the bounded default set: the web-safe families plus the popular webfonts, at most 100. With q, answers up to 100 families from the whole catalogue whose name contains it, case-insensitive. Each font comes with the Bunny Fonts stylesheet addresses that render the webfonts among them.","operationId":"list-fonts","parameters":[{"name":"q","in":"query","description":"Text to search family names for. Omitted or blank, the default set is answered.","required":false,"schema":{"type":"string"},"example":"garamond"}],"responses":{"200":{"description":"The fonts and their stylesheet addresses. fonts is empty when nothing matches q.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FontsResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/fonts/added":{"get":{"tags":["AI"],"summary":"List the fonts added to this account's picker","description":"The families recorded with POST /ai/fonts/added, most recent first, in the same shape as GET /ai/fonts so the two lists merge. A family the catalogue has since dropped is left out. stylesheets covers the offered fonts and the added ones together, so every picker entry points at a shared address.","operationId":"list-added-fonts","responses":{"200":{"description":"The added fonts and the stylesheet addresses covering the offered and added fonts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FontsResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true},"post":{"tags":["AI"],"summary":"Add a font to this account's picker","description":"Records one family so it stays in the editor's font picker across sessions. The family is matched to the catalogue case-insensitively and stored in the catalogue's spelling, so adding it again or with other casing does not make a second entry; it does move it to the front. The body is form-encoded. Answers 422 when the catalogue has no such family.","operationId":"add-a-font","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"required":["family"],"properties":{"family":{"description":"Family name to record; must be in the catalogue, any casing.","type":"string","example":"Zen Dots"}},"type":"object"}}}},"responses":{"200":{"description":"The family as recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FontAddedResponse"}}}},"422":{"description":"The catalogue has no such family.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FontErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/fonts/stylesheet":{"get":{"tags":["AI"],"summary":"Retrieve the @font-face rules for the offered fonts","description":"Answers CSS, not JSON. With family, the @font-face rule for that one family, carrying the Outlook fallback keys the font services omit; cached publicly for a day. Without family, one body covering every family the editor offers plus the ones this account added: the Bunny Fonts @import rules first, then a face rule per webfont; cached privately for a day, so callers change v when the account's added fonts change. Answers 404 with an empty body when family is not in the catalogue.","operationId":"retrieve-a-font-stylesheet","parameters":[{"name":"family","in":"query","description":"The one family to answer the rule for. Omitted or blank, every offered and added family is answered.","required":false,"schema":{"type":"string"},"example":"Inter"},{"name":"v","in":"query","description":"Cache buster. Not read; changing it makes the browser fetch a fresh copy of the batched body.","required":false,"schema":{"type":"string"},"example":"3"}],"responses":{"200":{"description":"The stylesheet. Cache-Control is public, max-age=86400 for one family and private, max-age=86400 for the batched body.","content":{"text/css":{"schema":{"type":"string","example":"@font-face{font-family:\"Inter\";mso-font-alt:\"Arial\";src:url(https://fonts.bunny.net/inter/files/inter-latin-400-normal.woff2) format(\"woff2\")}"}}}},"404":{"description":"family is not in the catalogue. The body is empty.","content":{"text/css":{"schema":{"type":"string","maxLength":0,"example":""}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/forms/customfields":{"get":{"tags":["AI"],"summary":"List the contact custom fields a form can collect","description":"Every contact custom field of the account, in the shape the form generation agent needs to place one on a form: title, the header a cfields entry shows, the field type, the field ID and, for fields that offer values, their options with the preselected one marked. Not filtered by the calling user's list access. No parameters. Called by the form generation agent in ac-agents; not a product API.","operationId":"list-form-custom-fields","responses":{"200":{"description":"The custom fields, in ID order.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FormCustomFieldRecord"}},"example":[{"title":"Company size","header":"Company size","type":"dropdown","id":"12","options":[{"label":"Small","value":"small","isDefault":1},{"label":"Large","value":"large"}]},{"title":"Favourite colour","header":"Favourite colour","type":"text","id":"13"}]}}}},"x-canonical-resource":"custom_field_definition","x-internal":true}},"/ai/forms/draft":{"put":{"tags":["AI"],"summary":"Update a form draft","description":"The same call as POST /ai/forms/draft, routed for both methods: stores data under the id sent, overwriting the stored draft, and extends its life to 2 days from now. Send the id of the draft to update; without one a new draft is created here too. Called by ac-agents and ac-frontend; not a product API.","operationId":"update-a-form-draft","requestBody":{"description":"The draft to store.","required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"id":{"description":"ID of an existing draft to overwrite. Omitted, a new UUID is minted and answered.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"data":{"description":"The draft, free-form but non-empty. By convention a form object in the POST /ai/forms/save shape, optionally with a business_goal_id.","type":"object","example":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}},"type":"object"},"example":{"id":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","data":{"form":{"name":"Newsletter signup","layout":"inline-form","cfields":[{"type":"email","header":"Email","required":true}]}}}}}},"responses":{"200":{"description":"The draft is stored for 2 days.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormDraftSavedResponse"},"example":{"id":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","data":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}}}},"400":{"description":"The body is not JSON, or data is missing or empty.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"Always \"400\", the HTTP status as a string.","type":"string","example":"400"},"detail":{"description":"Always this fixed message.","type":"string","enum":["Empty data payload"],"example":"Empty data payload"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Empty data payload"}]}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"post":{"tags":["AI"],"summary":"Store a form draft","description":"Stores the data object in the form AI draft cache under the id sent, or under a new UUID when none is sent, overwriting whatever that id held, and keeps it for 2 days from this save. The draft is what the form generation agent and the AI form builder pass between themselves before the form is saved with POST /ai/forms/save; nothing is checked beyond data being non-empty. PUT /ai/forms/draft is the same call. Called by ac-agents and ac-frontend; not a product API.","operationId":"create-a-form-draft","requestBody":{"description":"The draft to store.","required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"id":{"description":"ID of an existing draft to overwrite. Omitted, a new UUID is minted and answered.","type":"string","example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"},"data":{"description":"The draft, free-form but non-empty. By convention a form object in the POST /ai/forms/save shape, optionally with a business_goal_id.","type":"object","example":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}},"type":"object"},"example":{"id":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","data":{"form":{"name":"Newsletter signup","layout":"inline-form","cfields":[{"type":"email","header":"Email","required":true}]}}}}}},"responses":{"200":{"description":"The draft is stored for 2 days.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormDraftSavedResponse"},"example":{"id":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","data":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}}}},"400":{"description":"The body is not JSON, or data is missing or empty.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"Always \"400\", the HTTP status as a string.","type":"string","example":"400"},"detail":{"description":"Always this fixed message.","type":"string","enum":["Empty data payload"],"example":"Empty data payload"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Empty data payload"}]}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/forms/draft/{id}":{"get":{"tags":["AI"],"summary":"Retrieve a form draft","description":"The data object stored under this draft ID by POST or PUT /ai/forms/draft, exactly as saved: by convention a form object in the POST /ai/forms/save shape, optionally with a business_goal_id, but nothing is enforced. Drafts live in a cache for 2 days from their last save, then answer 404. Called by ac-agents and ac-frontend; not a product API.","operationId":"retrieve-a-form-draft","parameters":[{"name":"id","in":"path","description":"ID of the draft, as answered by the draft save.","required":true,"schema":{"type":"string"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The stored draft data.","content":{"application/json":{"schema":{"description":"The data object of the last save of this draft, free-form.","type":"object"},"example":{"form":{"name":"Newsletter signup","layout":"inline-form","cfields":[{"type":"email","header":"Email","required":true}]}}}}},"404":{"description":"No draft is stored under this ID, or it expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormErrorResponse"},"example":{"error":"Draft not found"}}}}},"x-canonical-resource":"forms","x-internal":true}},"/ai/forms/fonts":{"get":{"tags":["AI"],"summary":"List the fonts a form can use","description":"The fixed catalog of fonts the form builder offers, keyed by font slug, straight from FontConfiguration::DATA: 50 fonts, each with its subsets, styles, weights, CSS family name, category, provider and fallback list. Static and the same for every account; no parameters and no error path. Called by the form generation agent in ac-agents; not a product API.","operationId":"list-form-fonts","responses":{"200":{"description":"The font catalog.","content":{"application/json":{"schema":{"description":"One entry per font, keyed by slug (alegreya, amatic-sc, arial, ...).","type":"object","additionalProperties":{"$ref":"#/components/schemas/FormFontRecord"}},"example":{"alegreya":{"variants":{"greek":12,"latin":12,"cyrillic":12},"isVariable":true,"styles":["italic","normal"],"weights":[400,500,600,700,800,900],"familyName":"Alegreya","defSubset":"latin","category":"serif","provider":"BunnyFonts","fallbacks":"'Times New Roman', Times, Baskerville, Georgia, serif"}}}}}},"x-canonical-resource":"forms","x-internal":true}},"/ai/forms/getImageUrl":{"post":{"tags":["AI"],"summary":"Find a stock photo for a form","description":"Picks one stock photo for a form from a text prompt: a model turns the prompt into a few search terms, without brand context, then Pexels is searched with those terms, the first alone first and more of them appended until a result comes back, and the first photo that is not on the blocklist is answered. Nothing is stored. POST by method only; the call changes nothing. Called by the form generation agent in ac-agents; not a product API.","operationId":"find-a-form-stock-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormImageSearchRequest"},"example":{"prompt":"A friendly dentist office waiting room","orientation":"landscape"}}}},"responses":{"200":{"description":"A photo was found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormImageSearchResponse"}}}},"422":{"description":"prompt is missing or blank, or orientation is not portrait, landscape or square.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Invalid orientation","source":{"pointer":"/data/attributes/orientation"}}]}}}},"500":{"description":"The model could not produce search terms, the stock image search failed, or no photo matched any of the terms. detail is always Failed to get images.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Failed to get images"}]}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/forms/optin/{formId}":{"post":{"tags":["AI"],"summary":"Create the opt-in confirmation email of a form","description":"Creates the opt-in confirmation email (a campaign) and the opt-in child form of the form named in the path, and stores the email's ID on the form as options.optin_id. Only forms whose options.sendoptin is set qualify. When options.optin_id already names an existing campaign nothing is created and the form is answered as is. POST /ai/forms/save and PUT /ai/forms/save/{formId} do this on their own; this call is for a form saved without it. No body. No known caller.","operationId":"create-a-form-opt-in-email","parameters":[{"name":"formId","in":"path","description":"ID of the form to create the opt-in confirmation email for.","required":true,"schema":{"type":"integer"},"example":42}],"responses":{"200":{"description":"The form, with options.optin_id naming its opt-in confirmation email.","content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form in the shape GET /forms/{id} returns it, not the opt-in child form.","properties":{"id":{"description":"ID of the form.","type":"string","example":"42"},"name":{"description":"Name of the form.","type":"string","example":"Newsletter signup"},"options":{"description":"Form options, with optin_id set.","properties":{"sendoptin":{"description":"True: the form sends an opt-in confirmation email.","type":"boolean","example":true},"optin_id":{"description":"ID of the opt-in confirmation email campaign.","type":"string","example":"318"}},"type":"object"}},"type":"object"}},"type":"object"}}}},"400":{"description":"No form has this ID (detail: Form not found), or the form does not send an opt-in confirmation email (detail: Form has disabled opt-in email option).","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"Always \"400\", the HTTP status as a string.","type":"string","example":"400"},"detail":{"description":"Which check failed.","type":"string","enum":["Form not found","Form has disabled opt-in email option"],"example":"Form not found"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Form not found"}]}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/forms/save":{"post":{"tags":["AI"],"summary":"Create a form from an AI-built structure","description":"Saves a form the form generation agent or the AI form builder put together, with the extra checks the agent needs: the structure is checked for the fields its actions depend on before anything is written, and when the form asks for opt-in confirmation (options.sendoptin) the confirmation email and its opt-in child form are created in the same call, which POST /forms leaves to a separate request. The form itself is created through the same code as POST /forms, so its checks and permission apply. business_goal_id at the root files the form under that goal. Called by ac-agents and ac-frontend; not a product API.","operationId":"create-an-ai-form","requestBody":{"description":"The form structure in a form object, as the public POST /forms body, plus an optional business_goal_id at the root.","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it and POST /forms accepts it. layout, actiondata.actions and cfields are required by the structure check; outside the preference-center layout cfields must hold an email or phone field, an email field when an action is subscribe-to-list and a phone field when one is subscribe-to-sms-list; a preference-center form must have exactly one action, manage-preferences, and one emailidentifier, one listsubscriptions and one subscriptionmessage field; an html field must have non-empty html with no input, select, textarea, button, form, label, fieldset, legend, datalist, output, option or optgroup element. options.sendoptin true makes the save also create the opt-in confirmation email.","properties":{"name":{"description":"Name of the form.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"},"actiondata":{"description":"What happens on submit.","properties":{"actions":{"description":"The actions, each with a type (subscribe-to-list, subscribe-to-sms-list, manage-preferences, ...) and its settings.","type":"array","items":{"type":"object"}}},"type":"object"},"cfields":{"description":"The fields of the form, each with a type (email, phone, fullname, header, html, a custom field id, ...) and its settings.","type":"array","items":{"type":"object"}},"options":{"description":"Form options. sendoptin true asks for an opt-in confirmation email.","type":"object"}},"type":"object"},"business_goal_id":{"description":"ID of a business goal to file the form under. Removed from the structure before the form is saved; when the association cannot be written the error is logged and the save still succeeds.","type":"integer","example":7}},"type":"object"},"examples":{"Request Example":{"summary":"A minimal inline signup form","value":{"form":{"name":"Newsletter signup","layout":"inline-form","actiondata":{"actions":[{"type":"subscribe-to-list","list":"1"}]},"cfields":[{"type":"email","header":"Email","required":true}],"options":{"sendoptin":true}},"business_goal_id":7}}}}}},"responses":{"200":{"description":"The form was created, and its opt-in confirmation email when the structure asked for one.","content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form as saved, in the shape GET /forms/{id} returns it: id, name, layout, actiondata, cfields, options, style, cdate, udate, public_url, embed_code and the rest of the form record. options.optin_id names the opt-in confirmation email once it exists.","properties":{"id":{"description":"ID of the form.","type":"string","example":"42"},"name":{"description":"Name of the form.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown.","type":"string","example":"inline-form"},"parentformid":{"description":"ID of the parent form for an opt-in child form, 0 for a form of its own.","type":"string","example":"0"}},"type":"object"}},"type":"object"}}}},"422":{"description":"The body is not JSON (a single error message), or the structure check failed (a list of problems by path). Nothing was saved. The forms controller's own checks, layout plan, Preference Center limit and option values, answer as POST /forms does.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/FormErrorResponse"},{"$ref":"#/components/schemas/FormStructureValidationErrorResponse"}]},"examples":{"Not JSON":{"summary":"The body could not be decoded","value":{"error":"Form data not found in request body"}},"Structure check":{"summary":"A field the actions need is missing","value":{"error":[{"path":"/form/cfields","error-message":["For subscribe-to-list action email field is required"]}]}}}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/forms/save/{formId}":{"put":{"tags":["AI"],"summary":"Replace a form with an AI-built structure","description":"The update form of POST /ai/forms/save: the same body and checks, but the structure replaces the form named in the path through the same code as PUT /forms/{id}, so its checks and permission apply, and actiondata, cfields, options and style are stored whole. When the saved form asks for opt-in confirmation (options.sendoptin) and is not itself an opt-in child form, its confirmation email and opt-in child form are created if they do not exist yet. business_goal_id at the root files the form under that goal. Called by ac-agents and ac-frontend; not a product API.","operationId":"update-an-ai-form","parameters":[{"name":"formId","in":"path","description":"ID of the form to replace.","required":true,"schema":{"type":"integer"},"example":42}],"requestBody":{"description":"The form structure in a form object, as the public POST /forms body, plus an optional business_goal_id at the root.","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it and POST /forms accepts it. layout, actiondata.actions and cfields are required by the structure check; outside the preference-center layout cfields must hold an email or phone field, an email field when an action is subscribe-to-list and a phone field when one is subscribe-to-sms-list; a preference-center form must have exactly one action, manage-preferences, and one emailidentifier, one listsubscriptions and one subscriptionmessage field; an html field must have non-empty html with no input, select, textarea, button, form, label, fieldset, legend, datalist, output, option or optgroup element. options.sendoptin true makes the save also create the opt-in confirmation email.","properties":{"name":{"description":"Name of the form.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"},"actiondata":{"description":"What happens on submit.","properties":{"actions":{"description":"The actions, each with a type (subscribe-to-list, subscribe-to-sms-list, manage-preferences, ...) and its settings.","type":"array","items":{"type":"object"}}},"type":"object"},"cfields":{"description":"The fields of the form, each with a type (email, phone, fullname, header, html, a custom field id, ...) and its settings.","type":"array","items":{"type":"object"}},"options":{"description":"Form options. sendoptin true asks for an opt-in confirmation email.","type":"object"}},"type":"object"},"business_goal_id":{"description":"ID of a business goal to file the form under. Removed from the structure before the form is saved; when the association cannot be written the error is logged and the save still succeeds.","type":"integer","example":7}},"type":"object"},"examples":{"Request Example":{"summary":"A minimal inline signup form","value":{"form":{"name":"Newsletter signup","layout":"inline-form","actiondata":{"actions":[{"type":"subscribe-to-list","list":"1"}]},"cfields":[{"type":"email","header":"Email","required":true}],"options":{"sendoptin":true}},"business_goal_id":7}}}}}},"responses":{"200":{"description":"The form was replaced, and its opt-in confirmation email created when the structure asked for one and it had none.","content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form as saved, in the shape GET /forms/{id} returns it: id, name, layout, actiondata, cfields, options, style, cdate, udate, public_url, embed_code and the rest of the form record. options.optin_id names the opt-in confirmation email once it exists.","properties":{"id":{"description":"ID of the form.","type":"string","example":"42"},"name":{"description":"Name of the form.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown.","type":"string","example":"inline-form"},"parentformid":{"description":"ID of the parent form for an opt-in child form, 0 for a form of its own.","type":"string","example":"0"}},"type":"object"}},"type":"object"}}}},"422":{"description":"The body is not JSON (a single error message), or the structure check failed (a list of problems by path). Nothing was saved. The forms controller's own checks, layout plan, Preference Center limit and option values, answer as POST /forms does.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/FormErrorResponse"},{"$ref":"#/components/schemas/FormStructureValidationErrorResponse"}]},"examples":{"Not JSON":{"summary":"The body could not be decoded","value":{"error":"Form data not found in request body"}},"Structure check":{"summary":"A field the actions need is missing","value":{"error":[{"path":"/form/cfields","error-message":["For subscribe-to-list action email field is required"]}]}}}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/forms/submissions":{"get":{"tags":["AI"],"summary":"List the submissions of a form","description":"One page of a form's submissions, newest first, for AI reporting on the form. type picks the rows: all lists every submission; unique lists each contact once, dated by their latest submission of the form; contacts lists the contacts whose first ever form submission, on any form, was this form, dated by that submission. dateFrom and dateTo bound the submission date, each optional; dateTo must not be before dateFrom. No known caller yet; not a product API.","operationId":"list-form-submissions","parameters":[{"name":"formId","in":"query","description":"ID of the form whose submissions to list. Required: a form that does not exist is a 404.","required":true,"schema":{"type":"integer"},"example":42},{"name":"type","in":"query","description":"Which rows to list. all: every submission. unique: each contact once, dated by their latest submission of this form. contacts: the contacts whose first ever form submission was this form, dated by it.","schema":{"type":"string","default":"all","enum":["all","unique","contacts"]},"example":"all"},{"name":"dateFrom","in":"query","description":"First submission day to include, Y-m-d. Omitted: no lower bound.","schema":{"type":"string"},"example":"2026-07-01"},{"name":"dateTo","in":"query","description":"Last submission day to include, Y-m-d; not before dateFrom. Omitted: no upper bound.","schema":{"type":"string"},"example":"2026-07-31"},{"name":"limit","in":"query","description":"Rows per page, 1 to 1000.","schema":{"type":"integer","default":500},"example":500},{"name":"offset","in":"query","description":"Rows to skip before the first returned, 0 or more.","schema":{"type":"integer","default":0},"example":0}],"responses":{"200":{"description":"The page and the filters applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionsResponse"},"example":{"filters":{"formId":42,"type":"all","dateFrom":"2026-07-01","dateTo":"2026-07-31"},"total":128,"limit":500,"offset":0,"results":[{"submissionId":9001,"contactId":17,"email":"ada@example.com","submittedAt":"2026-07-14 09:12:46"}]}}}},"404":{"description":"No form has this formId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Form 42 not found"}]}}}},"422":{"description":"formId is missing or not a positive integer, type is not all, unique or contacts, a date is not Y-m-d, dateTo is before dateFrom, limit is outside 1 to 1000, or offset is negative.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"dateTo must be later than or equal to dateFrom","source":{"pointer":"/data/attributes/dateTo"}}]}}}}},"x-canonical-resource":"forms","x-internal":true}},"/ai/forms/submissions/aggregated":{"get":{"tags":["AI"],"summary":"Count the submissions of a form per day, week or month","description":"A gap-filled series of submission counts over dateFrom to dateTo, one bucket per day, week or month as aggregation says, for AI reporting on the form. type picks what is counted: all counts every submission; unique counts each contact once per bucket, by their latest submission in it; contacts counts the contacts whose first ever form submission was this form, in the bucket of that submission. The range is capped by aggregation: under 14 days for day, under 3 months for week, under 12 months for month, so a chart stays readable. No known caller yet; not a product API.","operationId":"aggregate-form-submissions","parameters":[{"name":"formId","in":"query","description":"ID of the form whose submissions to count. A form that does not exist is a 404.","required":true,"schema":{"type":"integer"},"example":42},{"name":"type","in":"query","description":"What to count per bucket. all: every submission. unique: each contact once per bucket, by their latest submission in it. contacts: the contacts whose first ever form submission was this form, in the bucket of that submission.","schema":{"type":"string","default":"all","enum":["all","unique","contacts"]},"example":"all"},{"name":"dateFrom","in":"query","description":"First day to count, Y-m-d.","required":true,"schema":{"type":"string"},"example":"2026-07-01"},{"name":"dateTo","in":"query","description":"Last day to count, Y-m-d; not before dateFrom. The range is capped by aggregation: under 14 days for day, under 3 months for week, under 12 months for month.","required":true,"schema":{"type":"string"},"example":"2026-07-13"},{"name":"aggregation","in":"query","description":"Bucket size. Weeks start on Monday, months on the 1st; the first and last bucket keys can fall outside the range.","required":true,"schema":{"type":"string","enum":["day","week","month"]},"example":"day"}],"responses":{"200":{"description":"The series and the filters applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionsAggregatedResponse"},"example":{"filters":{"formId":42,"type":"all","aggregation":"day","dateFrom":"2026-07-01","dateTo":"2026-07-03"},"total":13,"results":{"2026-07-01":4,"2026-07-02":0,"2026-07-03":9}}}}},"404":{"description":"No form has this formId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Form 42 not found"}]}}}},"422":{"description":"formId is missing or not a positive integer, type is not all, unique or contacts, dateFrom or dateTo is missing or not Y-m-d, dateTo is before dateFrom, aggregation is missing or not day, week or month, or the range exceeds the cap for the aggregation (reported on dateTo).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Date range cannot exceed 14 days for aggregation \"day\"","source":{"pointer":"/data/attributes/dateTo"}}]}}}}},"x-canonical-resource":"forms","x-internal":true}},"/ai/image/compile/{requestUUID}/{imageUUID}":{"get":{"tags":["AI"],"summary":"Retrieve a generated image","description":"Reads one completed image back from the temporary store as base64. The path is validated first: an unknown request or image answers 404, an image still pending, failed or already saved answers 422. Answers 500 when the cached image has expired or cannot be read (detail: Failed to compile image).","operationId":"retrieve-a-generated-image","parameters":[{"name":"requestUUID","in":"path","description":"UUID of the generation request, as answered by POST /ai/image/generate.","required":true,"schema":{"type":"string"}},{"name":"imageUUID","in":"path","description":"UUID of the image, as listed by the poll.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The image, base64 encoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageCompiledResponse"}}}},"404":{"description":"No request or image has these UUIDs (detail: Not found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The image is pending (Image generation image request record is not completed), failed (Image generation image request record failed) or already saved (Image generation image request record is already stored).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The cached image has expired or could not be read (detail: Failed to compile image).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/image/consumption":{"get":{"tags":["AI"],"summary":"Retrieve the image generation allowance used","description":"How much of its monthly image generation allowance the account has used, and the limit. On the advanced AI allowance the unit is credits and consumed may be fractional; on the legacy entitlement it is generation requests.","operationId":"retrieve-image-generation-consumption","responses":{"200":{"description":"The limit and what has been used this month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationConsumptionResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/image/content-manager":{"post":{"tags":["AI"],"summary":"Store a base64 image in a Content Manager folder","description":"Decodes imageBytes, checks the bytes are the declared image type at sane dimensions (at most 12,000 pixels a side, 10 MB decoded) and stores them in the chosen Content Manager folder: AI Generated or Stock Images. The same bytes under the same name answer the file already there rather than a copy. Built for callers that cannot send multipart; not gated on a feature flag. Answers 403 when the API user may not create campaigns, 400 when the bytes are refused, and 500 when Content Manager refused the folder or the upload.","operationId":"upload-an-image-to-content-manager","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageBytesToContentManagerRequest"}}}},"responses":{"201":{"description":"The file as stored, or the identical file already in the folder.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSavedResponse"}}}},"400":{"description":"The bytes were refused. detail is one of: imageBytes must be valid base64-encoded data; Decoded image exceeds the maximum allowed size; Declared mimeType 'image/png' does not match the detected image type (with the declared type); imageBytes is not a valid image or exceeds size limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"403":{"description":"The API user may not create campaigns (detail: You do not have permission to create campaigns).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The file could not be stored. detail is one of: Failed to obtain Content Manager folder; Failed to upload image to Content Manager; Content Manager upload returned no usable URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/create":{"post":{"tags":["AI"],"summary":"Produce one generated image","description":"Background job of POST /ai/image/generate: sends the rewritten prompts to the model, caches the image bytes in the temporary store and marks the image record completed; when every image of the request is done the request record is marked completed too. A failed model call marks the image failed and still answers 200, so the queue does not retry. Only Hosted queues this call.","operationId":"create-an-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageCreateWorkerRequest"}}}},"responses":{"200":{"description":"The model call failed; success is false and the image record is marked failed for the poll to report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageWorkerResponse"}}}},"201":{"description":"The image was produced and cached; success is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageWorkerResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/edit/compile/{requestUUID}/{imageUUID}":{"get":{"tags":["AI"],"summary":"Retrieve an edited image","description":"Reads one complete edited image back from the temporary store as base64, with its sniffed MIME type and the file name, alt text and tags the model wrote. The path is validated first: an unknown request or image answers 404, an image still pending, failed or already saved answers 422. Answers 500 when the cached bytes could not be read or are not valid base64.","operationId":"retrieve-an-edited-image","parameters":[{"name":"requestUUID","in":"path","description":"UUID of the edit request, as answered by POST /ai/image/edit/generate.","required":true,"schema":{"type":"string"}},{"name":"imageUUID","in":"path","description":"UUID of the image, as listed by the poll.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The image and its metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditCompiledResponse"}}}},"404":{"description":"No request or image has these UUIDs (detail: Not found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The image is pending (Image edit request record is not completed), failed (Image edit request record failed) or already saved (Image edit request record is already saved).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The image could not be read back (detail: Unable to compile edited image).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/image/edit/create":{"post":{"tags":["AI"],"summary":"Produce one edited image","description":"Background job of POST /ai/image/edit/generate: fetches the source image, calls the image edit model, runs the safety check, caches the result and marks the records complete. A failure marks the records failed with a failure code and still answers 200, so the queue does not retry. Only Hosted queues this call.","operationId":"create-an-edited-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditWorkerRequest"}}}},"responses":{"200":{"description":"The model call failed; success is false and the image record is marked failed for the poll to report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageWorkerResponse"}}}},"201":{"description":"The image was produced and cached; success is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageWorkerResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/edit/generate":{"post":{"tags":["AI"],"summary":"Edit an image from a prompt","description":"Starts an edit: records an edit request with one image record and queues the background job (POST /ai/image/edit/create). In edit mode the source is a public image address, or the result of an earlier edit named by its UUIDs; a source edit whose cached result has expired answers 400. In create mode the prompt alone drives the image and any source is refused with 422. Answers 403 when the account has used its allowance, and 500 when the request could not be stored or the job could not be queued.","operationId":"edit-an-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditRequest"}}}},"responses":{"201":{"description":"The edit request was stored and its job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditStartedResponse"}}}},"400":{"description":"The earlier edit named as source is no longer cached (detail: Source image not found. The previous edit may have expired.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"403":{"description":"The account has used its allowance (detail: Limit reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation: in edit mode neither imageUrl nor source UUIDs, or both; in create mode any image source (Image source must not be provided when mode is create).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The request could not be stored (detail: Unable to store image edit request) or queued (detail: Unable to dispatch image edit request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/edit/poll/{requestUUID}":{"get":{"tags":["AI"],"summary":"Poll an image edit","description":"Where an edit request and its image are: pending, complete, failed (with failure_code) or saved. Compile the image once it is complete. Answers 404 when the request is unknown or has no image.","operationId":"retrieve-image-edit-status","parameters":[{"name":"requestUUID","in":"path","description":"UUID of the edit request, as answered by POST /ai/image/edit/generate.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The request and image statuses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditStatusResponse"}}}},"404":{"description":"No request has this UUID (detail: Unable to find record associated with request UUID) or it has no image records (detail: No images found for request UUID).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/image/edit/save":{"post":{"tags":["AI"],"summary":"Save an edited image to Content Manager","description":"Moves one complete edited image from the temporary store into Content Manager with its generated metadata and marks the records saved. Answers 403 when the account has used its allowance, 422 when the request or image is unknown or not complete, and 500 when the upload failed.","operationId":"save-an-edited-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditSaveRequest"}}}},"responses":{"201":{"description":"The image as stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSavedResponse"}}}},"403":{"description":"The account has used its allowance (detail: Limit reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation: unknown request or image (Invalid requestUUID), or an image that is pending, failed or already saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The upload failed (detail: Unable to save edited image).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/from-bytes":{"post":{"tags":["AI"],"summary":"Store a base64 image in the AI Generated folder","description":"Decodes imageBytes, checks the bytes are the declared image type at sane dimensions (at most 12,000 pixels a side, 10 MB decoded) and stores them in the AI Generated folder of Content Manager. Built for callers that cannot send multipart. Answers 403 when the API user may not create campaigns, 400 when the bytes are refused, and 500 when Content Manager refused the folder or the upload.","operationId":"upload-an-image-from-bytes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFromBytesRequest"}}}},"responses":{"201":{"description":"The file as stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSavedResponse"}}}},"400":{"description":"The bytes were refused. detail is one of: imageBytes must be valid base64-encoded data; Decoded image exceeds the maximum allowed size; Declared mimeType 'image/png' does not match the detected image type (with the declared type); imageBytes is not a valid image or exceeds size limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"403":{"description":"The API user may not create campaigns (detail: You do not have permission to create campaigns).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The file could not be stored. detail is one of: Failed to obtain Content Manager folder; Failed to upload image to Content Manager; Content Manager upload returned no usable URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/generate":{"post":{"tags":["AI"],"summary":"Generate images from a prompt","description":"Starts a generation: has the model rewrite the prompt for the chosen style and brand kit, records a request with one image record per image, and queues one background job per image (POST /ai/image/create). Answers at once with the request UUID to poll. One generation runs at a time per account: a second call while one is running answers 409. Answers 403 when the account has used its monthly allowance, and 500 when the prompt rewrite or the job queueing failed.","operationId":"generate-images","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerateRequest"}}}},"responses":{"201":{"description":"The request was accepted and its jobs queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationStartedResponse"}}}},"403":{"description":"The account has used its allowance (detail: Generation limit reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"A generation is already running for the account (detail: Image generation is currently locked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The prompt could not be rewritten (detail: Unable to generate sanitized prompts) or the jobs could not be queued (detail: Unable to generate images).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/poll/{requestUUID}":{"get":{"tags":["AI"],"summary":"Poll an image generation","description":"Where a generation request and each of its images are. Statuses are numeric: 1 pending, 2 completed, 3 failed, 4 used. Compile an image once it is 2; the request is 2 once no image is pending. Answers 404 when the request is unknown or has no images, and 500 when the records could not be read.","operationId":"retrieve-image-generation-status","parameters":[{"name":"requestUUID","in":"path","description":"UUID of the generation request, as answered by POST /ai/image/generate.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The request and image statuses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationStatusResponse"}}}},"404":{"description":"No request has this UUID (detail: Unable to find record associated with request UUID) or it has no image records (detail: No images found for request UUID).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"500":{"description":"The records could not be read (detail: Unable to poll status).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/image/save":{"post":{"tags":["AI"],"summary":"Save a generated image to Content Manager","description":"Moves one completed image from the temporary store into the AI Generated folder of Content Manager, with the file name, alt text and tags the model wrote for it, and marks the image record used. Answers 403 when the account has used its allowance, 422 when the request or image is unknown or the image is not completed, and 500 when the upload failed.","operationId":"save-a-generated-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedImageSaveRequest"}}}},"responses":{"201":{"description":"The image as stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSavedResponse"}}}},"403":{"description":"The account has used its allowance (detail: Limit reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation: unknown request or image (Invalid requestUUID), or an image that is pending, failed or already stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The upload failed (detail: Unable to save image).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/image/styles":{"get":{"tags":["AI"],"summary":"List the image generation styles","description":"The style keys POST /ai/image/generate accepts, each with a label in the account's language.","operationId":"list-image-styles","responses":{"200":{"description":"The styles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageStylesResponse"}}}}},"x-canonical-resource":"content_manager_file","x-internal":true}},"/ai/images/metadata/process":{"post":{"tags":["AI"],"summary":"Write alt text and tags for a Content Manager image","description":"Background job queued by the content API when an image is created or updated without alt text or tags: has the model describe the image and writes alt text and tags onto the file. Answers 200 with a skipped marker when the account does not have the feature turned on, and 200 with success true after a run whether or not it wrote anything, so the queue does not redeliver. Only the queue calls this.","operationId":"generate-image-metadata","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageMetadataWorkerRequest"}}}},"responses":{"200":{"description":"The run finished, or was skipped because the feature is off.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ImageMetadataProcessedResponse"},{"$ref":"#/components/schemas/ImageMetadataSkippedResponse"}]}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/images/save":{"post":{"tags":["AI"],"summary":"Import a web image into Content Manager","description":"Fetches the image at url after checking it is https, public and a valid image, has the model write alt text and tags for it, and stores it in the Website Images folder of Content Manager. Answers 500 both when the address fails a check (detail says which: for example URL must use HTTPS, URL is not allowed, Image exceeds maximum allowed size) and when analysis or the upload failed.","operationId":"import-a-website-image","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteImageSaveRequest"}}}},"responses":{"201":{"description":"The file as stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSavedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The address failed a check, or the image could not be analysed or stored; detail carries the reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/images/scrape":{"post":{"tags":["AI"],"summary":"Collect the images on a web page","description":"Scrapes the page at url and answers the addresses of its images that are https, public and fetch as valid images, de-duplicated, with counts of what was found and dropped. Nothing is stored; POST /ai/images/save imports one. Answers 500 when the page could not be scraped.","operationId":"scrape-images-from-a-page","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageScrapeRequest"}}}},"responses":{"200":{"description":"The image addresses and counts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageScrapeResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The page could not be scraped (detail: Failed to scrape images from URL).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/images/search":{"post":{"tags":["AI"],"summary":"Find stock photos for a prompt","description":"Has the model turn the prompt (and the brand kit's voice, when one is given) into search terms, searches the stock photo provider with them and answers up to perPage photos, after dropping blocklisted sources and deny-listed alt text. Nothing is stored. Answers 500 when the model or the provider failed.","operationId":"search-stock-images","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockImageSearchRequest"}}}},"responses":{"200":{"description":"The photos found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockImageSearchResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The search terms could not be generated (detail: Failed to generate search terms) or the provider search failed (detail: Failed to get images).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content_manager_file","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/inbox/conversation-summary/generation/dispatchUpdate":{"post":{"tags":["AI"],"summary":"Generate an Inbox conversation summary (background worker)","description":"Background worker target, not a client API: Hosted's own queue calls it on itself after POST /ai/inbox/conversation-summary/generation/update stores an in-progress record. It generates the summary from the previous summary and messages in the body, replaces the conversation's summary in the Inbox service with it, and marks the record success. When generation fails the record is marked error with a reason and the call answers 500.","operationId":"dispatch-inbox-conversation-summary-update","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxConversationSummaryGenerateDispatchRequest"}}}},"responses":{"201":{"description":"The summary was generated and saved on the conversation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxSummaryDispatchedResponse"}}}},"422":{"description":"conversation_id is missing or blank, external_identifier is not a UUID, previous_summary is not a string, or messages is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Invalid external_identifier","source":{"pointer":"/data/attributes/external_identifier"}}]}}}},"500":{"description":"The summary could not be generated or saved to the Inbox service; the record is then marked error. detail carries the underlying message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_conversation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/inbox/conversation-summary/generation/update":{"post":{"tags":["AI"],"summary":"Start updating an Inbox conversation summary","description":"Starts generating an updated summary of an Inbox conversation from its previous summary and new messages. Hosted stores an in-progress record and queues the generation, then answers at once with the id of that record. When the summary is ready it is saved on the conversation in the Inbox service, not returned here. Poll GET /ai/inbox/conversation-summary/generation/{requestId} until it stops answering 409, then read the conversation's summary from the Inbox service.","operationId":"create-inbox-conversation-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxConversationSummaryGenerateRequest"}}}},"responses":{"201":{"description":"The generation was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxGenerationRequestedResponse"}}}},"422":{"description":"conversation_id is missing or blank, previous_summary is not a string, messages is empty, or a message does not follow the form \"SenderName : message content\".","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Cannot update conversation summary: messages array cannot be empty","source":{"pointer":"/data/attributes/messages"}}]}}}},"500":{"description":"The generation could not be stored or queued. detail carries the underlying message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_conversation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/inbox/conversation-summary/generation/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve the status of an Inbox conversation summary update","description":"Returns the outcome of an update started with POST /ai/inbox/conversation-summary/generation/update. Poll this call: it answers 409 while the summary is still being generated and 200 once it has been saved, so keep polling until the 409s stop, then re-read the conversation's summary from the Inbox service. The summary text is not part of this response. A generation that failed answers 500 and will not recover, so start a new one.","operationId":"retrieve-inbox-conversation-summary-generation","parameters":[{"name":"requestId","in":"path","description":"The requestId that update returned.","required":true,"schema":{"type":"string","format":"uuid"},"example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}],"responses":{"200":{"description":"The summary was generated and saved on the conversation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedInboxConversationSummary"}}}},"404":{"description":"No summary generation with this id exists on the account."},"409":{"description":"The summary is still being generated. Poll again."},"500":{"description":"The generation failed, or the stored record could not be read."}},"x-canonical-resource":"sms_conversation","x-internal":true}},"/ai/inbox/reply/generation/dispatchGenerate":{"post":{"tags":["AI"],"summary":"Generate an AI Inbox reply (background worker)","description":"Background worker target, not a client API: Hosted's own queue calls it on itself after POST /ai/inbox/reply/generation/generate stores an in-progress record. It generates the reply from the conversation context in the body, trying up to 3 times and stopping at the first reply of 139 characters or fewer. If none is that short, the shortest reply returned is kept. The reply is saved on the record as success. When no attempt returns any content the record is saved as error and the call answers 500. The reply is read with GET /ai/inbox/reply/generation/{requestId}.","operationId":"dispatch-inbox-ai-reply-generation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxReplyGenerateDispatchRequest"}}}},"responses":{"201":{"description":"The reply was generated and stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxReplyDispatchedResponse"}}}},"422":{"description":"A required field is missing or blank, external_identifier is not a UUID, tone is not an available tone, or role is not an available role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Invalid external_identifier","source":{"pointer":"/data/attributes/external_identifier"}}]}}}},"500":{"description":"The stored record could not be read or the reply could not be generated; the record is then marked error. detail carries the underlying message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_conversation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/inbox/reply/generation/generate":{"post":{"tags":["AI"],"summary":"Start generating an AI reply for an Inbox conversation","description":"Starts generating a reply to the last message of an Inbox conversation, in the requested tone and following the user's prompt. Hosted reads the conversation's context from the Inbox service (last message, summary, FAQ, website URLs, recent history, brand kit and role), stores an in-progress record and queues the generation, then answers at once with the id of that record. Poll GET /ai/inbox/reply/generation/{requestId} until it stops answering 409. Fails with 500 when the calling user is refused access to the SMS inbox or the generation cannot be stored or queued. When the Inbox service itself cannot be reached the call still succeeds, and the reply is generated from an empty conversation context.","operationId":"create-inbox-ai-reply","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxReplyGenerateRequest"}}}},"responses":{"201":{"description":"The generation was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxGenerationRequestedResponse"}}}},"422":{"description":"A field is missing or blank, or tone is not an available tone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Missing prompt","source":{"pointer":"/data/attributes/prompt"}}]}}}},"500":{"description":"The calling user is refused access to the SMS inbox, or the generation could not be stored or queued. detail carries the underlying message. An unreachable Inbox service is not an error here: see the operation description.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"sms_conversation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/inbox/reply/generation/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a generated AI Inbox reply","description":"Returns the reply generated for a request started with POST /ai/inbox/reply/generation/generate. Poll this call: it answers 409 while the reply is still being generated and 200 with the reply once it is ready, so keep polling until the 409s stop. A generation that failed answers 500 and will not recover, so start a new one.","operationId":"retrieve-inbox-ai-reply","parameters":[{"name":"requestId","in":"path","description":"The requestId that generate returned.","required":true,"schema":{"type":"string","format":"uuid"},"example":"5f0c7a52-3a3b-4c3e-9a55-0d3a1f2b9c11"}],"responses":{"200":{"description":"The generated reply.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedInboxReply"}}}},"404":{"description":"No reply generation with this id exists on the account."},"409":{"description":"The reply is still being generated. Poll again."},"500":{"description":"The generation failed, or the stored record could not be read."}},"x-canonical-resource":"sms_conversation","x-internal":true}},"/ai/industries":{"get":{"tags":["AI"],"summary":"List the industries a brand kit can be assigned to","description":"The industry catalogue with its sub-industries, titles translated to the account's language. Answers 500 when the catalogue could not be read.","operationId":"list-industries","responses":{"200":{"description":"The industries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndustriesResponse"}}}},"500":{"description":"The catalogue could not be read (detail: Unable to gather industry list).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"brand_kit","x-internal":true}},"/ai/industries/fallback-images":{"get":{"tags":["AI"],"summary":"List the fallback images per industry","description":"The stock image addresses used in a template preview when no brand kit images are available, keyed by industry slug. Answers 500 when the map could not be read.","operationId":"list-industry-fallback-images","responses":{"200":{"description":"Industry slug to image addresses.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"example":{"retail":["https://img.example-cdn.net/industries/retail-1.jpg","https://img.example-cdn.net/industries/retail-2.jpg"]}}}},"500":{"description":"The map could not be read (detail: Unable to gather industry fallback image map).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"brand_kit","x-internal":true}},"/ai/initiatives/performance/summary":{"get":{"tags":["AI"],"summary":"Retrieve the current user's goals performance summary","description":"Returns the summary of how the current user's pinned business goals and conversions performed, as last stored by POST /ai/initiatives/performance/summary, which starts generation. This call only reads: it never starts, refreshes or expires a summary, so it returns the stored one however old it is. Answers 404 until a summary has been requested for this user. While status is in_progress, summary is null. Poll with a time limit: a summary whose generation stopped without recording a result stays in_progress until a POST after it expires replaces it. The read can go to a database replica that lags, so right after a POST this call can briefly answer 404 or the previous summary.","operationId":"retrieve-goals-performance-summary","responses":{"200":{"description":"The stored summary and its status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PerformanceSummary"},"example":{"userId":1,"status":"success","summary":"There are no updates at this time. Keep doing amazing work!"}}}},"404":{"description":"No summary is stored for this user yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Summary record not found for ai-initiatives-performance-summary-1"}]}}}},"500":{"description":"Reading the stored summary failed, or its userId or status is missing, empty or zero (errors, with the cause in detail), or it holds a non-empty JSON array or object as status, or any JSON array or object as summary (message).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},{"$ref":"#/components/schemas/ServerErrorResponse"}]},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Invalid InitiativesPerformanceSummary data"}]}}}}},"x-canonical-resource":"business_goal","x-internal":true},"post":{"tags":["AI"],"summary":"Start an initiatives performance summary","description":"Starts generating an AI summary of how the requesting user's initiatives performed over the last interval_days days. If a summary for this user is younger than expiration_hours, it is returned as it is and nothing new is generated. Otherwise the stored summary is replaced by a new in-progress one, generation continues in the background, and this call answers at once with status in_progress and no summary. Poll GET /ai/initiatives/performance/summary until status is success or error. Answers 409 while a summary is still being generated, and 500 when the previous summary ended in error and has not expired.","operationId":"create-initiatives-performance-summary","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSummaryRequest"}}}},"responses":{"200":{"description":"The summary and where it stands.","content":{"application/json":{"schema":{"required":["id","status","summary"],"properties":{"id":{"description":"Identifier of the stored summary.","type":"string","example":"ai-initiatives-performance-summary-12"},"status":{"description":"in_progress when a new summary was started, success when a still-current summary is returned as it is.","type":"string","enum":["in_progress","success"],"example":"in_progress"},"summary":{"description":"The summary text. Null until status is success.","type":["string","null"],"example":null}},"type":"object"}}}},"409":{"description":"A summary for this user is still being generated."},"422":{"description":"interval_days is outside 1 to 30, expiration_hours is outside 1 to 168, or tone is not an available tone."},"500":{"description":"The previous summary ended in error, or the summary could not be started."}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/performance/summary/generate":{"post":{"tags":["AI"],"summary":"Generate the AI initiatives performance summary (background worker)","description":"Background worker target, not a client API: Hosted's own dispatcher calls it after POST /ai/initiatives/performance/summary stores an in-progress record and queues generation. It gathers the performance of the conversions on the user's goals dashboard over intervalDays, asks the AI model for a summary in the given tone, and saves the result on the stored record. It answers 200 with the final status: success, or error when the model call failed (the record is then stored with status error). An already successful record is answered success without generating again. When the user has no conversions on the dashboard, or they have no data in either period, the record is stored as a success with a fixed text and the model is not called. A summaryId with no stored record is answered 422, not 404. Answers 500 when something fails outside the model call; the cause is only logged.","operationId":"generate-initiatives-performance-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiativesPerformanceSummaryGenerateRequest"},"example":{"summaryId":"ai-initiatives-performance-summary-12","tone":"friendly","intervalDays":7}}}},"responses":{"200":{"description":"The generation finished.","content":{"application/json":{"schema":{"required":["status"],"properties":{"status":{"description":"success when the summary was saved, error when the model call failed.","type":"string","enum":["success","error"],"example":"success"}},"type":"object"}}}},"422":{"description":"summaryId or tone is missing or blank, no summary record is stored for summaryId, tone is not an available tone, intervalDays is missing or not 1 to 30, or a field has the wrong JSON type. One error per failed check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"No performance summary record stored for user","source":{"pointer":"/data/attributes/summaryId"}}]}}}},"500":{"description":"Something failed outside the model call, for example while gathering the performance data. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"Unexpected Error Occurred"}]}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/recipe/personalize":{"post":{"tags":["AI"],"summary":"Run the personalization of a stored goal recipe (background worker)","description":"Background worker target, not a client API: Hosted's own dispatcher calls it after a personalized recipe has been stored as queued for the hash. It asks the AI model to rewrite the recipe template's goal name, description and conversion name for the account, using the account's primary brand kit and the goals of its industry, and saves the result on the stored recipe. The answer is 200 with message done and the recipe's final status: done, or error when the model call failed (the recipe is then stored with status error and can be personalized again). A recipe that is already done is answered done without running again. A blank hash or a hash with no stored personalized recipe is a 422, and a recipe whose personalization is already in progress is a 409. A failure outside the model call, such as reading the brand kit, is a 500 with message and status error.","operationId":"run-a-goal-recipe-personalization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizeRecipeRequest"},"example":{"hash":"3KP9Mla"}}}},"responses":{"200":{"description":"The personalization finished, or the recipe was already done. status says which outcome: error means the model call failed.","content":{"application/json":{"schema":{"required":["message","status"],"properties":{"message":{"description":"Always done: it says the call ran, not that it worked. Read status.","type":"string","enum":["done"],"example":"done"},"status":{"description":"done when the recipe is personalized, error when the model call failed.","type":"string","enum":["done","error"],"example":"done"}},"type":"object"},"example":{"message":"done","status":"done"}}}},"409":{"description":"The recipe is already being personalized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"Conflict"}]}}}},"422":{"description":"hash is missing or blank, no personalized recipe is stored for it, or hash has the wrong JSON type. One error per failed check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"No personalized recipe record stored for this business goal","source":{"pointer":"/data/attributes/hash"}}]}}}},"500":{"description":"Something failed outside the model call. The recipe is not marked as failed.","content":{"application/json":{"schema":{"required":["message","status"],"properties":{"message":{"description":"A fixed prefix followed by the cause.","type":"string","example":"Unable to personalize goal recipe - No primary brand kit"},"status":{"description":"Always error.","type":"string","enum":["error"],"example":"error"}},"type":"object"},"example":{"message":"Unable to personalize goal recipe - No primary brand kit","status":"error"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/recipes":{"get":{"tags":["AI"],"summary":"List the account's personalized goal recipes","description":"Returns every goal recipe personalized for the account. Answers 409 while the recipes are not ready: when none are stored yet (start personalization with POST /ai/initiatives/recipes), or when fewer are stored than there are active recipe templates for the account's onboarding industry. In the second case this call also tries to dispatch personalization for the missing templates before answering. It answers 409 even if that dispatch fails or is skipped, so poll with a limit rather than forever. A 200 can still include recipes that are queued, in progress or failed; check each recipe's personalizationStatus.","operationId":"list-all-personalized-goal-recipes","responses":{"200":{"description":"The personalized recipes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizedInitiativeRecipeListResponse"},"example":{"recipes":[{"hash":"3KP9Mla","color":"FEE8B5","name":"Re-Engage Inactive Contacts","description":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value.","conversionName":"Has opened an email - any email","originalName":"Re-Engage Inactive Contacts","originalDescription":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value.","originalConversionName":"Has opened an email - any email","personalizationStatus":"done"}]}}}},"409":{"description":"The recipes are not ready: none are stored yet, or some templates have no recipe yet (personalization for those was attempted, which may have failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":409,"title":"Conflict"}]}}}},"500":{"description":"The recipe templates or the stored recipes could not be read, or no active template applies to the account's onboarding industry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerErrorResponse"}}}}},"x-canonical-resource":"business_goal","x-internal":true},"post":{"tags":["AI"],"summary":"Start personalizing the account's goal recipes","description":"UI kickoff for goal recipe personalization: the goals dashboard calls this once with retry false when it first needs recipes, then polls GET /ai/initiatives/recipes; its Retry button calls it with retry true. Takes the active recipe templates for the account's onboarding industry (the default templates when the account has no industry). Without retry, templates that already have a stored recipe are skipped, and the answer is status done when none is missing. With retry, every stored recipe is deleted first and every template is personalized again. Starting means storing a queued recipe per template and queueing one POST /ai/initiatives/recipe/personalize per recipe; the work itself happens in those requests, so poll GET /ai/initiatives/recipes for the outcome. The lock on this kickoff is per account: while another request holds it the answer is 200 with status redlocked and nothing is started. Only one personalization request per recipe is queued per call; a recipe whose request could not be queued is stored with personalizationStatus error. Answers 500 when the templates or stored recipes cannot be read, the stored recipes cannot be deleted for a retry, or the queued recipes cannot be stored.","operationId":"personalize-all-goal-recipes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitRecipePersonalizationsRequest"},"example":{"retry":false}}}},"responses":{"200":{"description":"Personalization was started (dispatched), was already complete (done), or is being started by another request (redlocked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitRecipePersonalizationsDoneResponse"},"example":{"message":"done","status":"dispatched"}}}},"500":{"description":"Personalization could not be started: the queued recipes could not be stored (dispatch_failed), or the templates or stored recipes could not be read or deleted (error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitRecipePersonalizationsErrorResponse"},"example":{"message":"error","status":"error"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete the account's personalized goal recipes","description":"Deletes every personalized goal recipe stored for the account: the records GET /ai/initiatives/recipes lists, whatever their personalizationStatus, including ones still queued or in progress (a personalization request already queued for a deleted recipe then fails its own validation and stores nothing). Reset and support tooling: no product code calls this route. Hosted runs the same deletion itself when the account's brand kit is deleted and when POST /ai/initiatives/recipes is called with retry true. Nothing else is touched: prepopulation records, prepopulated initiatives and recommendations stay. Afterwards GET /ai/initiatives/recipes answers 409 until personalization is started again, which the goals dashboard does on its next visit. The answer is 200 with message done when every record was deleted, also when there was none. The records are deleted one by one, not in a transaction: when reading them or deleting one fails, the ones already deleted stay deleted and the answer is 500 with the failure's message.","operationId":"delete-all-personalized-goal-recipes","responses":{"200":{"description":"Every stored recipe was deleted, or there was none.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"]}},"type":"object"},"example":{"message":"done"}}}},"500":{"description":"The stored recipes could not be read, or one of them could not be deleted; the ones deleted before the failure stay deleted.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"A fixed prefix followed by the failure's own message.","type":"string","example":"Unable to delete personalized recipes - Something went wrong"}},"type":"object"},"example":{"error":"Unable to delete personalized recipes - Something went wrong"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/initiatives/recipes/prepopulate":{"post":{"tags":["AI"],"summary":"Run business goal prepopulation for the account","description":"Worker target: Hosted queues this call to itself when a new account first needs business goals (InitiativeService::generatePrepopulatedInitiatives), after storing a queued prepopulation record. The run happens inside this request: it selects two goal recipe templates for the account's onboarding industry, personalizes any that has no personalized recipe yet, then queues one POST /initiatives/import per recipe (source prepopulated) and marks the record done. The request body is ignored. The answer is 200 with message done whether or not the run succeeded: a failure inside the run is logged and recorded as status error on the prepopulation record, which GET /ai/initiatives/recipes/prepopulate reports. The run expects the record to be queued; a record in any other state, including done, is treated as a failure and set to error, while a record in error (or none) is replaced by a new queued one. Only a run that cannot start answers 500, which happens when another run holds the prepopulation lock.","operationId":"prepopulate-business-goals","responses":{"200":{"description":"The run was executed. Read the outcome from GET /ai/initiatives/recipes/prepopulate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepopulationDoneResponse"},"example":{"message":"done"}}}},"500":{"description":"The run could not start, because another run holds the prepopulation lock or taking the lock failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepopulationErrorResponse"},"example":{"error":"Unable to prepopulate initiatives - Recipe prepopulation initialization is locked"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true,"x-internal":true},"get":{"tags":["AI"],"summary":"Retrieve the status of business goal prepopulation","description":"Reports where the account's business goal prepopulation stands, from the prepopulation record that InitiativeService::generatePrepopulatedInitiatives stores before queueing POST /ai/initiatives/recipes/prepopulate. The UI polls this every few seconds after a new account's first visit to the goals dashboard until it reads done. The status is the record's own (queued, selecting, personalizing, importing, done), with one adjustment: a done record is reported as importing while fewer prepopulated initiatives exist than recipes were selected, because the imports the run queued (one POST /initiatives/import per recipe) are still landing. Once the record is done the body also lists the selected recipe template hashes. Answers 404 when there is no record, that is prepopulation was never requested for the account or the record was deleted, and 500 when the record is in error (the run failed; POST the run again to replace the record) or the prepopulated initiatives cannot be read. Only that read is guarded: a failure reading the record itself is not caught and answers the API's generic 500 instead.","operationId":"retrieve-business-goal-prepopulation-status","responses":{"200":{"description":"The status of the run, and the selected recipes once the record is done.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepopulationStatusResponse"},"example":{"status":"done","selectedRecipes":["3KP9Mla","5RN6Ztc"]}}}},"404":{"description":"No prepopulation record exists for the account.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Always this fixed message.","type":"string","enum":["Prepopulation record not found"]}},"type":"object"},"example":{"error":"Prepopulation record not found"}}}},"500":{"description":"The record is in error, because the run failed (the cause is only logged), or the prepopulated initiatives could not be read.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"Prepopulation failed when the record is in error; otherwise a fixed prefix followed by the cause of the read failure.","type":"string","example":"Prepopulation failed"}},"type":"object"},"example":{"error":"Prepopulation failed"}}}}},"x-canonical-resource":"business_goal","x-internal":true},"delete":{"tags":["AI"],"summary":"Delete the business goal prepopulation record (support reset)","description":"Support and reset tooling with no product caller, kept as the fallback for when prepopulation fails or gets stuck loading. It deletes the account's stored prepopulation record, the one GET /ai/initiatives/recipes/prepopulate reads, so that status then answers 404 until a new run stores a record. Only the record goes: the goals already imported, the recipes, and the prepopulation lock are left as they are, so a run that still holds the lock keeps blocking a new one. The answer is 200 with message done whether or not a record existed. A failure while deleting is a 500 with the cause in error.","operationId":"delete-business-goal-prepopulation-record","responses":{"200":{"description":"The delete was attempted. This does not confirm that a record existed.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"}},"type":"object"},"example":{"message":"done"}}}},"500":{"description":"The record could not be found or deleted.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"A fixed prefix followed by the cause.","type":"string","example":"Unable to delete prepopulation record - Connection reset by peer"}},"type":"object"},"example":{"error":"Unable to delete prepopulation record - Connection reset by peer"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/recipes/{templateHash}":{"get":{"tags":["AI"],"summary":"Retrieve a personalized goal recipe","description":"Returns the goal recipe personalized for the account from the recipe template with the given hash. Answers 404 when no recipe is stored for that hash. A stored recipe can still be queued or in progress, so check personalizationStatus; only a done recipe has its personalized name, description and conversionName. A recipe whose personalization failed is answered with 500 and an error message instead of the recipe.","operationId":"retrieve-a-personalized-goal-recipe","parameters":[{"name":"templateHash","in":"path","description":"Hash of the recipe template, as returned in the hash field of each recipe from GET /ai/initiatives/recipes.","required":true,"schema":{"type":"string"},"example":"3KP9Mla"}],"responses":{"200":{"description":"The personalized recipe.","content":{"application/json":{"schema":{"required":["recipe"],"properties":{"recipe":{"$ref":"#/components/schemas/PersonalizedInitiativeRecipe"}},"type":"object"},"example":{"recipe":{"hash":"3KP9Mla","color":"FEE8B5","name":"Re-Engage Inactive Contacts","description":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value.","conversionName":"Has opened an email - any email","originalName":"Re-Engage Inactive Contacts","originalDescription":"Win back contacts who haven't engaged in a while. This goal helps you re-spark interest with a friendly nudge, special offer, or reminder of your value.","originalConversionName":"Has opened an email - any email","personalizationStatus":"done"}}}}},"404":{"description":"No personalized recipe is stored for this template hash.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"No Personalized Goal Recipe found by template hash 3KP9Mla"}]}}}},"500":{"description":"Personalization of this recipe failed (the body has an error message), or the recipe could not be read (the body has a fixed message).","content":{"application/json":{"schema":{"oneOf":[{"required":["error"],"properties":{"error":{"description":"Names the template hash whose personalization failed.","type":"string","example":"Unable to personalize goal recipe with template hash 3KP9Mla"}},"type":"object"},{"$ref":"#/components/schemas/ServerErrorResponse"}]}}}}},"x-canonical-resource":"business_goal","x-internal":true}},"/ai/initiatives/recommendations":{"post":{"tags":["AI"],"summary":"Start or check the asset recommendation for a business goal","description":"Recommends an automation recipe or a campaign template for a business goal (initiativeId) or a goal recipe template (templateHash). With no stored recommendation, this call stores a queued one and starts selection in the background, answering 200 with status dispatched. Call it again to poll: 409 while selection is queued or running, then 200 with the recommendation once it is done. A recommendation that failed answers 200 with an error body and is not retried by this call. A failure while starting selection, including another request already starting it, answers 500. Leaving out assetType (or sending it empty) answers 500, not 422, when initiativeId is a business goal that exists or when any templateHash is sent. Send only one of initiativeId and templateHash: when both are sent, selection starts for the goal, but templateHash is still validated and the answer can come from the template's stored recommendation.","operationId":"create-a-goal-recommendation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecommendationRequest"}}}},"responses":{"200":{"description":"Selection was started (status dispatched), the stored recommendation is done (recommendation), or the stored recommendation failed (error).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RecommendationDispatchedResponse"},{"$ref":"#/components/schemas/GoalRecommendationResponse"},{"$ref":"#/components/schemas/InitiativeErrorResponse"}]},"example":{"message":"done","status":"dispatched"}}}},"400":{"description":"Neither initiativeId nor templateHash was sent (or both are empty).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiativeErrorResponse"},"example":{"error":"Either initiative or template must be provided"}}}},"409":{"description":"Selection for this goal or template is already queued or running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"Conflict"}]}}}},"422":{"description":"assetType is null or not automation or campaign (or is missing, when the 500 case for a missing assetType does not apply), initiativeId is not a business goal that exists and is not archived, templateHash is not a goal recipe template, or templateHash or assetType has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"No initiative found with id 123","source":{"pointer":"/data/attributes/initiativeId"}}]}}}},"500":{"description":"Selection could not be started (error, with the cause in the message), assetType was left out or empty while initiativeId is a business goal that exists or a templateHash is sent (errors), or an unexpected failure, for example an initiativeId that is an array or object (message).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/InitiativeErrorResponse"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},{"$ref":"#/components/schemas/ServerErrorResponse"}]},"example":{"error":"Unable to select automation recommendation for business goal with id 123 due to error: Business goal recommendation creation is locked"}}}}},"x-canonical-resource":"business_goal","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete business goal recommendations","description":"Deletes stored next-step recommendations (the automation or campaign suggested for a business goal) so the next request for them generates new ones. UI retry flow: the goals dashboard's Retry button calls this with assetType and externalId (the initiative ID) before re-requesting that asset. Both parameters are optional. assetType limits the deletion to one kind of recommendation; without it both kinds are handled, automation then campaign. externalId limits it to the recommendations made for one business goal; without it, or empty, every recommendation of the kind(s) on the account is deleted. With externalId, an automation deletion also clears the cached automation goal recipes for the goal the deleted recommendation recorded. Caution: when no automation recommendation exists for that externalId, or the stored one recorded no goal, that clearing step runs with no goal and removes every cached automation goal recipe on the account (a PHP warning, not an error, so the answer is still 200). The answer is 200 with message done when the deletions ran, also when nothing matched. Records are deleted one by one, not in a transaction: when a read or delete fails, the ones already deleted stay deleted and the answer is 500 with the failure's message. An assetType other than automation or campaign is a 422.","operationId":"delete-business-goal-recommendations","parameters":[{"name":"assetType","in":"query","description":"Which kind of recommendation to delete: automation or campaign. Omitted: both kinds.","schema":{"type":"string","enum":["automation","campaign"]},"example":"automation"},{"name":"externalId","in":"query","description":"Limit the deletion to the recommendations made for one business goal: the initiative ID, or the goal recipe template hash for a recommendation made from a template. Omitted or empty: every recommendation of the asset type(s) on the account.","schema":{"type":"string"},"example":"42"}],"responses":{"200":{"description":"The deletions ran, or nothing matched.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"]}},"type":"object"},"example":{"message":"done"}}}},"422":{"description":"assetType is not automation or campaign.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title","detail","source"],"properties":{"status":{"type":"integer","enum":[422]},"title":{"type":"string","enum":["Invalid attribute"]},"detail":{"type":"string","enum":["assetType must be one of the supported asset types: automation, campaign"]},"source":{"required":["pointer"],"properties":{"pointer":{"type":"string","enum":["/data/attributes/assetType"]}},"type":"object"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"assetType must be one of the supported asset types: automation, campaign","source":{"pointer":"/data/attributes/assetType"}}]}}}},"500":{"description":"Reading or deleting a record failed; the ones deleted before the failure stay deleted.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"A fixed prefix followed by the failure's own message.","type":"string","example":"Unable to delete recommendations - Something went wrong"}},"type":"object"},"example":{"error":"Unable to delete recommendations - Something went wrong"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/initiatives/recommendations/markused":{"post":{"tags":["AI"],"summary":"Mark a business goal recommendation as used","description":"Records that the account used the recommended asset, by setting used to true on the stored recommendation for a business goal (or for a goal recipe template, stored under its hash) and the assetType given. It is for engagement records. The stored recommendation is updated whatever its selection status, and marking one that is already used changes nothing. The answer is 200 with message done and status done. A stored recommendation that does not exist is answered with 422, and an unsupported assetType with 422. Leaving out assetType (or sending it empty) while sending an initiativeId answers 500, not 422. Meant for the product's own screens.","operationId":"mark-a-goal-recommendation-used","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkRecommendationUsedRequest"}}}},"responses":{"200":{"description":"The recommendation is marked as used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationDispatchedResponse"},"example":{"message":"done","status":"done"}}}},"422":{"description":"initiativeId is missing, or no stored recommendation exists for it and the assetType, or assetType is not automation or campaign, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"The initiative recommendation record does not exist","source":{"pointer":"/data/attributes/initiativeId"}}]}}}},"500":{"description":"assetType was left out or empty while initiativeId was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal Server Error","detail":"Internal server error"}]}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/recommendations/selection":{"post":{"tags":["AI"],"summary":"Run the asset selection for a stored recommendation","description":"Background worker target, not a client API: Hosted's own dispatcher calls it after POST /ai/initiatives/recommendations stores a queued recommendation. It picks the recommended asset for the stored recommendation (externalId and assetType), which can take a while, and saves the result on the stored recommendation. A recommendation that is already done is answered 200 done without running again. No stored recommendation for the externalId is answered 200 with status error, not 404. A stored recommendation that already failed is answered 500, and so is a selection that fails or is already running for the same goal. Leaving out assetType (or sending it empty) while sending an externalId answers 500, not 422.","operationId":"run-a-goal-recommendation-selection","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectRecommendationRequest"}}}},"responses":{"200":{"description":"The selection finished (or the recommendation was already done), or there is no stored recommendation to select for (status error).","content":{"application/json":{"schema":{"oneOf":[{"required":["message","status"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"],"example":"done"},"status":{"description":"Always done.","type":"string","enum":["done"],"example":"done"}},"type":"object"},{"required":["message","status"],"properties":{"message":{"description":"Says the stored recommendation was not found.","type":"string","example":"Recommendation record not found"},"status":{"description":"Always error.","type":"string","enum":["error"],"example":"error"}},"type":"object"}]},"example":{"message":"done","status":"done"}}}},"422":{"description":"externalId is missing, or assetType is not automation or campaign, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"externalId is required","source":{"pointer":"/data/attributes/externalId"}}]}}}},"500":{"description":"The selection failed or is already running for this goal (message and status error), the stored recommendation had already failed, or assetType was left out or empty while externalId was sent (errors).","content":{"application/json":{"schema":{"oneOf":[{"required":["message","status"],"properties":{"message":{"description":"A fixed prefix followed by the cause.","type":"string","example":"Unable to select goal recommendation - Business goal recommendation selection is locked"},"status":{"description":"Always error.","type":"string","enum":["error"],"example":"error"}},"type":"object"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}]},"example":{"message":"Unable to select goal recommendation - Business goal recommendation selection is locked","status":"error"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/initiatives/recommendations/{recommendationId}":{"delete":{"tags":["AI"],"summary":"Delete a business goal recommendation","description":"Deletes one stored next-step recommendation (the automation or campaign suggested for a business goal) by the ID of its stored record. No product code calls this; it exists for support and cleanup. The record is looked up by ID alone in the account's key-value store, so the asset type does not matter (the automation recommendation service handles the call whatever type the recommendation is), and an ID that belongs to another kind of stored record deletes that record instead. The answer is 200 with message done whether or not a record was deleted: a lookup or delete failure, including an ID that matches no record, is logged and swallowed by the service. The 500 is only reached when the recommendation service itself cannot be built.","operationId":"delete-a-business-goal-recommendation","parameters":[{"name":"recommendationId","in":"path","description":"ID of the recommendation's record in the account's key-value store. The API never returns this ID; it is read from the store directly.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The delete was attempted. This does not confirm a record existed or was removed.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always done.","type":"string","enum":["done"]}},"type":"object"},"example":{"message":"done"}}}},"500":{"description":"The recommendation service could not be built. A failure to find or delete the record does not reach this; it is logged and answers 200.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"A fixed prefix followed by the cause.","type":"string","example":"Unable to delete recommendation - Service not found"}},"type":"object"},"example":{"error":"Unable to delete recommendation - Service not found"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/insights/campaigns/cadence":{"get":{"tags":["AI"],"summary":"Retrieve each campaign creator's sending cadence","description":"Service-to-service read: the insights engine's CadenceSuggestionWorkflow calls this with a service JWT for the account to find creators who send campaigns on a steady rhythm. Looks at the last 26 full weeks of sent one-off campaigns (status sent or completed, dated by their send date; automation, recurring and reminder campaigns are left out) and returns one row per creator, ordered by user ID. Several campaigns on one day count as one send day. Days and hours are in the account time zone. Answers 500 when the campaigns cannot be read.","operationId":"retrieve-account-campaign-cadence","responses":{"200":{"description":"One row per creator who sent a campaign in the window; an empty list when nobody did.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignCadence"}},"example":[{"user_id":3,"name":"Ana Pérez","label":"weekly","median_gap_days":7,"campaign_count":24,"last_campaign_at":"2026-10-19T10:02:00-04:00","usual_day":"monday","usual_day_of_month":null,"usual_hour":10,"recent_campaigns":[{"name":"Weekly newsletter #42","subject":"This week at Acme","sent_at":"2026-10-19T10:02:00-04:00"}]}]}}},"500":{"description":"The campaigns could not be read. One error with the fixed detail \"An error occurred while fetching campaign cadence.\"; the cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"An error occurred while fetching campaign cadence."}]}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/ai/insights/filters":{"get":{"tags":["AI"],"summary":"List the account filter categories","description":"Returns the account filter categories that GET /ai/insights/filters/matches can check. The categories are fixed in code, so the list is the same for every account; this call does not check whether the account matches any of them. With filterCategories, only those categories are returned, each once, in the fixed category order rather than the order sent. Without it, or with it empty (and with filterCategoriesArray not sent), every category is returned.","operationId":"list-all-insight-filter-categories","parameters":[{"name":"filterCategories","in":"query","description":"Comma-separated filter category IDs. Spaces around an ID are ignored; IDs are case-sensitive. Any entry that is not a category ID answers 422, one error per bad entry. Empty (or \"0\") counts as not sent.","schema":{"type":"string"},"example":"has_brandkit,has_domain"},{"name":"filterCategoriesArray[]","in":"query","description":"Not meant to be sent: the server fills it from a non-empty filterCategories, replacing any value sent. When filterCategories is not sent or empty, a value sent here is used as is and its IDs are not checked.","schema":{"type":"array","items":{"type":"string"}},"example":["has_brandkit"]}],"responses":{"200":{"description":"The filter categories, as a JSON array.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InsightsFilterCategory"}},"example":[{"id":"has_brandkit","label":"Has Brand Kit","description":"Accounts that have set up a primary brand kit."}]}}},"422":{"description":"filterCategories holds an entry that is not a category ID (one error per bad entry), or a parameter has the wrong type, for example filterCategories sent as a list (Unexpected type).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Invalid filter category: has_brand_kit","source":{"pointer":"/data/attributes/filterCategories"}}]}}}},"500":{"description":"A requested category could not be built: each one is loaded with its services to read its ID, label and description. One error with the fixed detail \"An error occurred while fetching filter categories.\"; the cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/insights/filters/matches":{"get":{"tags":["AI"],"summary":"Check whether the account matches insight filter categories","description":"Service-to-service check used before a scheduled insight run. Evaluates each filter category in filterCategories against the requesting account. matches is true only when the account passes every category; failed_filters lists the categories it does not pass and is omitted when matches is true. A missing or empty filterCategories is 422, and an unknown category ID is rejected as a validation error.","operationId":"check-account-insight-filters","parameters":[{"name":"filterCategories","in":"query","description":"Comma-separated filter category IDs to check, such as has_brandkit or campaign_weekly.","required":true,"schema":{"type":"string"},"example":"has_brandkit,has_domain"},{"name":"filterCategoriesArray[]","in":"query","description":"Not meant to be sent: the server fills it from a non-empty filterCategories, replacing any value sent. When filterCategories is not sent or empty, a value sent here is used as is and its IDs are not checked.","schema":{"type":"array","items":{"type":"string"}},"example":["has_brandkit"]}],"responses":{"200":{"description":"Whether the account passes every requested filter category.","content":{"application/json":{"schema":{"properties":{"matches":{"description":"True when the account passes every requested filter category.","type":"boolean","example":false},"failed_filters":{"description":"IDs of the categories the account does not pass. Omitted when matches is true.","type":"array","items":{"type":"string"},"example":["has_domain"]}},"type":"object"}}}},"422":{"description":"No filter category was provided, or a category ID is not recognised."},"500":{"description":"The filters could not be evaluated."}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/insights/milestones/metrics":{"get":{"tags":["AI"],"summary":"Retrieve the account's milestone metrics","description":"Service-to-service read: the insights engine's MilestoneWorkflow calls this (FetchMilestoneMetricsActivity, with a service JWT for the account) before it evaluates the account against milestone thresholds, then reads the one metric its event type maps to (contacts_added reads contact_count). Returns the account's current value for every metric; today that is only contact_count, the subscriber-limit count, which is served from the account's subscriber-count cache when it holds a value. The engine gives each attempt 25 seconds and retries up to three times. Answers 500 when the count cannot be read.","operationId":"retrieve-account-milestone-metrics","responses":{"200":{"description":"The account's current metric values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneMetrics"},"example":{"contact_count":1250}}}},"500":{"description":"The contact count could not be read. One error with the fixed detail \"An error occurred while fetching milestone metrics.\"; the cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsErrorResponse"},"example":{"errors":[{"status":500,"title":"Internal server error","detail":"An error occurred while fetching milestone metrics."}]}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/insights/seed-data/execute":{"post":{"tags":["AI"],"summary":"Seed one data domain of a staging test account","description":"Rewrites the account's data for one domain so that AI insights can be exercised against it: contacts, campaigns, automations (campaigns flagged as automation sends) or deals. The run is synchronous and works on the live product database. With state active or dormant it brings the domain to inside plus outside records (deleting extra records or creating [Seed]-prefixed ones), dates inside of them within the window and the rest earlier, applies the performance profile, and when the domain is not contacts also tops the account up to 2000 active contacts. With state empty it deletes every record of the domain instead; deleting contacts also deletes campaigns, automations and deals. Only accounts on a fixed staging allowlist may call it; anywhere else, including production, it answers 403. The known caller is ai-insights-engine's seed-data client.","operationId":"execute-insights-seed-data","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataPrepareRequest"},"example":{"domain":"campaigns","state":"active","window":30,"inside":8,"outside":42,"performance":"steady_good"}}}},"responses":{"200":{"description":"The run finished. The report lists what was deleted, seeded and moved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataExecuteResponse"},"example":{"success":true,"params":{"domain":"campaigns","state":"active","window_days":30,"inside":8,"outside":42,"performance":"steady_good"},"report":{"domain":"campaigns","inside":8,"outside":42,"actions":["Seeded 50 campaigns (0 → 50)","Placed 8 campaigns inside 30d window","Remaining campaigns moved outside 30d window","Updated 50 campaigns to steady_good performance"]}}}}},"400":{"description":"The seeding SQL raised a RuntimeException, for example the account has no user to own the seeded records. The data may be partly changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataExecutionFailedResponse"},"example":{"error":"Seed data execution failed"}}}},"403":{"description":"The account is not on the seed-data allowlist, or this is not a staging environment. Only returned once the body has passed validation, so a non-allowlisted caller that sends an invalid body gets 422.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataHttpErrorResponse"},"example":{"errors":[{"status":"403","detail":"Account not in allowlist"}]}}}},"422":{"description":"domain, state or performance is missing or not one of its allowed values, window is outside 3 to 365, inside or outside is outside 0 to 500, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"The \"domain\" parameter is required.","source":{"pointer":"/data/attributes/domain"}}]}}}},"503":{"description":"The run failed with something other than a RuntimeException. The cause is only logged; the data may be partly changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataHttpErrorResponse"},"example":{"errors":[{"status":"503","detail":"Failed to execute seed data operation"}]}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/insights/seed-data/status":{"get":{"tags":["AI"],"summary":"Check a staging test account against the insight filters","description":"Reads, without changing anything, how the account's contacts, campaigns, automations and deals stand against the insight account filters, over a window of days: which filters the account passes, how many records of each domain fall inside and outside the window, and a fixed list of suggested seed setups to use with POST /ai/insights/seed-data/execute. Only accounts on a fixed staging allowlist may call it; anywhere else, including production, it answers 403. The known caller is ai-insights-engine's seed-data client.","operationId":"retrieve-insights-seed-data-status","parameters":[{"name":"window","in":"query","description":"Window in days that counts a record as inside. At least 3.","schema":{"type":"integer","default":30},"example":30},{"name":"domain","in":"query","description":"Which domain to report on, or all for the four domains.","schema":{"type":"string","default":"all","enum":["all","contacts","campaigns","automations","deals"]},"example":"all"}],"responses":{"200":{"description":"The account's state for the requested domains.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataStatusResponse"},"example":{"success":true,"window":30,"domains":["campaigns"],"filters":{"campaigns":{"campaigns_30d":{"pass":true,"detail":"8 non-automated campaigns in 2-30d"},"no_campaigns_30d":{"pass":false,"detail":"8 non-automated campaigns in 2-30d"},"sent_campaign_ever":{"pass":true,"detail":"has sent campaigns"},"never_sent_campaign":{"pass":false,"detail":"has sent campaigns"}}},"distributions":{"campaigns":{"inside":8,"outside":42,"total":50}},"scenarios":[{"label":"Healthy active with history","inside":25,"outside":50,"state":"active","performance":"steady_good"}]}}}},"403":{"description":"The account is not on the seed-data allowlist, or this is not a staging environment. Only returned once the query has passed validation, so a non-allowlisted caller that sends an invalid query gets 422.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataHttpErrorResponse"},"example":{"errors":[{"status":"403","detail":"Account not in allowlist"}]}}}},"422":{"description":"window is below 3 or is not an integer, or domain is not one of all, contacts, campaigns, automations or deals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Window must be at least 3 days.","source":{"pointer":"/data/attributes/window"}}]}}}},"503":{"description":"The status could not be read. The cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeedDataHttpErrorResponse"},"example":{"errors":[{"status":"503","detail":"Failed to retrieve seed data status"}]}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/insights/under-review-status":{"post":{"tags":["AI"],"summary":"Check whether the account is under review","description":"Service-to-service status check for scheduled insight runs. Reports whether the account is under review, using the supplied down4 standing or the requesting account's own when it is omitted, and whether the account is active. The call also records the standing: it stores the date review was first seen and the date the account left review, so a repeated call can change the answer once the window_days window after leaving review has passed. window_days is required.","operationId":"check-account-under-review-status","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnderReviewStatusRequest"}}}},"responses":{"200":{"description":"The under-review status and whether the account is active.","content":{"application/json":{"schema":{"properties":{"is_under_review":{"description":"True while the account is under review, or within window_days of leaving review.","type":"boolean","example":true},"is_active":{"description":"False when the account is under maintenance, expired, archived, prepared, or has had its database dropped.","type":"boolean","example":true}},"type":"object"}}}},"422":{"description":"window_days is missing, not an integer, or negative, or down4 is blank."},"500":{"description":"The status could not be checked."}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/lang":{"get":{"tags":["AI"],"summary":"List the languages available for translation","description":"The languages the translation service supports, the account's own language first; when the translation service cannot be reached the core language list is answered instead. When the account has a preferred-language contact field, an entry with code preferred follows the account language so content can be translated into each contact's preference. Answers 500 when neither list could be read.","operationId":"list-translation-languages","responses":{"200":{"description":"The languages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationLanguagesResponse"}}}},"500":{"description":"The languages could not be read (detail: Failed to get available languages).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/monetization/upgrade-request":{"post":{"tags":["AI"],"summary":"Ask the account admin for more AI credits","description":"Emails the account's primary admin that the calling user wants more AI credits, naming the user. Takes no body. Sent once per account: after the first email, later calls answer 200 without sending again. Backs the Upgrade now button of the AI monetization banner.","operationId":"request-ai-credit-upgrade","responses":{"200":{"description":"The primary admin has been notified, now or by an earlier request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeRequestSentResponse"}}}},"403":{"description":"The account is not offered AI credit upgrades: its AI credit settlement is neither shadow nor live, or it has unlimited AI credits. Resold accounts have nothing to buy."},"422":{"description":"The account has no primary admin user, or the primary admin has no email address."},"500":{"description":"The email could not be sent."}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/onboarding/card/generate":{"post":{"tags":["AI"],"summary":"Generate one personalized onboarding card","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/onboarding/cards/triggerGeneration, once per card template that is personalized with a brand kit; not a user API. Asks the model for the card's title, action prompt and example email from the brand kit and onboarding answers in the body, then overwrites the pending card record named by external_identifier with the result, marked success. When the model call fails the record is overwritten as failed instead, and the call still answers 201. A record that no longer exists, deleted by a regeneration that ran in between, is skipped, also with 201.","operationId":"generate-an-onboarding-card","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCardGenerateDispatchRequest"}}}},"responses":{"201":{"description":"The job ran; the card record is now success or failed, or was skipped because it no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCardGeneratedResponse"}}}},"422":{"description":"A required field is missing, external_identifier or template_slug is blank, a field has the wrong type, or brandkit_uuid does not name a brand kit of the account."},"500":{"description":"The card record could not be read, or could not be marked failed after the model call failed."}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/onboarding/cards":{"get":{"tags":["AI"],"summary":"List the onboarding cards and their generation status","description":"The onboarding cards of one brand kit and where their generation stands; poll it after POST /ai/onboarding/cards/triggerGeneration. brandkitUuid names the kit; omitted, the account's primary brand kit is used, and an account with no brand kit, or a kit that has no cards yet, is served the fallback cards generated without one. Cards whose template no longer exists, whose visibility requirement is not met or that need a permission the user lacks are left out; at most 10 are returned, in template order. Reading also tidies the set: static cards missing for a template added since generation are written, a card pending for more than 5 minutes is marked stuck and one stuck for more than 12 hours is marked failed.","operationId":"list-onboarding-cards","parameters":[{"name":"brandkitUuid","in":"query","description":"UUID of one of the account's brand kits, whose cards to list. Omitted: the account's primary brand kit, or the fallback cards generated without a brand kit when the account has none.","schema":{"type":"string"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The cards and the overall status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCardsStatusResponse"}}}},"422":{"description":"brandkitUuid does not name a brand kit of the account."},"500":{"description":"The cards could not be read."}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/onboarding/cards/triggerGeneration":{"post":{"tags":["AI"],"summary":"Start generating the onboarding cards","description":"Builds the onboarding cards of one brand kit: brandkitUuid names the kit; omitted, the cards are generated without brand context as the account's fallback set. Static cards are written at once. For each template personalized with a brand kit a pending card is written and a generation job is queued (POST /ai/onboarding/card/generate), so the call answers before those cards are ready: poll GET /ai/onboarding/cards. With skipExisting false, the default, every existing card of the set is deleted first and all are regenerated; with true, cards already generated successfully are kept, only cards whose template no longer exists are deleted, and the rest are generated. Templates needing a permission the user lacks are skipped and at most 10 visible cards are generated.","operationId":"trigger-onboarding-card-generation","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCardsTriggerGenerationRequest"}}}},"responses":{"200":{"description":"The static cards are written and a job is queued for each personalized card.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCardsTriggeredResponse"}}}},"409":{"description":"brandkitUuid was given and that brand kit's cards are already in_progress: one of its displayed cards is still pending. Not checked when brandkitUuid is omitted."},"422":{"description":"brandkitUuid does not name a brand kit of the account, or skipExisting is not a boolean."},"500":{"description":"Reading the brand kit, deleting the old cards or writing a card record failed. A job that could not be queued does not fail the call: its card is marked failed."}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/onboarding/checklist":{"get":{"tags":["AI"],"summary":"Retrieve the onboarding checklist","description":"The account's onboarding checklist: the fixed steps (brand kit, goal, contacts import, campaign, automation, apps, SMS registration, SMS opt-in form, SMS registration error), each marked checked when the account meets its requirement. Steps whose visibility requirement is not met are left out: goal, contacts import and apps on trial accounts, the SMS steps on accounts without SMS; so are steps needing a permission the user lacks. Takes no parameters.","operationId":"retrieve-the-onboarding-checklist","responses":{"200":{"description":"The steps the user may see and whether all of them are checked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingChecklistResponse"}}}},"500":{"description":"The checklist could not be built: a requirement check or permission lookup failed."}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/ai/prompt/preview":{"post":{"tags":["AI"],"summary":"Start a prompt action preview","description":"Stores a preview record for a prompt action and its settings, reusing a matching record from an earlier call, and answers its ID for POST /ai/prompt/preview/{requestId}. Answers 500 when the record could not be stored.","operationId":"start-a-prompt-action-preview","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewRequest"}}}},"responses":{"200":{"description":"The preview record to build against.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewStartedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The record could not be stored (error: Error while attempting to create a new preview record), or something else failed (error: An error occurred while initializing the preview).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/prompt/preview/{requestId}":{"post":{"tags":["AI"],"summary":"Build a prompt action preview","description":"Runs the prompt action against a sample contact of the segment in params and answers the text it would write. The record must have been created with POST /ai/prompt/preview; the path is validated first and an unknown record answers 404 as a standard error. Answers 404 as a single-message error when the segment has no contacts, and 500 when the record could not be updated or the model failed.","operationId":"build-a-prompt-action-preview","parameters":[{"name":"requestId","in":"path","description":"ID of the preview record answered by POST /ai/prompt/preview.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewRequest"}}}},"responses":{"200":{"description":"The text the action would write for the sampled contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewResponse"}}}},"404":{"description":"No preview record has this ID (standard error, detail: Not found), or the segment has no contacts (error: No contacts found for the given segment).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},{"$ref":"#/components/schemas/PromptActionPreviewErrorResponse"}]}}}},"422":{"description":"The body or the path failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The record could not be updated (error: Error while encoding the preview record) or the model failed (error: An error occurred while generating the preview).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptActionPreviewErrorResponse"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/report_trends_activity":{"get":{"summary":"Retrieve contact trends for a list","description":"Daily contact and unsubscribe totals for a date window, the same numbers as the Contact Trends report. Pass list_id for one list. Omit it, or send 0, for every list the caller can access. A caller who is not a main-group admin only receives lists they are allowed to see. unsubscribe_total is the count of memberships still unsubscribed whose unsubscribe date falls in the window. The series is built from the current membership row, so a contact who left and later resubscribed is counted from the latest subscribe date only, and a deleted contact is absent.","operationId":"retrieve-list-contact-trends","parameters":[{"name":"list_id","in":"query","description":"List id. Omit it, or send 0, for every list the caller can access. The query key is list_id.","schema":{"type":"integer","default":0,"minimum":0},"example":4},{"name":"from","in":"query","description":"First day of the window, as YYYY-MM-DD, counted from 00:00:00. Required, and must be on or before to.","required":true,"schema":{"type":"string"},"example":"2026-01-01"},{"name":"to","in":"query","description":"Last day of the window, as YYYY-MM-DD, counted through 23:59:59. Required, and must be on or after from.","required":true,"schema":{"type":"string"},"example":"2026-01-31"},{"name":"graph","in":"query","description":"Which series to calculate. active_contacts and total_contacts are daily running contact totals. new_contacts is joins per day (subscribe date on one list, contact created date when list_id is omitted). unsubscribes makes unsubscribe_total the count of unsubscribes in the window. Omit it for the Contact Trends default, a daily running total that does not restrict the start count to memberships that are still active.","schema":{"type":"string","enum":["","active_contacts","total_contacts","new_contacts","unsubscribes"]},"example":"unsubscribes"}],"responses":{"200":{"description":"Contact and unsubscribe totals for the window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTrendsActivityResponseResource"}}}},"422":{"description":"A query parameter was rejected: from or to missing or not YYYY-MM-DD, to before from, list_id negative, or a graph value outside the allowed set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTrendsActivityValidationErrorResponse"}}}}},"x-canonical-resource":"lists"}},"/ai/segment/catalog":{"get":{"tags":["AI"],"summary":"Retrieve the segment catalog","description":"The records an AI segment prompt can refer to, one entry per catalog key: tag, list, contactCustomField, emailCampaign, automatedEmail and customObject, as configured in segment_catalog_rules.json. Each entry carries the account's total count, a slice of records selected by the key's default strategy (all when the account has at most 100 of them, otherwise the 100 most recent), the strategies the key accepts, and for contactCustomField the built-in contact fields. A key whose entitlement the account lacks (campaigns for emailCampaign) is an empty entry with count 0 and fetchStrategy null, not an error. The optional fetchStrategy query parameter replaces the default strategy of every key, for a lighter response: all or recent:N; search and recent_days are refused with 400 and need POST. The client limit of POST does not apply here, so recent:N is clamped to 1000. Answers 500 when a catalog cannot be read.","operationId":"retrieve-the-segment-catalog","parameters":[{"name":"fetchStrategy","in":"query","description":"Strategy to apply to every key instead of each key's default: all (optionally all:desc) or recent:N. search:phrase and recent_days:N are refused with 400. Any other value is read as all.","required":false,"schema":{"type":"string"},"example":"recent:10"}],"responses":{"200":{"description":"The catalog, keyed by catalog key. Every configured key is present.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SegmentCatalogEntry"}},"example":{"tag":{"count":42,"maxLimit":2000,"fetchStrategy":{"type":"all","limit":500,"order":"asc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[{"id":1,"label":"VIP"},{"id":2,"label":"Newsletter"}]}},"list":{"count":2,"maxLimit":2000,"fetchStrategy":{"type":"all","limit":500,"order":"asc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[{"id":1,"label":"Main List","channel":"email"},{"id":2,"label":"SMS List","channel":"sms"}]}},"contactCustomField":{"count":10,"maxLimit":2000,"fetchStrategy":{"type":"all","limit":500,"order":"asc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[{"id":7,"label":"Neighborhood","type":"text","perstag":"NEIGHBORHOOD"}]},"standardFields":[{"id":"name","label":"fields:contacts:standard:full-name","type":"text","perstag":"FULLNAME"},{"id":"first_name","label":"fields:contacts:standard:first-name","type":"text","perstag":"FIRSTNAME"}]},"emailCampaign":{"count":0,"fetchStrategy":null,"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[]}},"automatedEmail":{"count":4862,"fetchStrategy":{"type":"recent","args":100,"limit":100,"order":"desc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[{"id":4862,"label":"Welcome email"}]}},"customObject":{"count":1,"fetchStrategy":{"type":"recent","args":100,"limit":100,"order":"desc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100}],"slice":{"type":"catalog","items":[{"id":"schema-1","label":"Schema 1"}]}}}}}},"400":{"description":"fetchStrategy is a search or recent_days mode, which GET does not allow; or a catalog refused an argument.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"GET does not allow search. Use \"all\" or \"recent:N\" for fetchStrategy query param. For search, use POST with fetchStrategy object { \"type\": \"search\", \"args\": \"phrase\", \"limit\": 500 }."}}}},"500":{"description":"A catalog could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"}}}}},"x-canonical-resource":"segments","x-internal":true},"post":{"tags":["AI"],"summary":"Query the segment catalog by key and strategy","description":"The same catalog as GET /ai/segment/catalog, but only for the keys listed in catalogSpec, each sliced with the strategy the caller asks for: all, recent, recent_days or search, with an optional limit and id order. The strategy must be an object, not a string alias, and its type must be one the key lists in allowedStrategies (a request of the same type with another argument is allowed); otherwise the whole request is refused with 400 and nothing is read. limit is honoured for all and search only, and only for keys with a maxLimit (tag, list and contactCustomField, clamped to 2000); other keys keep their default of 500, and a non-integer limit is ignored. recent and recent_days carry N in args. channels filters the list key by channel. A key whose entitlement the account lacks answers an empty entry, not an error. Duplicate keys answer one entry, the last one winning. Answers 500 when a catalog cannot be read. Reads only; nothing is changed.","operationId":"query-the-segment-catalog","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["catalogSpec"],"properties":{"catalogSpec":{"description":"The keys to read and how to slice each. Must be a non-empty list.","type":"array","items":{"required":["key","fetchStrategy"],"properties":{"key":{"description":"Catalog key: tag, list, contactCustomField, emailCampaign, automatedEmail, customObject or automation. An unknown key is refused with 400.","type":"string","example":"tag"},"fetchStrategy":{"description":"How to slice the key. Must be an object; a string alias such as \"all\" is refused with 400.","required":["type"],"properties":{"type":{"description":"all: the full set up to limit; recent: the N newest; recent_days: those created in the last N days; search: those whose name or label matches args. Must be a type the key allows.","type":"string","enum":["all","recent","recent_days","search"],"example":"all"},"args":{"description":"N for recent (default 100), the number of days for recent_days (default 7), the phrase for search, where a|b matches either phrase. Not read for all.","example":100,"oneOf":[{"type":"integer"},{"type":"string"}]},"limit":{"description":"Row ceiling for all and search, honoured up to the key's maxLimit and only for keys that have one. Ignored for recent and recent_days, and when not a positive integer.","type":"integer","example":2000},"order":{"description":"Id order for all and search; default asc. recent and recent_days are always desc.","type":"string","enum":["asc","desc"],"example":"asc"}},"type":"object"},"channels":{"description":"For the list key: keep only lists of these channels (email, sms).","type":"array","items":{"type":"string"},"example":["email"]}},"type":"object"}}},"type":"object"},"example":{"catalogSpec":[{"key":"tag","fetchStrategy":{"type":"all","limit":2000,"order":"asc"}},{"key":"emailCampaign","fetchStrategy":{"type":"search","args":"spring promo","limit":100}}]}}}},"responses":{"200":{"description":"The requested keys only, each sliced as asked.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SegmentCatalogEntry"}},"example":{"tag":{"count":2500,"maxLimit":2000,"fetchStrategy":{"type":"all","limit":2000,"order":"asc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"catalog","items":[{"id":1,"label":"Tag 1"},{"id":2,"label":"Tag 2"}]}},"emailCampaign":{"count":4862,"fetchStrategy":{"type":"search","args":"spring promo","limit":500,"order":"asc"},"allowedStrategies":[{"type":"all"},{"type":"recent","args":100},{"type":"recent_days","args":7},{"type":"search"}],"slice":{"type":"search","items":[{"id":41,"label":"Spring Promo Blast"},{"id":87,"label":"Spring Promo Reminder"}]}}}}}},"400":{"description":"The body is not JSON with a non-empty catalogSpec list; an entry lacks key or fetchStrategy; fetchStrategy is not an object; a key is unknown; or a strategy type is not allowed for its key. Every failing entry is reported in the one message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Entry 0: 'fetchStrategy' must be a JSON object (e.g. { \"type\": \"search\", \"args\": \"phrase\", \"limit\": 500 }), not a string alias."}}}},"500":{"description":"A catalog could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"}}}}},"x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/segment/catalog/fieldValues":{"get":{"tags":["AI"],"summary":"List the stored values of a contact custom field","description":"The distinct values one contact custom field holds, so a caller can resolve a phrase in a segment prompt to a value that really exists. A dropdown, listbox, checkbox or radio field answers its configured options (source options); any other type answers the distinct values contacts hold (source contactValues), limited to the lists the user may see when the user is outside the main admin group. A field such a user may not see is answered as unknown. At most limit values are returned, clamped to 2000, defaulting to 500. Answers 400 when fieldId is missing, not a positive integer or names no visible contact custom field, and 500 when the values cannot be read.","operationId":"list-segment-catalog-field-values","parameters":[{"name":"fieldId","in":"query","description":"Id of the contact custom field. Must be digits only and greater than 0.","required":true,"schema":{"type":"integer","minimum":1},"example":7},{"name":"limit","in":"query","description":"Most values to return; clamped to 2000. 500 when omitted, 0 or not digits.","required":false,"schema":{"type":"integer","maximum":2000},"example":25},{"name":"search","in":"query","description":"Keep only values matching this phrase; a|b matches either phrase. Blank is ignored.","required":false,"schema":{"type":"string"},"example":"harbor"}],"responses":{"200":{"description":"The field's values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentFieldValuesResponse"},"example":{"fieldId":7,"type":"text","source":"contactValues","count":2,"maxLimit":2000,"limit":500,"values":["Harbor Point","Fells Point"]}}}},"400":{"description":"fieldId is missing or not digits (\"fieldId is required and must be a positive integer.\"), is 0 (\"fieldId must be a positive integer.\"), or names no contact custom field the user may see (\"Unknown contact custom field id: 424242\").","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Unknown contact custom field id: 424242"}}}},"500":{"description":"The field or its values could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"}}}}},"x-canonical-resource":"segments","x-internal":true}},"/ai/segment/generate":{"post":{"tags":["AI"],"summary":"Generate a segment definition from a prompt","description":"Sends the prompt to the Segment On Demand service and answers its segment definition unchanged on success. The body's source field is accepted but not read by this action. Any non-2xx answer of the service is forwarded with its status code: its errors list, each error stripped of its code, when the service answered JSON errors; otherwise the raw body under error. Answers 422 when prompt is blank, and 500 when the call throws or the answer cannot be decoded.","operationId":"generate-a-segment-definition","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateSegmentRequest"},"example":{"prompt":"Contacts tagged VIP who opened a campaign in the last 30 days"}}}},"responses":{"200":{"description":"The segment definition the Segment On Demand service answered, forwarded unchanged.","content":{"application/json":{"schema":{"description":"The service's JSON body as-is; Hosted does not define its keys.","type":"object","additionalProperties":true},"example":{"id":1,"name":"Test Segment"}}}},"400":{"description":"The service refused the prompt; its status and body are forwarded, each error without its code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentServiceErrorsResponse"}}}},"422":{"description":"prompt is missing or blank (request validation, errors body); or the service could not turn the prompt into a segment, forwarded with its errors list.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/SegmentServiceErrorsResponse"}]}}}},"500":{"description":"Calling the service threw, or its answer could not be decoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Failed to decode segment response"}}}},"502":{"description":"The service answered 502 without a JSON errors list; the status and raw body are forwarded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Segment service returned 502: Bad Gateway"}}}},"503":{"description":"The service answered 503 without a JSON errors list; the status and raw body are forwarded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Segment service returned 503: Service Unavailable"}}}}},"x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/segmentsV2/generate":{"post":{"tags":["AI"],"summary":"Generate a segment definition for the segment AI builder","description":"Sends the prompt to the Segment On Demand service's agent segment endpoint and answers its segment JSON unchanged on success. source is recorded with the generation for tracing; when omitted or empty it is recorded as segment-ai-builder-source-unknown. Any non-2xx answer of the service is forwarded with its status code: its errors list, each error stripped of its code, when the service answered JSON errors; otherwise the raw body under error. Answers 422 when prompt is blank, and 500 when the call throws or the answer cannot be decoded.","operationId":"generate-an-agent-segment-definition","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateSegmentRequest"},"example":{"prompt":"Contacts tagged VIP who opened a campaign in the last 30 days","source":"segment-ai-builder"}}}},"responses":{"200":{"description":"The segment definition the Segment On Demand service answered, forwarded unchanged.","content":{"application/json":{"schema":{"description":"The service's JSON body as-is; Hosted does not define its keys.","type":"object","additionalProperties":true},"example":{"id":1,"name":"Test Segment"}}}},"400":{"description":"The service refused the prompt; its status and body are forwarded, each error without its code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentServiceErrorsResponse"}}}},"422":{"description":"prompt is missing or blank (request validation, errors body); or the service could not turn the prompt into a segment, forwarded with its errors list.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/SegmentServiceErrorsResponse"}]}}}},"500":{"description":"Calling the service threw, or its answer could not be decoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Failed to decode segment response"}}}},"502":{"description":"The service answered 502 without a JSON errors list; the status and raw body are forwarded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Segment service returned 502: Bad Gateway"}}}},"503":{"description":"The service answered 503 without a JSON errors list; the status and raw body are forwarded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentErrorResponse"},"example":{"error":"Segment service returned 503: Service Unavailable"}}}}},"x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/settings":{"get":{"tags":["AI"],"summary":"Retrieve the calling user's AI settings","description":"Returns the AI settings of the user making the request. A setting the user has never saved reads as false.","operationId":"retrieve-ai-settings","responses":{"200":{"description":"The calling user's AI settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSettingsResponse"}}}}},"x-canonical-resource":"agent_settings","x-internal":true},"put":{"tags":["AI"],"summary":"Update the calling user's AI settings","description":"Saves the AI settings of the user making the request, replacing the saved value, and returns the settings as saved. A missing or non-boolean value is a 422.","operationId":"update-ai-settings","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiSettingsRequest"}}}},"responses":{"200":{"description":"The calling user's AI settings after the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSettingsResponse"}}}},"422":{"description":"convert_conversation_uploads_to_resources is missing or is not a boolean."}},"x-canonical-resource":"agent_settings","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/summarization":{"get":{"tags":["AI"],"summary":"List the account's content summarizations","description":"Every content summarization record of the account, in brief, newest last. Empty when there are none. Answers 500 when the records could not be read.","operationId":"list-content-summarizations","responses":{"200":{"description":"The summarizations, possibly none.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContentSummarizationSummary"}}}}},"500":{"description":"The records could not be read; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content","x-internal":true},"post":{"tags":["AI"],"summary":"Summarize a website, video or file","description":"Parses the source (reads the page, transcribes the video, extracts the PDF), stores a summarization record and queues the background job that writes the summary (POST /ai/summarization/generate). Answers at once with the record in brief; poll GET /ai/summarization/{summarizationId}. Answers 422 when the body fails validation or the source could not be read, 409 when the parser reports the content as still being processed, and 500 when parsing or queueing failed.","operationId":"create-a-content-summarization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentSummarizationCreateRequest"}}}},"responses":{"200":{"description":"The record, with status in_progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentSummarizationSummary"}}}},"409":{"description":"The parser reports the content as still being processed (detail: Content Summarization is in progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation, or the source could not be read; detail carries the parser message.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}]}}}},"500":{"description":"Parsing or queueing failed (detail: Unexpected Error Occurred, or the parser message).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/summarization/generate":{"post":{"tags":["AI"],"summary":"Write a content summary","description":"Background job of POST /ai/summarization: has the model summarize the parsed content into the summarization schema and stores the result on the record, setting its status to success or error. Answers 404 when the record is unknown and 500 when it could not be read or updated. Only Hosted queues this call.","operationId":"generate-a-content-summary","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentSummarizationGenerateWorkerRequest"}}}},"responses":{"200":{"description":"The job finished; status says whether the summary was written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentSummarizationGenerateResponse"}}}},"404":{"description":"No summarization has this ID; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The record could not be read or updated (detail: Unexpected Error Occurred).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/summarization/{summarizationId}":{"get":{"tags":["AI"],"summary":"Retrieve a content summarization","description":"The finished summarization: its source, name and the summary the model wrote. Answers 409 while the background job is still running, 404 when no record has this ID, and 500 when the job ended in error or the record could not be read.","operationId":"retrieve-a-content-summarization","parameters":[{"name":"summarizationId","in":"path","description":"ID of the summarization, as answered by POST /ai/summarization.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The finished summarization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentSummarizationResponse"}}}},"404":{"description":"No summarization has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"The job is still running (detail: Content Summarization is in progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"500":{"description":"The job ended in error (detail: Content Summarization status is not successful) or the record could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"content","x-internal":true}},"/ai/template/analysis/create":{"post":{"tags":["AI"],"summary":"Start a template analysis","description":"Starts an analysis of an email template exported from another tool: stores the HTML and the name on a request record, queues the analysis job (POST /ai/template/analysis/process) and answers at once. The job asks a model to turn the raw HTML into semantic HTML with a loose Stripo-like structure and rewrites the images to the account's CDN; it saves no template. Poll GET /ai/template/analysis/{requestId} for the result. Requires the permission to create email templates. Called by the template import agent in ac-agents; not a product API.","operationId":"create-a-template-analysis","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportCreateRequest"},"example":{"rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"201":{"description":"The request is stored and its job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportRequestCreatedResponse"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","status":"pending"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"422":{"description":"rawHtml is missing, not a string, shorter than 10 or longer than 1,000,000 characters; or templateName is missing, not a string or longer than 200 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Missing rawHtml","source":{"pointer":"/data/attributes/rawHtml"}}]}}}},"500":{"description":"The request record could not be stored (error: Failed to create request.). A job that could not be queued after the record was stored is the framework's own 500 instead, and leaves the request pending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Failed to create request."}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/template/analysis/process":{"post":{"tags":["AI"],"summary":"Run a queued template analysis","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/template/analysis/create; not a user API. Moves the request record from pending to processing, asks a model (up to 9 minutes) to turn the stored HTML into semantic HTML with a loose Stripo-like structure, normalizes padding and rewrites image URLs to the account's CDN, then stores the result as completed. When the model call fails the record is stored as failed with a generic message and an error code when the cause is a timeout or truncated output. Requires the permission to create email templates.","operationId":"process-a-template-analysis","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateAnalysisProcessRequest"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"200":{"description":"The job ran and the request record is completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportProcessedResponse"},"example":{"status":"completed","requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"409":{"description":"Another worker moved the record out of pending first (error: Processing conflict - another process started).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing conflict - another process started"}}}},"422":{"description":"A body field is missing or blank, requestId is not a UUID or names no stored request of this kind (the validation body); or the record is no longer pending (error: Request already processed, current status: <status>).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/TemplateImportErrorResponse"}]},"examples":{"Invalid body":{"summary":"requestId is not a stored request","value":{"errors":[{"status":422,"title":"Invalid attribute","detail":"requestId is not a valid template import request","source":{"pointer":"/data/attributes/requestId"}}]}},"Already processed":{"summary":"The record left pending already","value":{"error":"Request already processed, current status: completed"}}}}}},"500":{"description":"The job failed and the record is now failed (error: Processing failed.), or the record vanished between validation and processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing failed."}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/template/analysis/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a template analysis","description":"Where an analysis stands and, once completed, the HTML the model produced. Poll it after POST /ai/template/analysis/create: 409 while pending or processing, 200 once completed, 500, 504 or 413 once failed. Requires the permission to create email templates. Called by the template import agent in ac-agents; not a product API.","operationId":"retrieve-a-template-analysis","parameters":[{"name":"requestId","in":"path","description":"ID of the request, as answered by the create call.","required":true,"schema":{"type":"string"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The analysis finished; analyzedHtml is ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateAnalysisCompletedResponse"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"404":{"description":"No request of this kind has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Request not found"}}}},"409":{"description":"The job has not finished: the record is pending or processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportInProgressResponse"},"example":{"status":"processing","message":"Request is still being processed","createdAt":"2026-10-23 14:02:11"}}}},"413":{"description":"The job failed because the model's output was truncated (errorCode content_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportFailedResponse"}}}},"500":{"description":"The job failed for a reason other than a timeout or truncated output (the failed body, errorCode null), or the record carries a status the action does not know (the unknown-status body).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TemplateImportFailedResponse"},{"$ref":"#/components/schemas/TemplateImportUnknownStatusResponse"}]}}}},"504":{"description":"The job failed because a model call timed out (errorCode timeout).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportFailedResponse"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/ai/template/import-deterministic/create":{"post":{"tags":["AI"],"summary":"Start a deterministic template import","description":"Starts a deterministic import of an email template exported from another tool: stores the HTML, the name and the hidden flag on a request record, queues the import job (POST /ai/template/import-deterministic/process) and answers at once. The job parses the HTML into stripes, containers and elements and rebuilds it as Stripo-compatible markup without a model, then saves it as a new template of the account. Poll GET /ai/template/import-deterministic/{requestId} for the template ID. Requires the permission to create email templates. Called by the template import agent in ac-agents, its default import path; not a product API.","operationId":"create-a-deterministic-template-import","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportCreateRequest"},"example":{"rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"201":{"description":"The request is stored and its job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportRequestCreatedResponse"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","status":"pending"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"422":{"description":"rawHtml is missing, not a string, shorter than 10 or longer than 1,000,000 characters; or templateName is missing, not a string or longer than 200 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Missing rawHtml","source":{"pointer":"/data/attributes/rawHtml"}}]}}}},"500":{"description":"The request record could not be stored (error: Failed to create request.). A job that could not be queued after the record was stored is the framework's own 500 instead, and leaves the request pending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Failed to create request."}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/template/import-deterministic/process":{"post":{"tags":["AI"],"summary":"Run a queued deterministic template import","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/template/import-deterministic/create; not a user API. Moves the request record from pending to processing, parses the stored HTML into stripes, containers and elements and regenerates it as Stripo-compatible markup without a model, regenerates empty images for the account's primary brand kit, saves the template (editor version 3, source deterministic_template_import, hidden when the request asked, screenshot requested) and stores the result as completed. When any step fails the record is stored as failed with a generic message and, for a model call that timed out or was truncated while regenerating images, an error code. Requires the permission to create email templates.","operationId":"process-a-deterministic-template-import","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeterministicTemplateImportProcessRequest"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"200":{"description":"The job ran and the request record is completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportProcessedResponse"},"example":{"status":"completed","requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"409":{"description":"Another worker moved the record out of pending first (error: Processing conflict - another process started).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing conflict - another process started"}}}},"422":{"description":"A body field is missing or blank, requestId is not a UUID or names no stored request of this kind (the validation body); or the record is no longer pending (error: Request already processed, current status: <status>).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/TemplateImportErrorResponse"}]},"examples":{"Invalid body":{"summary":"requestId is not a stored request","value":{"errors":[{"status":422,"title":"Invalid attribute","detail":"requestId is not a valid template import request","source":{"pointer":"/data/attributes/requestId"}}]}},"Already processed":{"summary":"The record left pending already","value":{"error":"Request already processed, current status: completed"}}}}}},"500":{"description":"The job failed and the record is now failed (error: Processing failed.), or the record vanished between validation and processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing failed."}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/template/import-deterministic/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a deterministic template import","description":"Where a deterministic import stands and, once completed, the saved template. Poll it after POST /ai/template/import-deterministic/create: 409 while pending or processing, 200 once completed, 500, 504 or 413 once failed. Requires the permission to create email templates. Called by the template import agent in ac-agents; not a product API.","operationId":"retrieve-a-deterministic-template-import","parameters":[{"name":"requestId","in":"path","description":"ID of the request, as answered by the create call.","required":true,"schema":{"type":"string"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The import finished; result names the saved template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeterministicTemplateImportCompletedResponse"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"404":{"description":"No request of this kind has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Request not found"}}}},"409":{"description":"The job has not finished: the record is pending or processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportInProgressResponse"},"example":{"status":"processing","message":"Request is still being processed","createdAt":"2026-10-23 14:02:11"}}}},"413":{"description":"The job failed because the model's output was truncated (errorCode content_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeterministicTemplateImportFailedResponse"}}}},"500":{"description":"The job failed for a reason other than a timeout or truncated output (the failed body, errorCode null), or the record carries a status the action does not know (the unknown-status body).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/DeterministicTemplateImportFailedResponse"},{"$ref":"#/components/schemas/TemplateImportUnknownStatusResponse"}]}}}},"504":{"description":"The job failed because a model call timed out (errorCode timeout).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeterministicTemplateImportFailedResponse"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/ai/template/import/create":{"post":{"tags":["AI"],"summary":"Start a template import","description":"Starts a model-based import of an email template exported from another tool: stores the HTML and the name on a request record, queues the import job (POST /ai/template/import/process) and answers at once. The job has a model rewrite the HTML as Stripo-compatible markup and saves it as a new template of the account. Poll GET /ai/template/import/{requestId} for the template ID. Requires the permission to create email templates. Referenced by the template import agent's prompt in ac-agents, which now prefers the deterministic import; not a product API.","operationId":"create-a-template-import","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportCreateRequest"},"example":{"rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"201":{"description":"The request is stored and its job queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportRequestCreatedResponse"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","status":"pending"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"422":{"description":"rawHtml is missing, not a string, shorter than 10 or longer than 1,000,000 characters; or templateName is missing, not a string or longer than 200 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Missing rawHtml","source":{"pointer":"/data/attributes/rawHtml"}}]}}}},"500":{"description":"The request record could not be stored (error: Failed to create request.). A job that could not be queued after the record was stored is the framework's own 500 instead, and leaves the request pending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Failed to create request."}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/template/import/process":{"post":{"tags":["AI"],"summary":"Run a queued template import","description":"Worker endpoint: Hosted dispatches this to itself through the queue from POST /ai/template/import/create; not a user API. Moves the request record from pending to processing, rewrites the stored HTML's external images to the account's CDN, detects the source tool to pick the prompt, has a model produce Stripo-compatible HTML, saves it as a new template (editor version 3, source ai_template_import, screenshot requested) and stores the result as completed. When the model call or the save fails the record is stored as failed with a generic message and an error code when the cause is a timeout or truncated output. Requires the permission to create email templates.","operationId":"process-a-template-import","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportProcessRequest"},"example":{"requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e","rawHtml":"<html><body><table width=\"600\">...</table></body></html>","templateName":"Spring newsletter"}}}},"responses":{"200":{"description":"The job ran and the request record is completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportProcessedResponse"},"example":{"status":"completed","requestId":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"409":{"description":"Another worker moved the record out of pending first (error: Processing conflict - another process started).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing conflict - another process started"}}}},"422":{"description":"A body field is missing or blank, requestId is not a UUID or names no stored request of this kind (the validation body); or the record is no longer pending (error: Request already processed, current status: <status>).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/TemplateImportErrorResponse"}]},"examples":{"Invalid body":{"summary":"requestId is not a stored request","value":{"errors":[{"status":422,"title":"Invalid attribute","detail":"requestId is not a valid template import request","source":{"pointer":"/data/attributes/requestId"}}]}},"Already processed":{"summary":"The record left pending already","value":{"error":"Request already processed, current status: completed"}}}}}},"500":{"description":"The job failed and the record is now failed (error: Processing failed.), or the record vanished between validation and processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Processing failed."}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/template/import/{requestId}":{"get":{"tags":["AI"],"summary":"Retrieve a template import","description":"Where a model-based import stands and, once completed, the saved template. Poll it after POST /ai/template/import/create: 409 while pending or processing, 200 once completed, 500, 504 or 413 once failed. Requires the permission to create email templates. Called by the template import agent in ac-agents; not a product API.","operationId":"retrieve-a-template-import","parameters":[{"name":"requestId","in":"path","description":"ID of the request, as answered by the create call.","required":true,"schema":{"type":"string"},"example":"0b3c1d6e-7f2a-4b9c-8d1e-2f3a4b5c6d7e"}],"responses":{"200":{"description":"The import finished; result names the saved template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportCompletedResponse"}}}},"403":{"description":"The user may not create email templates. Checked before anything else, so every call without the permission answers this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create email templates"}]}}}},"404":{"description":"No request of this kind has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportErrorResponse"},"example":{"error":"Request not found"}}}},"409":{"description":"The job has not finished: the record is pending or processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportInProgressResponse"},"example":{"status":"processing","message":"Request is still being processed","createdAt":"2026-10-23 14:02:11"}}}},"413":{"description":"The job failed because the model's output was truncated (errorCode content_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportFailedResponse"}}}},"500":{"description":"The job failed for a reason other than a timeout or truncated output (the failed body, errorCode null), or the record carries a status the action does not know (the unknown-status body).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TemplateImportFailedResponse"},{"$ref":"#/components/schemas/TemplateImportUnknownStatusResponse"}]}}}},"504":{"description":"The job failed because a model call timed out (errorCode timeout).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImportFailedResponse"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/ai/templates":{"get":{"tags":["AI"],"summary":"List the templates generated for brand kits","description":"The email templates generated for one brand kit (uuid given) or for every brand kit of the account, with counts of how many exist against how many could. A template that failed to generate is listed with createdSuccessfully false and templateId 0. Answers 500 when the templates could not be read.","operationId":"list-brandkit-templates","parameters":[{"name":"uuid","in":"query","description":"UUID of one brand kit to list templates for. Omitted, the templates of every brand kit are listed.","schema":{"type":"string"},"example":"7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}],"responses":{"200":{"description":"The templates and counts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplatesResponse"}}}},"500":{"description":"The templates could not be read (detail: Unable to fetch template list).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-internal":true},"post":{"tags":["AI"],"summary":"Generate one base template for a brand kit","description":"Background job of brand kit creation and rebuilds, one per base template: has the model write the content, renders the light and dark versions and saves them as email templates, replacing any earlier pair for the same slug. Answers 200 with skipped true when nothing was written because a later save superseded this job or another worker holds the lock. Answers 500 when the templates could not be saved. Only Hosted queues this call.","operationId":"create-brandkit-templates","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplateCreateWorkerRequest"}}}},"responses":{"200":{"description":"Nothing was written: superseded or locked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplateSkippedResponse"}}}},"201":{"description":"Both versions were generated and saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplateCreatedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The templates could not be saved (detail: Unable to save templates for brandkit followed by the UUID).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/create":{"post":{"tags":["AI"],"summary":"Generate one selected template","description":"Background job of POST /ai/templates/generate: has the model write the content for one base template in the given language and tone, renders the light and dark versions, saves them as email templates and records their IDs on the template request. On failure the template request is marked failed (IDs -1) and the call answers 500. Only Hosted queues this call.","operationId":"create-a-generated-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateWorkerRequest"}}}},"responses":{"201":{"description":"The templates were saved; requestId is the template request that was filled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateGenerationStartedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"Generation or saving failed (detail: Failed to generate template).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/generate":{"post":{"tags":["AI"],"summary":"Generate email templates from a prompt","description":"Has the model pick num base templates that fit the prompt, records a generation request with one template request per pick and queues a background job for each (POST /ai/templates/create). Answers at once with the request ID to poll with GET /ai/templates/{requestId}. Answers 500 when the request could not be stored or no job could be queued; a template whose job could not be queued is marked failed and the rest proceed.","operationId":"generate-templates","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateGenerateRequest"}}}},"responses":{"201":{"description":"The request was recorded and its jobs queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateGenerationStartedResponse"}}}},"422":{"description":"The body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The request could not be stored (detail: Failed to store templates), a template request could not be created (detail: Failed to dispatch template followed by its name) or no job could be queued (detail: Failed to dispatch templates).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/{requestId}":{"get":{"tags":["AI"],"summary":"Poll a template generation request","description":"The templates a generation request produced, keyed by base template name, once every job finished. Answers 409 while any job is still running, 404 when no request has this ID (a legacy single-message body), and 500 when the request or one of its jobs failed or a record could not be read.","operationId":"retrieve-generated-templates","parameters":[{"name":"requestId","in":"path","description":"UUID of the request, as answered by POST /ai/templates/generate.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The generated templates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateGenerationResultResponse"}}}},"404":{"description":"No request has this ID. A legacy body with a single message.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always Request not found.","type":"string","enum":["Request not found"],"example":"Request not found"}},"type":"object"}}}},"409":{"description":"A job is still running; poll again (detail: Request in progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"500":{"description":"The request or a job failed (detail: Request failed), or a record could not be read (detail: An error occurred while attempting to get request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/ai/templates/{templateId}/design-ir":{"get":{"tags":["AI"],"summary":"Retrieve the design IR of a template","description":"Read the design IR stored for an email template: the opaque JSON document the generation engine keeps so it can edit a stored template the way it edits a campaign, returned verbatim with the revision that identifies it. Called by the generation engine (ac-agents) before it edits a template. Reads need no template permission: a template the caller cannot see is reported as absent. Answers 404 for three reasons the detail string distinguishes: \"Not found\" when the account is not enrolled in campaign generation, \"Template not found: {id}\" when the template is missing or not visible to the caller, and \"Design IR not found\" when the template exists but has no design IR stored.","operationId":"retrieve-a-template-design-ir","parameters":[{"name":"templateId","in":"path","description":"Id of the email template whose design IR to read.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The stored design IR and its revision.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrDocument"}}}},"404":{"description":"Nothing to return. detail is one of three stable strings: \"Not found\" (the account is not enrolled), \"Template not found: {id}\" (missing or not visible) or \"Design IR not found\" (the template exists, nothing is stored).","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer","example":404},"title":{"type":"string","example":"Not Found"},"detail":{"description":"Which of the three reasons applies.","type":"string","example":"Design IR not found"},"error_code":{"type":"string","enum":["FEATURE_NOT_ENABLED","TEMPLATE_NOT_FOUND","DESIGN_IR_NOT_FOUND"],"example":"DESIGN_IR_NOT_FOUND"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The stored row could not be read (detail \"Design IR could not be read\", error_code DESIGN_IR_READ_FAILED), or it holds something that is not a JSON object or array (detail \"Stored design IR is not valid JSON\")."}},"x-canonical-resource":"templates","x-internal":true},"put":{"tags":["AI"],"summary":"Store the design IR of a template","description":"Store the design IR for an email template, replacing whatever was stored before. The design IR is an opaque JSON document owned by the generation engine; hosted stores the ir value verbatim keyed by template id and never inspects its shape. Called by the generation engine (ac-agents) after it composes or edits a template. Mirrors storing a campaign design IR: the write is read back before it is acknowledged, a verified write answers 204, and a write whose read-back found no row answers 200 with verified false. Send expectedRevision from a previous GET or PUT to refuse the write with 409 when another writer has changed the document since; omit it for last-writer-wins. Only v3 (markup) templates can hold a design IR; a v1 or v2 template answers 422. Requires enrollment in campaign generation (else 404 \"Not found\") and the update email templates permission.","operationId":"store-a-template-design-ir","parameters":[{"name":"templateId","in":"path","description":"Id of the email template the design IR belongs to.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"The design IR in an {\"ir\": ...} envelope.","required":true,"content":{"application/json":{"schema":{"required":["ir"],"properties":{"ir":{"description":"The design IR document to store verbatim: a non-empty JSON object or array the engine owns. Its JSON encoding must not exceed 4,000,000 bytes.","example":{"root":{"type":"container","blocks":[{"type":"text","text":"Hello"}]}},"oneOf":[{"type":"object"},{"type":"array","items":{}}]},"expectedRevision":{"description":"The revision the caller believes it is overwriting, from a previous GET or PUT. Present, the write is refused with 409 when the stored document has since changed; the empty string asserts that nothing is stored yet. Omitted or null, the write is last-writer-wins.","type":["string","null"],"example":"0f1d2c3b4a5e4f609b7c8d9e0f1a2b3c"}},"type":"object"}}}},"responses":{"200":{"description":"The write committed but the read-back found no row, so it is unverified; reason says whether the read-back query found nothing or failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignIrUnverifiedWrite"}}}},"204":{"description":"Stored and read back: the row holds the document that was written."},"403":{"description":"The API user may not update email templates, or cannot see this template (detail \"You do not have access to this template\")."},"404":{"description":"detail is \"Not found\" (error_code FEATURE_NOT_ENABLED) when the account is not enrolled in campaign generation, or \"Template not found: {id}\" (error_code TEMPLATE_NOT_FOUND) when no such template exists."},"409":{"description":"Another request is writing this template's design IR (error_code DESIGN_IR_LOCKED), or expectedRevision is not the stored revision (error_code DESIGN_IR_REVISION_MISMATCH, with current_revision on the error)."},"422":{"description":"The body is not a JSON object with an ir key, ir is empty or not an object or array, ir encodes to more than 4,000,000 bytes, or expectedRevision is not a string (detail \"Invalid design IR payload\" or the validation list); or the template is a v1 or v2 template that stores no markup (error_code DESIGN_IR_UNSUPPORTED_EDITOR, detail \"Template {id} uses editor version {n}, which cannot store a design IR\")."},"500":{"description":"The existing row could not be read before writing (detail \"Design IR could not be read\"), or the row read back cannot be a copy of what was written (detail \"Design IR write could not be verified\")."}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/{uuid}/generate-missing":{"post":{"tags":["AI"],"summary":"Queue the templates a brand kit is missing","description":"Finds the base templates the brand kit has no stored template for (for example ones added since the kit was created) and queues a generation job for each. Answers 201 with the names queued, or 200 with an empty list when nothing is missing. A brand kit error answers 400, 404, 422 or 503 with its own message; anything else answers 500.","operationId":"generate-missing-brandkit-templates","parameters":[{"name":"uuid","in":"path","description":"UUID of the brand kit.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Nothing is missing; dispatchedTemplates is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitMissingTemplatesResponse"}}}},"201":{"description":"Jobs were queued for the templates listed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitMissingTemplatesResponse"}}}},"400":{"description":"The brand kit service refused the request; detail is its message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"404":{"description":"No brand kit has this UUID; detail is the service message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The brand kit cannot have templates generated; detail is the service message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"500":{"description":"The jobs could not be queued (detail: Unable to generate missing templates for UUID: followed by the UUID).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"503":{"description":"The brand kit service was unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/{uuid}/preview":{"put":{"tags":["AI"],"summary":"Render a template preview for a brand kit","description":"Renders one base template with the brand kit sent in the body, so a kit can be previewed before or after it is saved. With the nil UUID (00000000-0000-0000-0000-000000000000) the kit is treated as unsaved: a legacy stock template is rendered from the body with industry fallback images, nothing is stored and no model is called. With a stored kit's UUID the body's logos are checked and uploaded to the kit first, and a stored template that failed to generate is queued for regeneration. Answers 400 when the body carries no brand kit, 404 when no template exists for the slug and kit, and the brand kit image check can answer 400, 403, 409, 422, 429 or 503 with its own message.","operationId":"preview-a-brandkit-template","parameters":[{"name":"uuid","in":"path","description":"UUID of the brand kit.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplatePreviewRequest"}}}},"responses":{"200":{"description":"The rendered preview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandkitTemplatePreviewResponse"}}}},"400":{"description":"The body carries no brand kit (detail: Missing brandkit data), or the image check refused a logo address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"403":{"description":"The image check refused a logo the account may not use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"404":{"description":"No template exists for this slug and brand kit (detail: Unable to find template for brandkit {uuid} and template {slug}).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"The image check found a conflicting upload in progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The body failed validation (unknown slug), or the image check refused a logo.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RequestValidationErrorResponse"},{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}]}}}},"429":{"description":"The image check was rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"500":{"description":"The preview could not be rendered; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"503":{"description":"The image service was unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ai/templates/{uuid}/rebuild":{"put":{"tags":["AI"],"summary":"Rebuild every template of a brand kit","description":"Regenerates all base templates for the brand kit in place, replacing the stored email templates, and answers a one-sentence text confirmation (served as text/html, the default) rather than JSON. Answers 500 when the rebuild failed.","operationId":"rebuild-brandkit-templates","parameters":[{"name":"uuid","in":"path","description":"UUID of the brand kit.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The templates were rebuilt. The body is the sentence Templates rebuilt for brandkit followed by the UUID.","content":{"text/html":{"schema":{"type":"string","example":"Templates rebuilt for brandkit 7c2e4b1a-0d3f-4e5a-9b6c-1f2a3b4c5d6e"}}}},"500":{"description":"The rebuild failed; detail is the exception message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/translations/checklist/{campaignId}":{"get":{"tags":["AI"],"summary":"Check whether a campaign is ready to be translated","description":"Reports, for each thing a campaign needs before it can be translated, whether it is in place. Checks the campaign's recipients' preferred languages against the account's language mapping or, when none is stored, a mapping of the supported languages, which is then stored. A check that fails does not fail the call: read the booleans.","operationId":"retrieve-campaign-translation-checklist","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign.","required":true,"schema":{"type":"integer"},"example":42}],"responses":{"200":{"description":"Each check and whether it passes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationChecklist"}}}},"400":{"description":"The checklist could not be worked out, for example the campaign could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"campaignId does not name a campaign, or the campaign has no lists or segment or no message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The checklist could not be built. detail says Failed to build checklist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-internal":true}},"/ai/translations/count":{"post":{"tags":["AI"],"summary":"Count the recipients of a translated language version (background worker)","description":"Background worker target, not a client API: Hosted's own queue calls it on itself, started by GET /ai/translations/poll/{campaignId}, to count how many recipients one language version of a segment campaign reaches. It works the count out and writes it to the count record. It answers 200 with a message whatever happened: a failed count is logged, not raised, so the queue does not retry.","operationId":"count-campaign-translation-recipients","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationSegmentCountRequest"}}}},"responses":{"200":{"description":"The job ran. message is Segment count updated, or Failed to get segment count when counting failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationMessageResponse"},"example":{"message":"Segment count updated"}}}},"422":{"description":"requestid does not name a stored count record, or campaignid is missing, not an integer or does not name a campaign.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/translations/generate":{"post":{"tags":["AI"],"summary":"Translate a campaign message into one language (background worker)","description":"Background worker target, not a client API: Hosted's own queue calls it on itself, one job for each language, after POST /ai/translations/initialize or /retry. It translates the message from source_code to target_code, creates the language version of the campaign, and updates that language's status record. A message not written in English goes through English: target_languages then lists the languages still to do, and a job for each is queued when this one finishes. It answers 200 with a message whatever happened, so the queue does not retry on its own: the message says whether the language was translated, was queued to try again, or failed, and a failure is also recorded on the translation request.","operationId":"generate-campaign-translation-variation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationGenerateRequest"}}}},"responses":{"200":{"description":"The job ran. message says how it ended: generated translation for the target code, retrying variation request, failed to generate translation for the target code, failed to dispatch translations, or failed to complete request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationMessageResponse"},"example":{"message":"generated translation for es"}}}},"400":{"description":"The language version's status record is already completed or failed, so there is nothing to translate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"A required field is missing or has the wrong type, campaignid or messageid does not name a campaign or a message with a design, or status_requestid does not name a stored status record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"An unexpected failure while translating. The cause is only logged."}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/translations/initialize":{"post":{"tags":["AI"],"summary":"Start translating a campaign","description":"Starts translating a campaign's message into the languages its recipients prefer. Hosted reads the recipients' preferred languages, works out which of them the account's language mapping covers, stores a translation request with one status record per language, and queues a background job for each (POST /ai/translations/generate). A message not written in English is translated to English first and then into the rest. The call answers at once with the request id: poll GET /ai/translations/poll/{campaignId} for the result. When the account has no language mapping, one is built from the supported languages and stored. Answers 409 when the campaign already has a completed translation or one started within the last hour; a failed one, or one still in progress after an hour, is deleted along with its language versions and replaced. To translate again, delete the translation first with DELETE /ai/translations/{campaignId}.","operationId":"start-campaign-translation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationInitializeRequest"}}}},"responses":{"200":{"description":"The translation was started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationRequestedResponse"}}}},"400":{"description":"The translation cannot be set up: the account has no language field, the recipients have no contacts or no preferred languages the mapping covers, the message language cannot be determined or the message design cannot be used. detail says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"409":{"description":"The campaign already has a completed translation, or one that started within the last hour and has not failed. Delete it first to translate again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"campaignid is missing or not an integer, does not name a campaign, or the campaign has no lists or segment, no message, or no message design.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The preferred languages could not be read, the records could not be created, or the jobs could not be queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/translations/map":{"get":{"tags":["AI"],"summary":"Retrieve the account's language mapping","description":"Returns the account's language mapping: the language each value of the language field translates to, and the contact field the mapping was built from. This call never answers an error status. When no mapping is stored the body is an empty list, not an object. A failed read of the mapping record is logged and answers the same empty list, so the two cannot be told apart. mapping and existingFieldId are both null only when the stored mapping data cannot be decoded or the record of its field cannot be read; the cause is only logged.","operationId":"retrieve-language-mapping","responses":{"200":{"description":"The stored mapping; an empty list when none is stored or the mapping record could not be read; or a mapping and existingFieldId that are both null when the stored data could not be decoded or its field record could not be read.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/LanguageMappingDetails"},{"type":"array","items":{"type":"object"},"maxItems":0}]}}}}},"x-canonical-resource":"campaign_message","x-internal":true},"put":{"tags":["AI"],"summary":"Replace the account's language mapping","description":"Replaces the stored language mapping with the one in the body and answers with it. Each entry's code and supportedLang must be a pair the translation service supports, or both default. When existingFieldId is given it is stored with the mapping, and the preferred-language automation is rebuilt from that field: the existing one is deleted and a new one created from the field's values. When the account has a preferred-language field, every contact whose value in the existingFieldId field the mapping maps to a language also has the matching code written to that preferred-language field, replacing any value already there; values mapped to default are left alone. This is applied before the automation is rebuilt and is not undone if that step fails. Rebuilding the automation is best effort: the existing automation is deleted first, and if building the new one then fails the failure is only logged, the call still answers 200 and the account is left without one. When the account has no preferred-language field the contact writes and the rebuild are skipped and the call still answers 200. Rebuilding the automation needs permission to manage automations, and a user without it is refused with 403 before anything is stored. Without existingFieldId no contact value or automation is touched and the permission is not needed.","operationId":"update-language-mapping","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageMappingUpdateRequest"}}}},"responses":{"200":{"description":"The saved mapping, with needsReview set to false on every entry because saving marks the mapping as reviewed, and the existingFieldId the request sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageMappingDetails"}}}},"403":{"description":"existingFieldId was given and the user may not manage automations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"mapping is missing, empty or not a list, an entry lacks lang, supportedLang or code, an entry pairs a code with a language the translation service does not support, or existingFieldId does not name a dropdown or radio contact field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The mapping could not be stored, or deleting the existing preferred-language automation failed. The cause is only logged. A failure to build the new automation is not reported here: it is logged and the call answers 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":true,"x-internal":true},"post":{"tags":["AI"],"summary":"Build and store the account's language mapping","description":"Builds the account's language mapping, stores it in place of any stored one, and returns it. Without existingFieldId the mapping is built from the languages the translation service supports. With existingFieldId, the field's options and the values contacts have saved are sent to an AI model, which maps each onto a supported language; those entries come back with needsReview true so a person can check them. The field must be a dropdown or radio field with at least one option or saved value. Contacts and automations are not changed.","operationId":"create-language-mapping","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageMappingCreateRequest"}}}},"responses":{"200":{"description":"The mapping that was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageMappingDetails"}}}},"400":{"description":"The field has no options or saved values to map, or the model refused the request."},"422":{"description":"existingFieldId does not name a contact field, or the field is not a dropdown or radio field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The supported languages could not be fetched, the model request failed, or the mapping could not be stored. detail carries the underlying message or says Unable to create mapping.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"tags":["AI"],"summary":"Delete the account's language mapping","description":"Deletes the stored language mapping and the record of which contact field it was built from. It succeeds when none is stored. Translations already made, and the preferred-language automation, are not touched.","operationId":"delete-language-mapping","responses":{"200":{"description":"The mapping was deleted, or none was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageMappingDeletedResponse"}}}},"500":{"description":"The mapping could not be deleted. detail says Unable to delete language mapping; the cause is only logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/translations/poll/{campaignId}":{"get":{"tags":["AI"],"summary":"Retrieve the status of a campaign's translation","description":"Reports where a campaign's translation stands and each language of it. Poll this call after starting a translation until status is completed or failed. For a campaign that sends to a segment, the first call also queues background jobs that count each language version's recipients, and the status is reported in_progress, with recipientCount null, until every count is in. Needs the account to have a language mapping and a preferred-language field.","operationId":"retrieve-campaign-translation-status","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign.","required":true,"schema":{"type":"integer"},"example":42}],"responses":{"200":{"description":"The translation's status and its language versions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationStatusResponse"}}}},"400":{"description":"The account has no language mapping, or no preferred-language field was found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"campaignId does not name a campaign, or the campaign has no translation request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The status could not be read, including when the campaign has no recipients or a language has no entry in the mapping.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-internal":true}},"/ai/translations/retry":{"post":{"tags":["AI"],"summary":"Translate one language version of a campaign again","description":"Translates one language version of a campaign's message again, after it failed. The version is set back to in progress, its earlier message is forgotten, and a new background job is queued for it. When the original message is not in English the version is translated from the English one, which must exist. If the translation as a whole had been marked complete it goes back to in progress; one marked failed is refused with 400. Answers with the id of the campaign's translation request; poll GET /ai/translations/poll/{campaignId}.","operationId":"retry-campaign-translation-variation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationRetryRequest"}}}},"responses":{"200":{"description":"The language version was queued again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationRequestedResponse"}}}},"400":{"description":"The translation as a whole failed, so start it again instead; the language version is already completed or still in progress; or the English version needed to translate from does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"campaignid is missing or not an integer or has no translation request, targetLanguage is missing, en, not a supported language, or has no language version on the campaign.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The language version could not be reset, or the job could not be queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ai/translations/unsent":{"get":{"tags":["AI"],"summary":"List translated campaigns that have not been sent","description":"Lists the campaigns that have a translation request and are still a draft or scheduled. Shown before the language mapping changes, because changing it means translating those campaigns again. An empty list when there are none.","operationId":"list-unsent-translated-campaigns","responses":{"200":{"description":"The unsent translated campaigns.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UnsentTranslatedCampaign"}}}}},"500":{"description":"The list could not be read. detail says Failed to get unsent translated campaigns.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-internal":true},"post":{"tags":["AI"],"summary":"Reset the unsent translated campaigns","description":"Deletes the translation of each given campaign, with its language versions, so it can be translated again under a new language mapping, and sets a scheduled campaign back to a draft. The ids must be unsent (draft or scheduled) campaigns and must include every one that GET /ai/translations/unsent lists; a campaign with no translation request is skipped. Nothing is changed when the ids are refused.","operationId":"reset-unsent-translated-campaigns","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsentTranslatedCampaignsResetRequest"}}}},"responses":{"204":{"description":"The campaigns were reset. There is no body."},"400":{"description":"A given campaign is no longer unsent, or the list leaves out an unsent translated campaign.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"campaignids is missing, empty, not a list, or holds something that is not an integer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The reset failed. detail says Failed to reset unsent translated campaigns.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ai/translations/{campaignId}":{"delete":{"tags":["AI"],"summary":"Delete a campaign's translation","description":"Deletes the translated language versions of a campaign and the translation request, or with variation, one language version. A language version's message and any recipient count record go with it; the campaign's own message does not. When one language is deleted while the translation is still in progress, the translation is then marked complete so the remaining languages can finish; a failure there is logged and ignored. Deleting is how a campaign is translated again.","operationId":"delete-campaign-translation","parameters":[{"name":"campaignId","in":"path","description":"Id of the campaign.","required":true,"schema":{"type":"integer"},"example":42},{"name":"variation","in":"query","description":"Code of the one language version to delete. It cannot be the language the message was written in. Left out, every language version and the translation request are deleted.","schema":{"type":"string"},"example":"es"}],"responses":{"204":{"description":"The translation, or the one language version, was deleted. There is no body."},"422":{"description":"campaignId does not name a campaign, the campaign has no translation request, or variation is the language the message was written in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestValidationErrorResponse"}}}},"500":{"description":"The translation could not be deleted. detail says Failed to delete request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/alerts/generate":{"post":{"summary":"Rebuild the account's in-app alerts","description":"Internal: queues a run of the alert checks that otherwise run while someone is signed in to the app, so the account's in-app alerts (sending and contact limit warnings, and campaign, deal connection and concurrent session notices) are brought up to date without a signed-in user. Not a customer API.\n\nThe checks run later as a background batch job, and the response does not wait for them. When they run, each check creates, updates or removes the account's alert of its kind. Takes no request body and no parameters. If the job cannot be queued, the failure is only logged and the answer is still 201.","operationId":"generate-alerts","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"responses":{"201":{"description":"The alert checks were queued, or queuing them failed and was logged. The body is empty."},"405":{"description":"The method is not POST. The Allow header names POST, and the body is empty."}},"x-internal":true}},"/ambassador/stats":{"get":{"summary":"Retrieve the user's referral program stats","description":"The signed-in user's standing in the ActiveCampaign referral (ambassador) program, read from Referral Rock: their referral link and how many clicks, referrals and paid signups it has brought, and the commission paid to them. Internal: backs the referral panel of the app navigation.\n\nThe user is matched to a Referral Rock member by their login email. When there is no member with that email yet, this read enrols the user first (name, email and phone from their user record, the account ID as the external identifier), so the first call for a user creates their Referral Rock membership. The stats are then cached per user for four hours, so a new click or referral can take that long to show.","operationId":"retrieve-ambassador-stats","responses":{"200":{"description":"The user's referral stats.","content":{"application/json":{"schema":{"required":["referral_link","clicks","unique_referrals","paid_signups","commission_paid"],"properties":{"referral_link":{"description":"The user's personal referral URL.","type":"string","example":"https://example.referralrock.com/l/PATLEE/"},"clicks":{"description":"How many times the referral link has been opened (Referral Rock views).","type":"integer","example":42},"unique_referrals":{"description":"Referrals the link has brought in (Referral Rock's referrals count).","type":"integer","example":3},"paid_signups":{"description":"Referrals Referral Rock has marked approved (its referralsApproved count).","type":"integer","example":1},"commission_paid":{"description":"Total reward amount Referral Rock has recorded for the user (its rewardAmountTotal).","type":"number","example":100}},"type":"object"}}}},"500":{"description":"Referral Rock could not be reached, refused the lookup or the enrolment, or answered with something unexpected. The error is logged and rethrown, so the body is not a documented JSON shape."}},"x-canonical-resource":"account_user","x-internal":true}},"/assetMigration":{"post":{"summary":"Start moving the account's images to the Content Manager","description":"Starts the one-time move of the images the account keeps in the old asset manager into the Content Manager. Only acts while the account's migration status (the content_manager.asset_migration_status setting) is not started: Hosted then asks the asset-manager-migrater service to move the images, retrying the call with backoff, and hands it the callback URL /api/3/assetMigration/{id} carrying the ID of the user making this request; a PUT or PATCH on that URL marks the migration completed. Once the service accepts the request the status becomes in progress. In any other status nothing is called or changed. Either way the answer is the status setting as it now stands. The request body is ignored. Internal: one step of the asset manager to Content Manager migration, not a customer API.","operationId":"start-asset-migration","responses":{"200":{"description":"The migration status setting, under config. val is in progress once the move has started; otherwise it is unchanged.","content":{"application/json":{"schema":{"properties":{"config":{"description":"The account setting that records the migration status.","properties":{"keyname":{"description":"Name of the setting. Always content_manager.asset_migration_status here.","type":"string","example":"content_manager.asset_migration_status"},"section":{"description":"Section the setting is filed under. Not used by this setting.","type":"string","example":""},"item":{"description":"Item the setting is filed under. Not used by this setting.","type":"string","example":""},"userid":{"description":"ID of the user the setting belongs to, as a string.","type":"string","example":"0"},"val":{"description":"The migration status: not started, in progress or completed.","type":"string","example":"in progress"},"cdate":{"description":"When the setting was created, as a date and time with UTC offset.","type":"string","example":"2024-03-01T10:15:00-06:00"},"udate":{"description":"When the setting was last changed, as a date and time with UTC offset.","type":"string","example":"2024-03-05T09:02:11-06:00"},"links":{"description":"URLs of the records related to the setting.","properties":{"owner":{"description":"URL of the user the setting belongs to.","type":"string","example":"https://:account.api-us1.com/api/3/configs/42/owner"}},"type":"object"},"id":{"description":"ID of the setting, as a string.","type":"string","example":"42"},"owner":{"description":"ID of the user the setting belongs to. The same value as userid.","type":"string","example":"0"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is JSON but not an object. Body: errors, a list with one item carrying status, title and detail."},"500":{"description":"The asset-manager-migrater service could not be reached or answered with an error after the retries, or the account has no migration status setting. Body: message, a generic sentence."}},"x-canonical-resource":"content_manager_file","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/assetMigration/status":{"get":{"summary":"Retrieve the account's image migration status","description":"The status of the one-time move of the account's images from the old asset manager into the Content Manager: the content_manager.asset_migration_status setting, under meta.status. While the status is not started the call also settles it: if the asset-manager-migrater service reports the images already exist in the Content Manager, Hosted starts the migration and then stores completed (this response still says not started); if the account has no images in the old asset manager, it stores and returns completed. Only GET is accepted; other verbs answer 405 with an Allow: GET header. Internal: part of the asset manager to Content Manager migration, not a customer API.","operationId":"retrieve-asset-migration-status","x-canonical-resource":"content_manager_file","responses":{"200":{"description":"The migration status","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","properties":{"status":{"type":"string","description":"not started, in progress or completed. An empty string when the account has no migration status setting.","example":"completed"}}}}},"example":{"meta":{"status":"completed"}}}}},"500":{"description":"Checking with the asset-manager-migrater service failed, or it answered with an error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always Internal server error.","example":"Internal server error"}}},"example":{"error":"Internal server error"}}}},"503":{"description":"The asset-manager-migrater service could not be reached. The body is the same as for 500.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always Internal server error.","example":"Internal server error"}}},"example":{"error":"Internal server error"}}}}},"deprecated":false,"x-internal":true}},"/assetMigration/{id}":{"put":{"summary":"Mark the account's image migration as completed","description":"Callback for the asset-manager-migrater service once it has finished moving the account's images; POST /api/3/assetMigration hands it this URL. Only acts while the account's migration status (the content_manager.asset_migration_status setting) is in progress: the status becomes completed and the user whose ID is in the path is emailed that the migration has finished, unless that user has no email address. In any other status nothing changes. Either way the answer is the status setting as it now stands. The request body is ignored, and PUT and PATCH behave the same. Internal: service-to-service callback, not a customer API.","operationId":"complete-asset-migration","parameters":[{"name":"id","in":"path","description":"ID of the user who started the migration. That user is the one emailed when it completes.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The migration status setting, under config. val is completed when this call finished the migration; otherwise it is unchanged.","content":{"application/json":{"schema":{"properties":{"config":{"description":"The account setting that records the migration status.","properties":{"keyname":{"description":"Name of the setting. Always content_manager.asset_migration_status here.","type":"string","example":"content_manager.asset_migration_status"},"section":{"description":"Section the setting is filed under. Not used by this setting.","type":"string","example":""},"item":{"description":"Item the setting is filed under. Not used by this setting.","type":"string","example":""},"userid":{"description":"ID of the user the setting belongs to, as a string.","type":"string","example":"0"},"val":{"description":"The migration status: not started, in progress or completed.","type":"string","example":"completed"},"cdate":{"description":"When the setting was created, as a date and time with UTC offset.","type":"string","example":"2024-03-01T10:15:00-06:00"},"udate":{"description":"When the setting was last changed, as a date and time with UTC offset.","type":"string","example":"2024-03-05T09:02:11-06:00"},"links":{"description":"URLs of the records related to the setting.","properties":{"owner":{"description":"URL of the user the setting belongs to.","type":"string","example":"https://:account.api-us1.com/api/3/configs/42/owner"}},"type":"object"},"id":{"description":"ID of the setting, as a string.","type":"string","example":"42"},"owner":{"description":"ID of the user the setting belongs to. The same value as userid.","type":"string","example":"0"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is JSON but not an object. Body: errors, a list with one item carrying status, title and detail."},"500":{"description":"The account has no migration status setting, or reading or writing it failed. Body: message, a generic sentence."}},"x-canonical-resource":"content_manager_file","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Mark the account's image migration as completed","description":"Callback for the asset-manager-migrater service once it has finished moving the account's images; POST /api/3/assetMigration hands it this URL. Only acts while the account's migration status (the content_manager.asset_migration_status setting) is in progress: the status becomes completed and the user whose ID is in the path is emailed that the migration has finished, unless that user has no email address. In any other status nothing changes. Either way the answer is the status setting as it now stands. The request body is ignored, and PUT and PATCH behave the same. Internal: service-to-service callback, not a customer API.","operationId":"complete-asset-migration-via-patch","parameters":[{"name":"id","in":"path","description":"ID of the user who started the migration. That user is the one emailed when it completes.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The migration status setting, under config. val is completed when this call finished the migration; otherwise it is unchanged.","content":{"application/json":{"schema":{"properties":{"config":{"description":"The account setting that records the migration status.","properties":{"keyname":{"description":"Name of the setting. Always content_manager.asset_migration_status here.","type":"string","example":"content_manager.asset_migration_status"},"section":{"description":"Section the setting is filed under. Not used by this setting.","type":"string","example":""},"item":{"description":"Item the setting is filed under. Not used by this setting.","type":"string","example":""},"userid":{"description":"ID of the user the setting belongs to, as a string.","type":"string","example":"0"},"val":{"description":"The migration status: not started, in progress or completed.","type":"string","example":"completed"},"cdate":{"description":"When the setting was created, as a date and time with UTC offset.","type":"string","example":"2024-03-01T10:15:00-06:00"},"udate":{"description":"When the setting was last changed, as a date and time with UTC offset.","type":"string","example":"2024-03-05T09:02:11-06:00"},"links":{"description":"URLs of the records related to the setting.","properties":{"owner":{"description":"URL of the user the setting belongs to.","type":"string","example":"https://:account.api-us1.com/api/3/configs/42/owner"}},"type":"object"},"id":{"description":"ID of the setting, as a string.","type":"string","example":"42"},"owner":{"description":"ID of the user the setting belongs to. The same value as userid.","type":"string","example":"0"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is JSON but not an object. Body: errors, a list with one item carrying status, title and detail."},"500":{"description":"The account has no migration status setting, or reading or writing it failed. Body: message, a generic sentence."}},"x-canonical-resource":"content_manager_file","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/audiences":{"get":{"tags":["Saved Segment Summaries"],"summary":"List Summaries for Saved Segments","description":"Lists the account's Saved Segments with their summary: name, category, contact counts and dates.\n\nA Saved Segment is a segment that has a `name` (a name cannot be added after a segment is created, it must be set when the segment is created). Saved Segments are displayed on the app/segments page. A segment without a `name` is not a Saved Segment and does not have a summary.\n\nSaved Segment summaries can be found by listing them or by searching by name with the `search` param. To read a segment's definition use `GET /api/3/segmentsV2/{segmentId}`.\n\nThe `counts` attribute contains `last_total` and `last_active_total`. These results are from the segment's last evaluation run at the indicated `run_id_start` time (counts are not live).\n\nA 404 means no Saved Segments were found. This could be because the account has no Saved Segments or no Saved Segments match the `search` filter. A 404 indicates an empty result set, not an error.","operationId":"get_saved_segment_summaries","x-canonical-resource":"saved_segment_summaries","parameters":[{"name":"page","in":"query","description":"Page Number","required":false,"style":"form","schema":{"type":"integer","minimum":1,"example":1}},{"name":"page_size","in":"query","description":"Page Size","required":false,"style":"form","schema":{"type":"integer","minimum":1,"maximum":10000,"example":10,"default":20}},{"name":"sort","in":"query","description":"Single sort value. Dash sign indicates descending order","required":false,"schema":{"type":"string","default":"-updated_date","enum":["updated_date","-updated_date","name","-name","recent","-recent","last_total","-last_total","last_active_total","-last_active_total"]}},{"name":"search","in":"query","description":"Search for Saved Segments by name. Not case sensitive","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Retrieved Saved Segment Summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentSummarySuccessRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentSummaryErrorRootDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"No Saved Segments matched the request. The account has no Saved Segments, or none match the `search` filter. This is an empty result, not an error."}},"deprecated":false}},"/audiences/{segmentId}":{"get":{"tags":["Saved Segment Summaries"],"summary":"Retrieve a Saved Segment's Summary","description":"Retrieves the summary (name, category, contact counts, dates) of one Saved Segment by its UUID.\n\nGet the UUID from `GET /api/3/audiences` (list them or search by name with `search`). Contact counts are from the segment's last evaluation run, not live.\n\nOnly Saved Segments have a summary: segments that have a `name`. A segment without a `name` returns 404 here even though the segment exists. If you are not sure the segment is a Saved Segment, call `GET /api/3/segmentsV2/{segmentId}` first and check for a `name`.\n\nTo read the segment's definition use `GET /api/3/segmentsV2/{segmentId}`.","operationId":"get_saved_segment_summaries_by_id","x-canonical-resource":"saved_segment_summaries","parameters":[{"name":"segmentId","in":"path","description":"The Saved Segment's UUID. Numeric (legacy) segment IDs never have a summary and return 404.","required":true,"style":"simple","schema":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132"}}],"responses":{"200":{"description":"Retrieve a Saved Segment's Summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentSummarySuccessRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentSummaryErrorRootDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment Not Found, or the segment is not a Saved Segment (it has no `name`)"}},"deprecated":false}},"/automation/actions":{"get":{"summary":"List an automation's action blocks","description":"Internal: backs the automation builder. Returns every block of one automation in the same JSON API format as `GET /automations/{id}/blocks`. Requires the `pg_automation_manage` permission. Answers GET, POST and PUT; any other method gets 405 with `{\"message\":\"Method not allowed\",\"success\":0}`.","operationId":"list-automation-action-blocks","x-canonical-resource":"automation","parameters":[{"name":"automationId","in":"query","description":"ID of the automation whose blocks to return.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The automation's blocks.","content":{"application/json":{"schema":{"type":"object","properties":{"automationBlocks":{"type":"array","description":"Every block of the automation.","items":{"$ref":"#/components/schemas/AutomationBuilderActionBlock"}}}}}}},"403":{"description":"The user lacks the `pg_automation_manage` permission, or (GET) may not access this automation. For a missing permission the body is a JSON string whose content is the encoded `{\"success\":0,\"message\":\"You don't have permission to perform this action.\"}` object: the endpoint encodes that result twice.","content":{"application/json":{"schema":{"oneOf":[{"type":"string","description":"JSON-encoded `success`/`message` result."},{"type":"object","description":"Access to the automation was denied.","properties":{"errors":{"type":"array","description":"One entry with `status` `403` and `detail` `Forbidden`.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status."},"detail":{"type":"string","description":"Error detail."}}}}}}]}}}},"404":{"description":"No automation with this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found, for example `No Result found for Series with id 10`."}}}}}},"422":{"description":"The `automationId` query parameter is missing or empty.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"`Missing parameter 'automationId'.`"}}}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Add an action block to an automation","description":"Internal: backs the automation builder. Inserts one action block next to or under an existing block and configures it with the block type's own fields. Siblings after the insertion point are renumbered, an inactive automation is marked as a draft, a revision snapshot is recorded and a new builder screenshot is requested. An `if` block is created with its `else` branch. Requires the `pg_automation_manage` permission. Answers GET, POST and PUT; any other method gets 405 with `{\"message\":\"Method not allowed\",\"success\":0}`.","operationId":"create-automation-action-block","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["seriesid","referenceblock","type"],"properties":{"seriesid":{"type":"integer","description":"ID of the automation."},"referenceblock":{"type":"integer","description":"ID of the existing block, in the same automation, that the new block is placed relative to."},"direction":{"type":"integer","enum":[-1,0,1],"default":0,"description":"Where the new block goes relative to `referenceblock`: `-1` before it in the same branch, `0` (or omitted) as the first block under it, `1` after it in the same branch."},"type":{"type":"string","description":"Block type to create, for example `note`, `addtag`, `update`, `wait`, `send` or `if`. `end` is refused."},"params":{"type":"object","description":"Fields of the block type's builder form, for example `{\"note\": \"...\"}` for `note`, `{\"tagNames\": [\"...\"]}` for `addtag` or `{\"segmentid\": 12}` for `if`. Each key is passed to the block type's save routine as a form field.","additionalProperties":true}}},"example":{"seriesid":1,"referenceblock":1,"direction":0,"type":"note","params":{"note":"new note from API"}}}}},"responses":{"201":{"description":"The block was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockSaveResult"}}}},"402":{"description":"Adding the block would exceed the account's automation block limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockLimitError"}}}},"403":{"description":"The user lacks the `pg_automation_manage` permission, or (GET) may not access this automation. For a missing permission the body is a JSON string whose content is the encoded `{\"success\":0,\"message\":\"You don't have permission to perform this action.\"}` object: the endpoint encodes that result twice.","content":{"application/json":{"schema":{"oneOf":[{"type":"string","description":"JSON-encoded `success`/`message` result."},{"type":"object","description":"Access to the automation was denied.","properties":{"errors":{"type":"array","description":"One entry with `status` `403` and `detail` `Forbidden`.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status."},"detail":{"type":"string","description":"Error detail."}}}}}}]}}}},"422":{"description":"The block was not created: the automation or reference block is missing or not found, the type is not recognised, the parent is a layer block, or the block type's own fields failed validation. `succeeded` is 0 and `message` says why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockSaveResult"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update an automation action block","description":"Internal: backs the automation builder. Re-saves one existing block with new values for its type's fields; fields not sent keep the defaults of the block type's save routine. Records a revision snapshot and requests a new builder screenshot. Requires the `pg_automation_manage` permission. Answers GET, POST and PUT; any other method gets 405 with `{\"message\":\"Method not allowed\",\"success\":0}`.","operationId":"update-automation-action-block","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["seriesid","blockid"],"properties":{"seriesid":{"type":"integer","description":"ID of the automation."},"blockid":{"type":"integer","description":"ID of the block to update, in that automation."},"params":{"type":"object","description":"Fields of the block type's builder form, for example `{\"tagNames\": [\"...\"]}` for `addtag`. Each key is passed to the block type's save routine as a form field.","additionalProperties":true}}},"example":{"seriesid":1,"blockid":2,"params":{"tagNames":["updated tagname from API"]}}}}},"responses":{"200":{"description":"The block was updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockSaveResult"}}}},"403":{"description":"The user lacks the `pg_automation_manage` permission, or (GET) may not access this automation. For a missing permission the body is a JSON string whose content is the encoded `{\"success\":0,\"message\":\"You don't have permission to perform this action.\"}` object: the endpoint encodes that result twice.","content":{"application/json":{"schema":{"oneOf":[{"type":"string","description":"JSON-encoded `success`/`message` result."},{"type":"object","description":"Access to the automation was denied.","properties":{"errors":{"type":"array","description":"One entry with `status` `403` and `detail` `Forbidden`.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status."},"detail":{"type":"string","description":"Error detail."}}}}}}]}}}},"422":{"description":"The block was not updated: the automation or block is missing or not found, the block type has no save routine, or its fields failed validation. `succeeded` is 0 and `message` says why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockSaveResult"}}}}},"deprecated":false,"x-internal":true}},"/automation/batch":{"get":{"summary":"Retrieve a page of automation revision history","description":"Internal: backs the revision history panel of the automation builder. Renders one page of an automation's revisions, newest first and excluding campaign revisions, as an HTML fragment: one entry per revision, followed by a \"load more\" element carrying the next `start` when more remain, or a \"no recent changes\" element when there are none. Only GET is answered; any other method gets an empty 200 response.","operationId":"retrieve-automation-revision-batch","x-canonical-resource":"automation","parameters":[{"name":"seriesid","in":"query","description":"ID of the automation.","required":true,"schema":{"type":"integer"}},{"name":"start","in":"query","description":"Offset of the first revision to render. Defaults to 0.","required":false,"schema":{"type":"integer"}},{"name":"limit","in":"query","description":"How many revisions to render; must be greater than 0.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The HTML fragment, or, when `seriesid` or `limit` is missing or not positive, a JSON `success: 0` result naming the missing value (`The series ID was not provided.`, `The limit was not provided.`, or `The start was not provided.` for a negative `start`).","content":{"text/html":{"schema":{"type":"string","description":"Revision history HTML."}},"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderOutcome"}}}},"500":{"description":"No automation with this ID that the user can see; the template cannot render without one.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Generic error message.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/automation/bulk_skip_wait":{"post":{"summary":"Skip several contacts past a wait","description":"Internal: backs the manage contacts drawer when it is opened from a wait queue. Advances up to 100 contact automation runs that are at the same wait or goal block. Each run is skipped on its own: a contact that already left the block, or a skip that throws, is listed in `failed` and the rest of the batch continues. Requires the `pg_automation_manage` (manage automations) permission. POST only.","operationId":"bulk-skip-contact-automation-waits","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":100,"description":"The waits to end. One to one hundred.","items":{"type":"object","required":["seriesid","blockid","subscriberid","runid"],"properties":{"seriesid":{"type":"integer","minimum":1,"description":"ID of the automation."},"blockid":{"type":"integer","minimum":1,"description":"ID of the wait or goal block the contact is at."},"subscriberid":{"type":"integer","minimum":1,"description":"ID of the contact."},"runid":{"type":"integer","minimum":1,"description":"ID of the contact automation run."}}}}}}}}},"responses":{"200":{"description":"The per-run outcome. `succeeded` lists the run ids that moved past the wait. `failed` lists the run ids that did not, each with an `error`. A partial batch is still 200.","content":{"application/json":{"schema":{"type":"object","required":["succeeded","failed"],"properties":{"succeeded":{"type":"array","description":"Run ids that moved past the wait.","items":{"type":"integer"}},"failed":{"type":"array","description":"Runs that were not ended.","items":{"type":"object","required":["runid","error"],"properties":{"runid":{"type":"integer","description":"ID of the contact automation run."},"error":{"type":"string","description":"Why that run was not ended."}}}}}}}}},"403":{"description":"The user lacks the `pg_automation_manage` permission."},"422":{"description":"The body has no `items` list, an item is not an object, an id is missing or not a positive number, the list is empty, or it has more than 100 waits. The body is `{\"error\":\"...\"}`.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Why the batch was rejected."}}}}}}},"deprecated":false,"x-internal":true}},"/automation/check_waits":{"post":{"summary":"Check which waits a revision would remove","description":"Internal: backs the automation builder's revert flow. Before restoring a revision, lists the automation's current wait and goal blocks that have contacts on them and are not wait blocks in the revision's snapshot, so the user can decide where those contacts go. Changes nothing. Only POST is answered; any other method gets an empty 200 response. The fields are read from the query string or from a form-encoded body (query string wins); a JSON body is not read.","operationId":"check-automation-revision-waits","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer","description":"ID of the automation revision."}}}}}},"responses":{"200":{"description":"The blocks, with `success: 1` and `Waits checked successfully.`; or `success: 0` with `Invalid revision` when no revision has this ID.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationBuilderOutcome"},{"type":"object","properties":{"waits":{"type":["array","object"],"description":"IDs of the affected blocks. Encoded from an array that keeps its original keys, so it is a JSON list when those keys are 0..n-1 and otherwise an object whose values are the IDs.","items":{"type":["integer","string"]},"additionalProperties":{"type":["integer","string"]}}}}]}}}}},"deprecated":false,"x-internal":true}},"/automation/history_start_data":{"get":{"summary":"Retrieve how a contact entered an automation","description":"Internal: backs the contact's automation history view. Describes the start trigger through which one contact automation run began, including the deal that started it for deal-related triggers. The JSON body is sent without a JSON `Content-Type` header. Only GET is answered; any other method gets an empty 200 response.","operationId":"retrieve-automation-run-start-data","x-canonical-resource":"contactAutomations","parameters":[{"name":"automationRunId","in":"query","description":"ID of the contact automation run (contactAutomation).","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The start trigger data; or, when no run has this ID, the plain text `Invalid Automation Run`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRunStartData"}},"text/plain":{"schema":{"type":"string","description":"`Invalid Automation Run`."}}}}},"deprecated":false,"x-internal":true}},"/automation/position":{"post":{"summary":"Move a contact to another block of an automation","description":"Internal: backs the automation builder. Moves one active contact automation run to the given block: logs the contact at that block, makes it the run's current block (updating `lastdate`) and clears the run's completion date. A run that is not active is left alone. Requires the `pg_automation_manage` (manage automations) permission; without it the endpoint answers 200 with `success: 0` and the message \"You don't have permission to perform this action.\" Only POST is answered; any other method gets an empty 200 response. The fields are read from the query string or from a form-encoded body (query string wins); a JSON body is not read.","operationId":"move-contact-automation-position","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["csid","blockid"],"properties":{"csid":{"type":"integer","description":"ID of the contact automation run to move."},"blockid":{"type":"integer","description":"ID of the block to move the contact to."}}}}}},"responses":{"200":{"description":"`success: 1` with `Contact moved successfully.`; `success: 1` with `Contact cannot be moved because they have completed the automation.` when the run is not active (nothing is changed); `success: 0` with `Invalid automation or contact` when no run has this ID, or with the permission message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderOutcome"}}}}},"deprecated":false,"x-internal":true}},"/automation/queued_subscribers":{"get":{"summary":"Count contacts currently at an automation block","description":"Internal: backs the automation builder. Counts the active contact automation runs whose current block is the given block, for example contacts waiting at a wait step. Only GET is answered; any other method gets an empty 200 response.","operationId":"count-automation-block-queued-contacts","x-canonical-resource":"contactAutomations","parameters":[{"name":"block_id","in":"query","description":"ID of the automation block.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The count. A missing or unknown `block_id` counts 0.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","description":"Number of active runs at the block."}}},"example":{"count":3}}}}},"deprecated":false,"x-internal":true}},"/automation/revert":{"post":{"summary":"Restore an automation revision","description":"Internal: backs the automation builder's revert flow. Validates the revision, rebuilds the automation's blocks and triggers from its snapshot, applies the caller's decision for contacts at waits the revision removes (see `POST /automation/check_waits`) and records a new `revert_revision` snapshot. Requires the `pg_automation_manage` (manage automations) permission; without it the endpoint answers 200 with `success: 0` and the message \"You don't have permission to perform this action.\" Only POST is answered; any other method gets an empty 200 response. The fields are read from the query string or from a form-encoded body (query string wins); a JSON body is not read.","operationId":"revert-automation-revision","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer","description":"ID of the revision to restore."},"waits":{"type":"array","description":"What to do with the active contacts at each wait or goal block the revision removes, sent as form arrays (`waits[0][id]=12&waits[0][action]=exit`). Contacts at blocks not listed are not moved.","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the current wait or goal block."},"action":{"type":"string","enum":["exit","wait"],"description":"`exit` ends the contacts' runs; `wait` moves them to `destination`."},"destination":{"type":"integer","description":"With `wait`: ID, in the revision's snapshot, of the block to move the contacts to."}}}}}}}}},"responses":{"200":{"description":"`success: 1` with `Revert successful`; or `success: 0` with `Invalid revision`, with the validation failure (for example a trigger that revisions cannot restore, or triggers and actions the plan no longer includes), or with the permission message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderOutcome"}}}},"402":{"description":"The account's block-limit entitlement does not allow this automation revision or block. Raised as a block-limit error, so the body is the standard `errors` array rather than the `success`/`message` object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockLimitError"}}}}},"deprecated":false,"x-internal":true}},"/automation/search_goals":{"get":{"summary":"Search goals in other automations","description":"Internal: backs the automation builder's goal picker. Lists goal blocks of every automation except the given one whose \"<goal name> (<automation name>)\" label contains the search phrase, case-insensitively; goal blocks marked deleted are included. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses.","operationId":"search-automation-goals","x-canonical-resource":"automation","parameters":[{"name":"query","in":"query","description":"Phrase to match in the label. Empty or omitted matches every goal.","required":false,"schema":{"type":"string"}},{"name":"seriesid","in":"query","description":"ID of the automation to leave out, normally the one being edited.","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Labels keyed by goal block ID; an empty JSON array when nothing matches.","content":{"application/json":{"schema":{"type":["object","array"],"description":"Goal block ID → \"<goal name> (<automation name>)\".","additionalProperties":{"type":"string"},"maxItems":0},"example":{"3":"Series 2 Goal 1 (Automation Name 2)"}}}}},"deprecated":false,"x-internal":true}},"/automation/skip_wait":{"post":{"summary":"Skip a contact past a wait","description":"Internal: backs the contact automation views. Advances one contact automation run that is at a wait or goal block straight to the next block and processes it, as if the wait had ended. Name the run either with a JSON body or with a `logid` query or form field naming its log entry. Refused while the automation is inactive or paused, when the contact has ended the automation or is no longer at that block, or while another skip for the same run and block is in progress. Requires the `pg_automation_manage` (manage automations) permission; without it the endpoint answers 200 with `success: 0` and the message \"You don't have permission to perform this action.\" Legacy endpoint with no method guard: any HTTP method is answered the same way; POST is the documented verb and the one the app uses.","operationId":"skip-contact-automation-wait","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"logid","in":"query","description":"ID of the contact automation log entry for the run at the wait. Read only when there is no JSON body.","required":false,"schema":{"type":"integer"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","required":["seriesid","blockid","subscriberid","runid"],"properties":{"seriesid":{"type":"integer","description":"ID of the automation."},"blockid":{"type":"integer","description":"ID of the wait or goal block the contact is at."},"subscriberid":{"type":"integer","description":"ID of the contact."},"runid":{"type":"integer","description":"ID of the contact automation run."}}}}}},"responses":{"200":{"description":"The outcome. A refused skip has `succeeded: false` and a translated `error` (for example `Wait block is already being processed.`, or `Invalid subscriber series log` for an unknown `logid`); a missing permission has `success: 0` and `message` instead.","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":["boolean","integer"],"description":"Truthy when the contact was moved past the wait and processed."},"error":{"type":"string","description":"Why the skip was refused."},"success":{"type":"integer","description":"0, only with the permission message."},"message":{"type":"string","description":"The permission message."}}}}}}},"deprecated":false,"x-internal":true}},"/automation/validate_revision":{"get":{"summary":"Retrieve whether an automation revision is valid","description":"Internal: backs the automation builder's revision history. Validates one revision and reports why it cannot be restored, listing the triggers and actions that violate the plan's entitlements. A block-limit failure is reported in the body rather than as 402. No permission check. Answers GET and POST; any other method gets an empty 200 response.","operationId":"retrieve-automation-revision-validity","x-canonical-resource":"automation","parameters":[{"name":"id","in":"query","description":"ID of the automation revision.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The validity. An unknown `id` is reported as `valid: false` with the string error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRevisionValidity"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Validate an automation revision","description":"Internal: backs the automation builder's revert flow. Checks that one revision can be restored: within the block limit, no triggers or actions the plan no longer includes, intact segment data, no split test running, and no custom object trigger on a revision too old to support it. Changes nothing. Requires the `pg_automation_manage` (manage automations) permission; without it the endpoint answers 200 with `success: 0` and the message \"You don't have permission to perform this action.\" Answers GET and POST; any other method gets an empty 200 response. The fields are read from the query string or from a form-encoded body (query string wins); a JSON body is not read.","operationId":"validate-automation-revision","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer","description":"ID of the automation revision."}}}}}},"responses":{"200":{"description":"`success: 1` with `Revision is valid`; or `success: 0` with the validation failure and `allow_revert`, with `Invalid revision`, or with the permission message.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationBuilderOutcome"},{"type":"object","properties":{"allow_revert":{"type":"boolean","description":"Present when validation failed: whether the revision may still be restored."}}}]}}}},"402":{"description":"The account's block-limit entitlement does not allow this automation revision or block. Raised as a block-limit error, so the body is the standard `errors` array rather than the `success`/`message` object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationBuilderBlockLimitError"}}}}},"deprecated":false,"x-internal":true}},"/automationConnections":{"get":{"summary":"List how automations are linked to other automations","description":"For each automation in ids, the other automations it starts or ends and the ones that start or end it, worked out from every automation's blocks and start triggers at request time. An ID that matches no automation still gets a record, with empty arrays. Internal: used by the app.","operationId":"list-all-automation-connections","parameters":[{"name":"ids","in":"query","description":"Comma-separated automation IDs. Values that are not positive integers are dropped and duplicates are returned once. Send a single comma-separated value: the repeated ids[] form fails with 500.","required":true,"schema":{"type":"string"},"example":"12,87"}],"responses":{"200":{"description":"One record per requested automation","content":{"application/json":{"schema":{"properties":{"automationConnections":{"description":"The records, one per distinct ID","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsConnection"}},"meta":{"description":"Counts","properties":{"total":{"description":"Number of records returned","type":"integer","example":1}},"type":"object"}},"type":"object"},"example":{"automationConnections":[{"id":12,"automation":12,"connectionStarts":[{"triggers":[{"triggerId":"41","type":"addtag","action":"\"VIP\" tag"}],"connectedId":87,"connectedTitle":"VIP onboarding","connectedInactive":false,"status":"1","invalid":0}],"connectionIsStartedBy":[],"connectionStops":[],"connectionIsStoppedBy":[],"connectionInvalid":[],"links":{"automation":"https://:account.api-us1.com/api/:version/automationConnections/12/automation"}}],"meta":{"total":1}}}}},"400":{"description":"ids is missing or holds no positive integer. The body is empty."}},"x-canonical-resource":"automation","x-internal":true}},"/automationConnections/{id}":{"get":{"summary":"Retrieve how one automation is linked to other automations","description":"The other automations this automation starts or ends and the ones that start or end it, worked out from every automation's blocks and start triggers at request time. An ID that matches no automation returns a record with empty arrays; an ID that is not a positive integer fails with 500. Internal: used by the app.","operationId":"retrieve-an-automation-connection","parameters":[{"name":"id","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record","content":{"application/json":{"schema":{"properties":{"automationConnection":{"$ref":"#/components/schemas/AutomationConnectionsConnection"}},"type":"object"},"example":{"automationConnection":{"id":12,"automation":12,"connectionStarts":[{"triggers":[{"triggerId":"41","type":"addtag","action":"\"VIP\" tag"}],"connectedId":87,"connectedTitle":"VIP onboarding","connectedInactive":false,"status":"1","invalid":0}],"connectionIsStartedBy":[],"connectionStops":[],"connectionIsStoppedBy":[],"connectionInvalid":[],"links":{"automation":"https://:account.api-us1.com/api/:version/automationConnections/12/automation"}}}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automationConnections/{seriesId}/blocks":{"get":{"summary":"List the tag actions in an automation that start other automations","description":"A narrow form of GET /automationConnections/{id}: only this automation's Add a tag and Remove a tag actions are checked, against the other automations' Tag is added and Tag is removed start triggers, and matches are listed under connectionStarts. The other arrays are always empty. An automation that does not exist returns a record with empty arrays. Internal: used by the automation builder.","operationId":"list-automation-block-connections","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"A list holding the automation's one record","content":{"application/json":{"schema":{"properties":{"automationConnections":{"description":"The automation's record","type":"array","items":{"$ref":"#/components/schemas/AutomationConnectionsConnection"}},"meta":{"description":"Counts","properties":{"total":{"description":"Always 1","type":"integer","example":1}},"type":"object"}},"type":"object"},"example":{"automationConnections":[{"id":12,"automation":12,"connectionStarts":[{"triggers":[{"triggerId":"41","type":"addtag","action":"\"VIP\" tag"}],"connectedId":87,"connectedTitle":"VIP onboarding","connectedInactive":false,"status":"1","invalid":0}],"connectionIsStartedBy":[],"connectionStops":[],"connectionIsStoppedBy":[],"connectionInvalid":[],"links":{"automation":"https://:account.api-us1.com/api/:version/automationConnections/12/automation"}}],"meta":{"total":1}}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automationGroups":{"post":{"summary":"Grant a user group access to an automation","description":"Creates one automation group record: it lets the users of one user group see and work with one automation. Users outside the account's main admin group only see automations granted to one of their groups; main-group users see every automation. Only a user in the main admin group may call this. Nothing in the body is checked: the automation and the user group are not looked up, a second record for a pair that is already granted is created rather than refused, and a body without automationGroup, or without automation or group, saves a record with 0 in the missing column. Internal: used by the app.","operationId":"create-an-automation-group-permission","requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"automationGroup":{"description":"The grant to create","properties":{"automation":{"description":"ID of the automation the user group may access. Not checked.","type":"integer","example":12},"group":{"description":"ID of the user group that gets access. Not checked.","type":"integer","example":4}},"type":"object"}},"type":"object"},"example":{"automationGroup":{"automation":12,"group":4}}}}},"responses":{"201":{"description":"The grant was created. The record is not read back: automation and group are echoed as sent.","content":{"application/json":{"schema":{"properties":{"automationGroup":{"description":"The new automation group record","properties":{"automation":{"description":"ID of the automation, as sent; null when it was sent as 0","type":["integer","string","null"],"example":12},"group":{"description":"ID of the user group, as sent; null when it was sent as 0","type":["integer","string","null"],"example":4},"cdate":{"description":"When the record was created, in ISO 8601","type":"string","example":"2026-10-15T10:52:26-05:00"},"links":{"description":"URLs of the record's related reads","properties":{"automation":{"description":"URL that returns the automation, GET /automationGroups/{id}/automation","type":"string","example":"https://:account.api-us1.com/api/:version/automationGroups/5/automation"},"group":{"description":"URL that returns the user group, GET /automationGroups/{id}/group","type":"string","example":"https://:account.api-us1.com/api/:version/automationGroups/5/group"}},"type":"object"},"id":{"description":"ID of the new automation group record","type":"string","example":"5"}},"type":"object"}},"type":"object"},"example":{"automationGroup":{"automation":12,"group":4,"cdate":"2026-10-15T10:52:26-05:00","links":{"automation":"https://:account.api-us1.com/api/:version/automationGroups/5/automation","group":"https://:account.api-us1.com/api/:version/automationGroups/5/group"},"id":"5"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What was wrong with the body","type":"string","example":"Request body must be a JSON object, array given."}},"type":"object"}}},"type":"object"}}}},"403":{"description":"The user is not in the account's main admin group.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"500":{"description":"The database refused the record.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Could not process request\"","type":"string","example":"Could not process request"},"error":{"description":"Always \"Error while processing request\"","type":"string","example":"Error while processing request"}},"type":"object"}}}}},"x-canonical-resource":"automation_group","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"List automation group permissions","description":"Lists automation group records, each granting one user group access to one automation. Any user may call this; no record is hidden from users outside the main admin group. Internal: used by the app.","operationId":"list-all-automation-group-permissions","x-canonical-resource":"automation_group","parameters":[{"name":"filters[seriesid]","in":"query","description":"Return only the records of this automation. This is the value the response returns as automation.","schema":{"type":"integer","format":"int32"}},{"name":"filters[groupid]","in":"query","description":"Return only the records of this user group. This is the value the response returns as group.","schema":{"type":"integer","format":"int32"}},{"name":"orders[seriesid]","in":"query","description":"Order by automation ID. Any value other than desc, in any case, orders ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[groupid]","in":"query","description":"Order by user group ID. Any value other than desc, in any case, orders ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"ids","in":"query","description":"Comma-separated IDs of the automation group records to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Comma-separated relationships to add to the response: automation adds an automations array, group adds a groups array. Unknown names are ignored.","schema":{"type":"string","example":"automation,group"}},{"name":"limit","in":"query","description":"Number of records to return. Default 20, maximum 100; a larger number returns 100, and the string null returns up to 1000.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Number of records to skip, for paging.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"The records, and the total that match","content":{"application/json":{"schema":{"type":"object","properties":{"automationGroups":{"type":"array","description":"The records on this page","items":{"$ref":"#/components/schemas/AutomationGroup"}},"automations":{"type":"array","description":"The automations the records point to. Present only with include=automation and at least one record.","items":{"type":"object"}},"groups":{"type":"array","description":"The user groups the records point to. Present only with include=group and at least one record.","items":{"type":"object"}},"meta":{"type":"object","description":"Paging information","properties":{"total":{"type":"integer","description":"Number of records that match, across all pages","example":1}}}}},"example":{"automationGroups":[{"automation":"12","group":"4","cdate":"2026-10-15T10:52:26-05:00","links":{"automation":"https://:account.api-us1.com/api/:version/automationGroups/5/automation","group":"https://:account.api-us1.com/api/:version/automationGroups/5/group"},"id":"5"}],"meta":{"total":1}}}}}},"x-internal":true}},"/automationGroups/bulkCreate":{"post":{"summary":"Grant user groups access to automations in bulk","description":"Creates one automation group record per entry, each letting the users of one user group see and work with one automation. Entries are processed in order and each automation and user group is looked up first; at the first one that does not exist the records already created by this request are deleted again and the response is HTTP 200 with an error body, not a 4xx. Pairs that are already granted are not detected, so repeating a pair creates a second record. The entries use the column names seriesid and groupid, not the automation and group keys of POST /automationGroups. Unlike POST /automationGroups this call does not require the main admin group. A body without automationGroups, or an entry without seriesid or groupid, fails with 500. Internal: used by the app.","operationId":"bulk-create-automation-group-permissions","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["automationGroups"],"properties":{"automationGroups":{"description":"The grants to create. An empty list creates nothing.","type":"array","items":{"required":["seriesid","groupid"],"properties":{"seriesid":{"description":"ID of the automation the user group may access. Must exist.","type":"integer","example":12},"groupid":{"description":"ID of the user group that gets access. Must exist.","type":"integer","example":4}},"type":"object"}}},"type":"object"},"example":{"automationGroups":[{"seriesid":12,"groupid":4},{"seriesid":12,"groupid":7}]}}}},"responses":{"200":{"description":"Either every grant was created, and automationGroups lists them, or an automation or user group did not exist, nothing was kept, and error says which.","content":{"application/json":{"schema":{"oneOf":[{"description":"Every grant was created","properties":{"automationGroups":{"description":"The records created, in request order. They carry no id: the record ids are not returned.","type":"array","items":{"properties":{"seriesid":{"description":"ID of the automation, as sent","type":["integer","string"],"example":12},"groupid":{"description":"ID of the user group, as sent","type":["integer","string"],"example":4},"cdate":{"description":"When the record was created, as YYYY-MM-DD HH:MM:SS","type":"string","example":"2026-10-15 10:52:26"}},"type":"object"}}},"type":"object"},{"description":"The request was refused","properties":{"error":{"description":"\"Invalid seriesid\" when an automation does not exist, \"Invalid groupid\" when a user group does not exist","type":"string","example":"Invalid seriesid"}},"type":"object"}]},"example":{"automationGroups":[{"seriesid":12,"groupid":4,"cdate":"2026-10-15 10:52:26"},{"seriesid":12,"groupid":7,"cdate":"2026-10-15 10:52:26"}]}}}},"500":{"description":"The body has no automationGroups list, an entry is missing seriesid or groupid or has one that is not a number, or the database refused a record. Records created before a database failure are kept.","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"Could not process request\" when the database refused a record, otherwise \"Something went wrong on our end. Please try again later\"","type":"string","example":"Something went wrong on our end. Please try again later"},"error":{"description":"Present only when the database refused a record: \"Error while processing request\"","type":"string","example":"Error while processing request"}},"type":"object"}}}}},"x-canonical-resource":"automation_group","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/automationGroups/bulkUpdate":{"put":{"summary":"Replace the user groups that can access an automation","description":"Sets the full list of user groups that may see and work with one automation. In one transaction it deletes every automation group record of the automation except those for the main admin group (user group 3), checks that the automation and each user group exist, and creates one record per entry of groupids. Records for the main admin group are kept and are not returned; listing the main admin group in groupids adds another record for it, and repeated ids are not merged. An empty groupids leaves the automation with only its main admin group records. Every failure, including a missing field and a database error, is answered with HTTP 200 and an error body, and the transaction is rolled back. Unlike POST and DELETE /automationGroups this call does not require the main admin group. Internal: used by the app.","operationId":"bulk-update-automation-group-permissions","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["seriesid","groupids"],"properties":{"seriesid":{"description":"ID of the automation whose user groups are replaced. Must exist.","type":"integer","example":12},"groupids":{"description":"IDs of the user groups that should have access, other than the main admin group. Each must exist.","type":"array","items":{"type":"integer"},"example":[4,7]}},"type":"object"},"example":{"seriesid":12,"groupids":[4,7]}}}},"responses":{"200":{"description":"Either the user groups were replaced, and automationGroups lists the records created, or the request was refused or failed, nothing changed, and error says why.","content":{"application/json":{"schema":{"oneOf":[{"description":"The user groups were replaced","properties":{"automationGroups":{"description":"The records created, one per entry of groupids, in that order. They carry no id: the record ids are not returned.","type":"array","items":{"properties":{"seriesid":{"description":"ID of the automation","type":"integer","example":12},"groupid":{"description":"ID of the user group","type":"integer","example":4},"cdate":{"description":"When the record was created, as YYYY-MM-DD HH:MM:SS","type":"string","example":"2026-10-15 10:52:26"}},"type":"object"}}},"type":"object"},{"description":"The request was refused","properties":{"error":{"description":"What was wrong. One of: \"Missing required property: seriesid\", \"Missing required property: groupids\", \"groupids must be an array\", \"Invalid seriesid: <id>\", \"Invalid groupid: <id>\", or a message starting \"Failed to delete existing series-group associations: \" or \"Database error during bulk update: \".","type":"string","example":"Invalid groupid: 9"}},"type":"object"}]},"example":{"automationGroups":[{"seriesid":12,"groupid":4,"cdate":"2026-10-15 10:52:26"},{"seriesid":12,"groupid":7,"cdate":"2026-10-15 10:52:26"}]}}}}},"x-canonical-resource":"automation_group","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/automationGroups/{id}":{"delete":{"summary":"Remove a user group's access to an automation","description":"Deletes one automation group record, so the users of that user group who are outside the main admin group no longer see the automation through it. The automation and the user group themselves are not changed. Only a user in the main admin group may call this; that is checked before the record is looked up. Internal: used by the app.","operationId":"delete-an-automation-group-permission","parameters":[{"name":"id","in":"path","description":"ID of the automation group record","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record was deleted. The body is an empty object.","content":{"application/json":{"schema":{"description":"Empty object","type":"object"},"example":{}}}},"403":{"description":"The user is not in the account's main admin group. In the rare case that the delete itself fails, the status is also 403 and the body is a plain-text failure message instead.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No automation group record has this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string","example":"No Result found for SeriesGroup with id 5"}},"type":"object"}}}}},"x-canonical-resource":"automation_group","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"Retrieve an automation group permission","description":"Returns one automation group record, the grant of one user group's access to one automation. Internal: used by the app.","operationId":"retrieve-an-automation-group-permission","x-canonical-resource":"automation_group","parameters":[{"name":"id","in":"path","description":"ID of the automation group record","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record","content":{"application/json":{"schema":{"type":"object","properties":{"automationGroup":{"$ref":"#/components/schemas/AutomationGroup"}}},"example":{"automationGroup":{"automation":"12","group":"4","cdate":"2026-10-15T10:52:26-05:00","links":{"automation":"https://:account.api-us1.com/api/:version/automationGroups/5/automation","group":"https://:account.api-us1.com/api/:version/automationGroups/5/group"},"id":"5"}}}}},"404":{"description":"No automation group record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesGroup with id 5"}}}}}}},"x-internal":true},"put":{"summary":"Update an automation group permission","description":"Changes one automation group record in place: automation moves the grant to another automation and group gives it to another user group. PATCH /automationGroups/{id} does the same thing. Unlike POST and DELETE /automationGroups, this call does not require the main admin group. Nothing in the body is checked: the automation and the user group are not looked up and a pair that is already granted is not detected. Fields left out keep their value, any key in automationGroup other than these two and the column names seriesid and groupid is ignored, and a body without automationGroup changes nothing and still returns 200. The record is not read back: the response is the stored record with the changed values as sent. Internal: used by the app.","operationId":"update-an-automation-group-permission","x-canonical-resource":"automation_group","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the automation group record to change","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationGroup":{"type":"object","description":"The fields to change","properties":{"automation":{"type":"integer","description":"ID of the automation to grant access to instead. Not checked.","example":12},"group":{"type":"integer","description":"ID of the user group to grant access to instead. Not checked.","example":7}}}}},"example":{"automationGroup":{"group":7}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"automationGroup":{"$ref":"#/components/schemas/AutomationGroup"}}},"example":{"automationGroup":{"automation":"12","group":7,"cdate":"2026-10-15T10:52:26-05:00","links":{"automation":"https://:account.api-us1.com/api/:version/automationGroups/5/automation","group":"https://:account.api-us1.com/api/:version/automationGroups/5/group"},"id":"5"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No automation group record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesGroup with id 5"}}}}}},"500":{"description":"The database refused the change.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Could not process request\"","example":"Could not process request"},"error":{"type":"string","description":"Always \"Error while processing request\"","example":"Error while processing request"}}}}}}},"x-internal":true},"patch":{"summary":"Update an automation group permission (PATCH)","description":"Changes one automation group record in place: automation moves the grant to another automation and group gives it to another user group. PUT /automationGroups/{id} does the same thing. Unlike POST and DELETE /automationGroups, this call does not require the main admin group. Nothing in the body is checked: the automation and the user group are not looked up and a pair that is already granted is not detected. Fields left out keep their value, any key in automationGroup other than these two and the column names seriesid and groupid is ignored, and a body without automationGroup changes nothing and still returns 200. The record is not read back: the response is the stored record with the changed values as sent. Internal: used by the app.","operationId":"patch-an-automation-group-permission","x-canonical-resource":"automation_group","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the automation group record to change","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationGroup":{"type":"object","description":"The fields to change","properties":{"automation":{"type":"integer","description":"ID of the automation to grant access to instead. Not checked.","example":12},"group":{"type":"integer","description":"ID of the user group to grant access to instead. Not checked.","example":7}}}}},"example":{"automationGroup":{"group":7}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"automationGroup":{"$ref":"#/components/schemas/AutomationGroup"}}},"example":{"automationGroup":{"automation":"12","group":7,"cdate":"2026-10-15T10:52:26-05:00","links":{"automation":"https://:account.api-us1.com/api/:version/automationGroups/5/automation","group":"https://:account.api-us1.com/api/:version/automationGroups/5/group"},"id":"5"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No automation group record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesGroup with id 5"}}}}}},"500":{"description":"The database refused the change.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Could not process request\"","example":"Could not process request"},"error":{"type":"string","description":"Always \"Error while processing request\"","example":"Error while processing request"}}}}}}},"x-internal":true}},"/automationLabels":{"post":{"summary":"Add a label to an automation","description":"Creates one automation label record, which attaches one label to one automation. An automation label is the association, not the label: labels themselves are managed under /labels and are shared with campaigns, forms and conversions. The label must exist and must not be an archived initiative, and the automation must exist; they are checked in that order. If the automation already has the label, nothing is created and the response is HTTP 200 with a message instead of the record. Internal: used by the app.","operationId":"create-an-automation-label","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["automationLabel"],"properties":{"automationLabel":{"description":"The association to create","required":["automation","label"],"properties":{"automation":{"description":"ID of the automation to label","type":"integer","example":12},"label":{"description":"ID of the label to attach","type":"integer","example":3}},"type":"object"}},"type":"object"},"example":{"automationLabel":{"automation":12,"label":3}}}}},"responses":{"200":{"description":"The automation already has this label. Nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says which automation and label are already associated","type":"string","example":"SeriesFolder with series id 12 and folder id 3 already exists"}},"type":"object"}}}},"201":{"description":"The label was attached. The record is not read back: automation and label are echoed as sent, and the timestamp and user columns are absent.","content":{"application/json":{"schema":{"properties":{"automationLabel":{"description":"The new automation label record","properties":{"automation":{"description":"ID of the automation, as sent","type":["integer","string"],"example":12},"label":{"description":"ID of the label, as sent","type":["integer","string"],"example":3},"links":{"description":"URLs of the record's related reads","properties":{"labels":{"description":"URL of GET /automationLabels/{id}/labels","type":"string","example":"https://:account.api-us1.com/api/:version/automationLabels/7/labels"},"series":{"description":"URL of GET /automationLabels/{id}/series","type":"string","example":"https://:account.api-us1.com/api/:version/automationLabels/7/series"}},"type":"object"},"id":{"description":"ID of the new automation label record. Pass it to DELETE /automationLabels/{id} to take the label off the automation.","type":"string","example":"7"}},"type":"object"}},"type":"object"},"example":{"automationLabel":{"automation":12,"label":3,"links":{"labels":"https://:account.api-us1.com/api/:version/automationLabels/7/labels","series":"https://:account.api-us1.com/api/:version/automationLabels/7/series"},"id":"7"}}}}},"400":{"description":"automationLabel is missing, automation or label is missing or not a number, or the body is JSON but not an object.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What was wrong. One of: \"An automation label must be provided\", \"A automation id must be provided\", \"A folder or label id must be provided\", \"Request body must be a JSON object, <type> given.\"","type":"string","example":"An automation label must be provided"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"An automation label must be provided"}]}}}},"403":{"description":"The label is an archived initiative.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 3 is archived and cannot have automations associated with it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 3 is archived and cannot have automations associated with it."}]}}}},"404":{"description":"The label does not exist, or the automation does not exist.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string","example":"No Result found for Folder with id 3"}},"type":"object"}}}}},"x-canonical-resource":"automation_label","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"List automation labels","description":"Lists automation label records, each attaching one label to one automation. The resource has no filters: filters[...] and orders[...] are accepted but ignored, so this cannot list the labels of one automation; page through the records or pass ids. Internal: used by the app.","operationId":"list-automation-labels","x-canonical-resource":"automation_label","parameters":[{"name":"include_folder","in":"query","description":"When 1, adds the label's name as title and its color to each record, and leaves out records whose label no longer exists; meta.total leaves them out too.","schema":{"type":"integer","enum":[0,1]}},{"name":"ids","in":"query","description":"Comma-separated IDs of the automation label records to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of records to return. Default 20, maximum 100; a larger number returns 100, and the string null returns up to 1000.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Number of records to skip, for paging.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"The records, and the total that match","content":{"application/json":{"schema":{"type":"object","properties":{"automationLabels":{"type":"array","description":"The records on this page","items":{"$ref":"#/components/schemas/AutomationLabel"}},"meta":{"type":"object","description":"Paging information","properties":{"total":{"type":"integer","description":"Number of records that match, across all pages","example":1}}}}},"example":{"automationLabels":[{"automation":"12","label":"3","created_timestamp":"2026-10-15 10:52:26","updated_timestamp":"2026-10-15 10:52:26","created_by":null,"updated_by":null,"links":{"labels":"https://:account.api-us1.com/api/:version/automationLabels/7/labels","series":"https://:account.api-us1.com/api/:version/automationLabels/7/series"},"id":"7","title":"Onboarding","color":"edf0f7"}],"meta":{"total":1}}}}}},"x-internal":true}},"/automationLabels/bulkCreate":{"post":{"summary":"Add labels to automations in bulk","description":"Attaches labels to automations, one association per entry, in a single insert. The body is a bare JSON array, not wrapped in a key. Every label named is checked first: a label that does not exist fails the whole request with 404 and an archived initiative fails it with 403, before anything is inserted. Then entries without a numeric automation or label are reported in errors, and entries that repeat an earlier pair in the request, name an automation that does not exist, or are already associated are skipped without an error. Internal: used by the app.","operationId":"bulk-create-automation-labels","requestBody":{"required":true,"content":{"application/json":{"schema":{"description":"The associations to create","type":"array","items":{"required":["automation","label"],"properties":{"automation":{"description":"ID of the automation to label","type":"integer","example":12},"label":{"description":"ID of the label to attach","type":"integer","example":3}},"type":"object"}},"example":[{"automation":12,"label":3},{"automation":14,"label":3}]}}},"responses":{"200":{"description":"Nothing was created: the body was empty, or no entry was left to insert.","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"No data provided\" for an empty body, otherwise \"No valid labels provided\"","type":"string","example":"No valid labels provided"},"errors":{"description":"The refused entries, as in the 201 response. Absent for an empty body.","type":"array","items":{"properties":{"index":{"description":"Position of the refused entry in the request array, from 0","type":"integer","example":0},"error":{"description":"\"A automation id must be provided\" or \"A folder or label id must be provided\"","type":"string","example":"A folder or label id must be provided"}},"type":"object"}},"meta":{"description":"Outcome flags","properties":{"success":{"description":"True when no entry was refused, false otherwise","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"message":"No valid labels provided","errors":[],"meta":{"success":true}}}}},"201":{"description":"At least one association was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Labels created successfully\"","type":"string","example":"Labels created successfully"},"added":{"description":"Number of associations created","type":"integer","example":2},"errors":{"description":"One entry per request entry that was refused; empty when none was","type":"array","items":{"properties":{"index":{"description":"Position of the refused entry in the request array, from 0","type":"integer","example":1},"error":{"description":"\"A automation id must be provided\" or \"A folder or label id must be provided\"","type":"string","example":"A automation id must be provided"}},"type":"object"}},"meta":{"description":"Outcome flags","properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"message":"Labels created successfully","added":2,"errors":[],"meta":{"success":true}}}}},"403":{"description":"A label in the request is an archived initiative. Nothing was created.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 3 is archived and cannot have automations associated with it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 3 is archived and cannot have automations associated with it."}]}}}},"404":{"description":"A label in the request does not exist. Nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string","example":"No Result found for Folder with id 3"}},"type":"object"}}}},"500":{"description":"The insert failed. A label that is not a number also fails with 500, with the generic body {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says the insert failed","type":"string","example":"Error creating labels - unable to insert new labels in rel table"},"errors":{"description":"The refused entries, as in the 201 response","type":"array","items":{"properties":{"index":{"description":"Position of the refused entry in the request array, from 0","type":"integer","example":0},"error":{"description":"\"A automation id must be provided\" or \"A folder or label id must be provided\"","type":"string","example":"A folder or label id must be provided"}},"type":"object"}},"meta":{"description":"Outcome flags","properties":{"success":{"description":"Always false","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"automation_label","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/automationLabels/bulkDelete":{"delete":{"summary":"Remove labels from automations in bulk","description":"Deletes the automation label records named in the ids query parameter, taking those labels off their automations. Every record is checked before anything is deleted: an ID that is not an automation label record, or whose label no longer exists, fails the whole request with 404, and a record whose label is an archived initiative fails it with 403. Without ids nothing is deleted. Internal: used by the app.","operationId":"bulk-delete-automation-labels","parameters":[{"name":"ids","in":"query","description":"Comma-separated IDs of the automation label records to delete, not label IDs. The repeated ids[] form is not accepted and fails with 500.","required":false,"schema":{"type":"string"},"example":"7,8,9"}],"responses":{"200":{"description":"The records were deleted, or ids was empty or missing and nothing was deleted.","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"Labels deleted successfully\", or \"Nothing to delete\" when ids is empty or missing","type":"string","example":"Labels deleted successfully"},"meta":{"description":"Outcome flags","properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"message":"Labels deleted successfully","meta":{"success":true}}}}},"403":{"description":"A record's label is an archived initiative. Nothing was deleted.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 3 is archived and cannot have automations removed from it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 3 is archived and cannot have automations removed from it."}]}}}},"404":{"description":"An ID is not an automation label record, or a record's label no longer exists. Nothing was deleted.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string","example":"No Result found for SeriesFolder with id 9"}},"type":"object"}}}},"500":{"description":"The delete failed.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Why the delete failed","type":"string","example":"Error deleting labels - unable to delete labels from rel table"},"meta":{"description":"Outcome flags","properties":{"success":{"description":"Always false","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"automation_label","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/automationLabels/{id}":{"delete":{"summary":"Remove a label from an automation","description":"Deletes one automation label record, taking the label off the automation. The label and the automation themselves are not changed. Refused when the label is an archived initiative. Internal: used by the app.","operationId":"delete-an-automation-label","parameters":[{"name":"id","in":"path","description":"ID of the automation label record, not the label ID","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The association was deleted. The body is an empty object.","content":{"application/json":{"schema":{"description":"Empty object","type":"object"},"example":{}}}},"403":{"description":"The label is an archived initiative. In the rare case that the delete itself fails, the status is also 403 and the body is a plain-text failure message instead.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 3 is archived and cannot have automations removed from it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 3 is archived and cannot have automations removed from it."}]}}}},"404":{"description":"No automation label record has this ID, or the label it points to no longer exists.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string","example":"No Result found for SeriesFolder with id 7"}},"type":"object"}}}}},"x-canonical-resource":"automation_label","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"Retrieve an automation label","description":"Returns one automation label record, the association of one label with one automation. Internal: used by the app.","operationId":"retrieve-an-automation-label","x-canonical-resource":"automation_label","parameters":[{"name":"id","in":"path","description":"ID of the automation label record, not the label ID","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record","content":{"application/json":{"schema":{"type":"object","properties":{"automationLabel":{"$ref":"#/components/schemas/AutomationLabel"}}},"example":{"automationLabel":{"automation":"12","label":"3","created_timestamp":"2026-10-15 10:52:26","updated_timestamp":"2026-10-15 10:52:26","created_by":null,"updated_by":null,"links":{"labels":"https://:account.api-us1.com/api/:version/automationLabels/7/labels","series":"https://:account.api-us1.com/api/:version/automationLabels/7/series"},"id":"7"}}}}},"404":{"description":"No automation label record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesFolder with id 7"}}}}}}},"x-internal":true},"put":{"summary":"Update an automation label","description":"Changes one automation label record in place: automation moves the association to another automation and label points it at another label. PATCH /automationLabels/{id} does the same thing. To relabel an automation, prefer DELETE /automationLabels/{id} and then POST /automationLabels: unlike those, this call checks nothing in the body. The automation and the label are not looked up, an archived initiative is not refused, and an association that already exists is not detected. Fields left out keep their value, any key in automationLabel other than these two and the column names seriesid and folderid is ignored, and a body without automationLabel changes nothing and still returns 200. The record is not read back: the response is the stored record with the changed values as sent. Internal: used by the app.","operationId":"update-an-automation-label","x-canonical-resource":"automation_label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the automation label record to change, not the label ID","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationLabel":{"type":"object","description":"The fields to change","properties":{"automation":{"type":"integer","description":"ID of the automation to move the association to. Not checked.","example":12},"label":{"type":"integer","description":"ID of the label to point the association at. Not checked.","example":5}}}}},"example":{"automationLabel":{"label":5}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"automationLabel":{"$ref":"#/components/schemas/AutomationLabel"}}},"example":{"automationLabel":{"automation":"12","label":5,"created_timestamp":"2026-10-15 10:52:26","updated_timestamp":"2026-10-15 10:52:26","created_by":null,"updated_by":null,"links":{"labels":"https://:account.api-us1.com/api/:version/automationLabels/7/labels","series":"https://:account.api-us1.com/api/:version/automationLabels/7/series"},"id":"7"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No automation label record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesFolder with id 7"}}}}}},"500":{"description":"The database refused the change.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Could not process request\"","example":"Could not process request"},"error":{"type":"string","description":"Always \"Error while processing request\"","example":"Error while processing request"}}}}}}},"x-internal":true},"patch":{"summary":"Update an automation label (PATCH)","description":"Changes one automation label record in place: automation moves the association to another automation and label points it at another label. PUT /automationLabels/{id} does the same thing. To relabel an automation, prefer DELETE /automationLabels/{id} and then POST /automationLabels: unlike those, this call checks nothing in the body. The automation and the label are not looked up, an archived initiative is not refused, and an association that already exists is not detected. Fields left out keep their value, any key in automationLabel other than these two and the column names seriesid and folderid is ignored, and a body without automationLabel changes nothing and still returns 200. The record is not read back: the response is the stored record with the changed values as sent. Internal: used by the app.","operationId":"patch-an-automation-label","x-canonical-resource":"automation_label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the automation label record to change, not the label ID","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationLabel":{"type":"object","description":"The fields to change","properties":{"automation":{"type":"integer","description":"ID of the automation to move the association to. Not checked.","example":12},"label":{"type":"integer","description":"ID of the label to point the association at. Not checked.","example":5}}}}},"example":{"automationLabel":{"label":5}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"automationLabel":{"$ref":"#/components/schemas/AutomationLabel"}}},"example":{"automationLabel":{"automation":"12","label":5,"created_timestamp":"2026-10-15 10:52:26","updated_timestamp":"2026-10-15 10:52:26","created_by":null,"updated_by":null,"links":{"labels":"https://:account.api-us1.com/api/:version/automationLabels/7/labels","series":"https://:account.api-us1.com/api/:version/automationLabels/7/series"},"id":"7"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No automation label record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesFolder with id 7"}}}}}},"500":{"description":"The database refused the change.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Could not process request\"","example":"Could not process request"},"error":{"type":"string","description":"Always \"Error while processing request\"","example":"Error while processing request"}}}}}}},"x-internal":true}},"/automationRelations/{automationId}/tracking":{"get":{"summary":"Retrieve what an automation tracks","description":"Returns the conversions and business goals an automation is set to track, each with how many of the automation's contacts have completed it. A business goal lists its figures per conversion it contains. An automation that tracks nothing, or does not exist, returns two empty arrays. Internal: backs the tracking panel of the automation builder.","operationId":"retrieve-automation-tracking-relations","parameters":[{"name":"automationId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"What the automation tracks","content":{"application/json":{"schema":{"properties":{"conversions":{"description":"Conversions the automation tracks. The conversion is returned as its stored row, so numbers are strings and dates are `Y-m-d H:i:s` values.","type":"array","items":{"properties":{"id":{"description":"ID of the conversion","type":"string","example":"7"},"name":{"description":"Name of the conversion","type":"string","example":"Purchased a plan"},"value":{"description":"Value of one conversion","type":"string","example":"0"},"currency":{"description":"Three-letter currency code of the value","type":"string"},"attributionData":{"description":"How the automation's contacts did against the conversion","properties":{"convertedTotal":{"description":"Contacts who entered the automation and completed the conversion","type":"integer","example":12},"percentage":{"description":"convertedTotal as a percentage of the contacts who entered the automation; 0 when none entered","type":"number","example":24}},"type":"object"}},"type":"object","additionalProperties":true}},"initiatives":{"description":"Business goals the automation tracks, returned as their stored label rows (numbers as strings).","type":"array","items":{"properties":{"id":{"description":"ID of the business goal","type":"string","example":"3"},"folder":{"description":"Name of the business goal","type":"string","example":"Grow trial conversions"},"is_initiative":{"description":"1 when the label is a business goal","type":"string","example":"1"},"attributionData":{"description":"The figures for each conversion in the business goal, keyed by conversion ID, each with `convertedTotal` and `percentage` as for a tracked conversion. An empty array when the goal has no conversions.","type":"array","items":{},"additionalProperties":{"properties":{"convertedTotal":{"description":"Contacts who entered the automation and completed the conversion","type":"integer"},"percentage":{"description":"convertedTotal as a percentage of the contacts who entered the automation","type":"number"}},"type":"object"}}},"type":"object","additionalProperties":true}}},"type":"object"},"example":{"conversions":[{"id":"7","name":"Purchased a plan","value":"0","attributionData":{"convertedTotal":12,"percentage":24}}],"initiatives":[]}}}}},"x-canonical-resource":"automation","x-internal":true},"put":{"summary":"Set what an automation tracks","description":"Makes the automation track exactly one conversion or one business goal: every conversion and business goal it tracked before is removed and the one in the body is added, in one transaction. The automation and the conversion or business goal are not looked up. Internal: backs the tracking panel of the automation builder.","operationId":"update-automation-tracking-relation","parameters":[{"name":"automationId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRelationsTrackingRequest"},"example":{"relationType":"conversion","relationId":7}}}},"responses":{"200":{"description":"The automation now tracks the record in the body","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}}}},"400":{"description":"The body is empty or is not JSON. Body: an `errors` array."},"422":{"description":"relationType or relationId is missing or has the wrong type, relationType is not conversion or initiative, or the relation could not be saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused attribute","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":422},"title":{"description":"Always the same text","type":"string","example":"Invalid attribute"},"detail":{"description":"What was wrong","type":"string","example":"Invalid relation type"},"source":{"description":"The attribute that was refused","properties":{"pointer":{"description":"JSON pointer to the attribute","type":"string","example":"/data/attributes/relationType"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Stop an automation tracking anything","description":"Removes every conversion and business goal the automation tracks, in one transaction. The conversions and business goals themselves are not changed. An automation that tracks nothing, or does not exist, also returns success. Internal: backs the tracking panel of the automation builder.","operationId":"delete-automation-tracking-relations","parameters":[{"name":"automationId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The automation tracks nothing","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}}}},"422":{"description":"The relations could not be deleted.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused attribute","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":422},"title":{"description":"Always the same text","type":"string","example":"Invalid attribute"},"detail":{"description":"What was wrong","type":"string","example":"Failed to delete the relation(s)"},"source":{"description":"The attribute that was refused","properties":{"pointer":{"description":"JSON pointer to the attribute","type":"string","example":"/data/attributes/automationId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/automationStarts":{"get":{"summary":"List automation start triggers","description":"Lists start triggers, the events that enter contacts into automations, across all of the account's automations or, with filters[seriesid], for one automation. The response key is automationTriggers, not automationStarts. Internal: used by the app.","operationId":"list-all-automation-triggers","x-canonical-resource":"automation","parameters":[{"name":"filters[seriesid]","in":"query","description":"Return only the triggers of this automation","schema":{"type":"integer"},"example":12},{"name":"orders[seriesid]","in":"query","description":"Order by automation ID. Any value other than desc, in any case, orders ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"ids","in":"query","description":"Comma-separated IDs of the triggers to return. Overrides limit; offset still applies.","schema":{"type":"string"},"example":"55,56"},{"name":"limit","in":"query","description":"Number of triggers to return. Default 20, maximum 100; a larger number returns 100, and the string null returns up to 1000.","schema":{"type":"integer","default":20}},{"name":"offset","in":"query","description":"Number of triggers to skip, for paging.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The triggers on this page, and the total that match","content":{"application/json":{"schema":{"type":"object","properties":{"automationTriggers":{"type":"array","description":"The triggers on this page","items":{"$ref":"#/components/schemas/AutomationStartsTrigger"}},"meta":{"type":"object","description":"Paging information","properties":{"total":{"type":"integer","description":"Number of triggers that match, across all pages","example":1}}}}},"example":{"automationTriggers":[{"seriesid":"12","segmentid":"0","multientry":"0","type":"tagadd","relid":"0","params":{"tag":"triggertag"},"cdate":"2026-10-15T10:52:26-05:00","mdate":"2026-10-15T10:52:26-05:00","links":[],"id":"55"}],"meta":{"total":1}}}}}},"x-internal":true},"post":{"summary":"Create or update an automation start trigger","description":"Saves one start trigger of an automation through the automation builder's block save: startid 0 adds a trigger to the automation, any other startid replaces the settings of that trigger, which must belong to seriesid and have the same type. A new trigger is also added to the start block. The automation's list relations and scheduled processing are rebuilt, a draft automation becomes inactive, and a revision is recorded. Every key of automationStart listed as required must be present, even when 0. Problems found by the save itself (an automation, block or trigger that does not exist, settings the trigger type refuses) are answered with HTTP 200 and succeeded 0; check succeeded, not the status. Internal: used by the automation builder.","operationId":"save-an-automation-trigger","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["automationStart"],"properties":{"automationStart":{"description":"The trigger","required":["multientry","params","relid","segmentid","seriesid","startid","type","blockid"],"properties":{"startid":{"description":"ID of the trigger to update; 0 to add a new trigger","type":"integer","example":0},"seriesid":{"description":"ID of the automation","type":"integer","example":12},"blockid":{"description":"ID of the automation's start block. The block's type decides which save runs, so it must be the start block.","type":"integer","example":101},"type":{"description":"Trigger type, such as subscribe, unsubscribe, tagadd, tagrem, field, date, event, url or dealstage","type":"string","example":"subscribe"},"relid":{"description":"ID of the record the trigger watches, such as the list of a subscribe trigger; 0 for any. Saved as 0 for date, event, field, tagadd, tagrem and url triggers.","type":"integer","example":3},"params":{"description":"The settings of this trigger type, for example the tag name of a tagadd trigger","type":"object","example":{"tag":"triggertag"},"additionalProperties":true},"multientry":{"description":"1 to let a contact enter the automation more than once from this trigger","type":["integer","boolean"],"example":0},"segmentid":{"description":"ID of the segment whose conditions a contact must meet to enter; 0 for none. Replaced when advancedSegmentData is sent.","type":"integer","example":0},"segmentData":{"description":"Segment conditions as a JSON-encoded string. When present, the fieldId, fieldValue and fieldOperator keys are dropped from params.","type":"string"},"vars":{"description":"Accepted, but not read when a start trigger is saved","type":"object","additionalProperties":true}},"type":"object"},"advancedSegmentData":{"description":"Segment conditions in the segments service format, saved as the trigger's segment; its segment ID replaces automationStart.segmentid. Must carry an attributes object.","required":["attributes"],"properties":{"id":{"description":"ID of the segment to update; leave out to create one","type":"string"},"attributes":{"description":"The segment definition","type":"object","additionalProperties":true}},"type":"object","additionalProperties":true}},"type":"object"},"example":{"automationStart":{"startid":0,"seriesid":12,"blockid":101,"type":"tagadd","relid":0,"params":{"tag":"triggertag"},"multientry":0,"segmentid":0}}}}},"responses":{"200":{"description":"The outcome. succeeded is 1 when the trigger was saved, 0 when the save refused it.","content":{"application/json":{"schema":{"required":["succeeded","message"],"properties":{"succeeded":{"description":"1 when the trigger was saved, otherwise 0","type":"integer","enum":[0,1],"example":1},"message":{"description":"Translated outcome: a confirmation, or why the save was refused","type":"string"},"block":{"description":"The automation's start block after the save, as the builder displays it. Present only when succeeded is 1.","properties":{"id":{"description":"ID of the start block","type":"string","example":"101"},"seriesid":{"description":"ID of the automation","type":"string","example":"12"},"parentid":{"description":"ID of the parent block; 0 for the start block","type":"string","example":"0"},"ordernum":{"description":"Position of the block among its parent's children","type":"string","example":"0"},"type":{"description":"Always start","type":"string","example":"start"},"params":{"description":"vars as a JSON-encoded string","type":"string"},"deleted":{"description":"1 when the block is deleted, otherwise 0","type":"string","example":"0"},"cdate":{"description":"When the block was created, Y-m-d H:i:s","type":["string","null"]},"mdate":{"description":"When the block was last modified, Y-m-d H:i:s","type":["string","null"]},"vars":{"description":"The block's settings","properties":{"starts":{"description":"Every start trigger of the automation, after the change","type":"array","items":{"properties":{"id":{"description":"ID of the start trigger","type":"integer","example":55},"seriesid":{"description":"ID of the automation","type":"integer","example":12},"segmentid":{"description":"ID of the segment whose conditions a contact must meet to enter; 0 for none","type":"integer","example":0},"multientry":{"description":"1 when a contact may enter the automation more than once","type":"integer","example":0},"type":{"description":"Trigger type","type":"string","example":"subscribe"},"relid":{"description":"ID of the record the trigger watches, such as the list of a subscribe trigger; 0 for any","type":"integer","example":3},"params":{"description":"The trigger's settings as stored, a JSON-encoded string","type":"string"},"vars":{"description":"The trigger's settings, decoded, with settings saved in an older format converted to the current one. An empty array when the trigger has no settings.","type":"array","items":{}},"_segmenttext":{"description":"Description of the trigger's segment conditions, for display. Present only when the trigger has a segment.","type":"string"},"cdate":{"description":"When the trigger was created, Y-m-d H:i:s","type":["string","null"]},"mdate":{"description":"When the trigger was last modified, Y-m-d H:i:s","type":["string","null"]}},"type":"object","additionalProperties":true}}},"type":"object"}},"type":"object","additionalProperties":true},"notes":{"description":"Notes saved on the trigger. Present only when succeeded is 0 and the trigger has notes.","type":"array","items":{"type":"object","additionalProperties":true}}},"type":"object"}}}},"400":{"description":"The body is JSON but not an object. Body: an `errors` array."},"403":{"description":"The user does not have the manage automations permission.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":403},"title":{"description":"Translated name of the HTTP status","type":"string"},"detail":{"description":"Always the same message","type":"string","example":"You don't have permission to perform this action."}},"type":"object"}}},"type":"object"}}}},"422":{"description":"automationStart or one of its required keys is missing, or advancedSegmentData has no attributes object. The body is the bare message text, not JSON, although the Content-Type header says application/json.","content":{"text/plain":{"schema":{"type":"string","example":"Missing required field: blockid"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/automationStarts/{id}":{"get":{"summary":"Retrieve an automation start trigger","description":"Returns one start trigger, the event that enters contacts into an automation. The response key is automationTrigger, not automationStart. Internal: used by the app.","operationId":"retrieve-an-automation-trigger","x-canonical-resource":"automation","parameters":[{"name":"id","in":"path","description":"ID of the start trigger","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The trigger","content":{"application/json":{"schema":{"type":"object","properties":{"automationTrigger":{"$ref":"#/components/schemas/AutomationStartsTrigger"}}},"example":{"automationTrigger":{"seriesid":"12","segmentid":"0","multientry":"0","type":"tagadd","relid":"0","params":{"tag":"triggertag"},"cdate":"2026-10-15T10:52:26-05:00","mdate":"2026-10-15T10:52:26-05:00","links":[],"id":"55"}}}}},"404":{"description":"No start trigger has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for SeriesStart with id 55"}}}}}}},"x-internal":true}},"/automationStarts/{id}/primaryContactOnly":{"put":{"summary":"Let an automation trigger start for every contact on a record","description":"Turns off primary_contact_only on one start trigger, so a trigger that started the automation only for the primary contact of a deal (or other record) starts it for every contact on it. The only accepted body is {\"primary_contact_only\": false}: the setting cannot be turned on here. A trigger that does not have the setting on is left unchanged and the call still succeeds. A query string on the URL makes the call fail with 405, because the action checks that the request URI ends in /primaryContactOnly. Internal: used by the automation builder.","operationId":"convert-an-automation-trigger-to-all-contacts","parameters":[{"name":"id","in":"path","description":"ID of the start trigger","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["primary_contact_only"],"properties":{"primary_contact_only":{"description":"Must be the boolean false","type":"boolean","enum":[false],"example":false}},"type":"object"},"example":{"primary_contact_only":false}}}},"responses":{"200":{"description":"The trigger starts for every contact on the record","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always 1","type":"integer","example":1},"block":{"description":"The automation's start block, as the builder displays it","properties":{"id":{"description":"ID of the start block","type":"string","example":"101"},"seriesid":{"description":"ID of the automation","type":"string","example":"12"},"parentid":{"description":"ID of the parent block; 0 for the start block","type":"string","example":"0"},"ordernum":{"description":"Position of the block among its parent's children","type":"string","example":"0"},"type":{"description":"Always start","type":"string","example":"start"},"params":{"description":"vars as a JSON-encoded string","type":"string"},"deleted":{"description":"1 when the block is deleted, otherwise 0","type":"string","example":"0"},"cdate":{"description":"When the block was created, Y-m-d H:i:s","type":["string","null"]},"mdate":{"description":"When the block was last modified, Y-m-d H:i:s","type":["string","null"]},"vars":{"description":"The block's settings","properties":{"starts":{"description":"Every start trigger of the automation, after the change","type":"array","items":{"properties":{"id":{"description":"ID of the start trigger","type":"integer","example":55},"seriesid":{"description":"ID of the automation","type":"integer","example":12},"segmentid":{"description":"ID of the segment whose conditions a contact must meet to enter; 0 for none","type":"integer","example":0},"multientry":{"description":"1 when a contact may enter the automation more than once","type":"integer","example":0},"type":{"description":"Trigger type","type":"string","example":"subscribe"},"relid":{"description":"ID of the record the trigger watches, such as the list of a subscribe trigger; 0 for any","type":"integer","example":3},"params":{"description":"The trigger's settings as stored, a JSON-encoded string","type":"string"},"vars":{"description":"The trigger's settings, decoded, with settings saved in an older format converted to the current one. An empty array when the trigger has no settings.","type":"array","items":{}},"_segmenttext":{"description":"Description of the trigger's segment conditions, for display. Present only when the trigger has a segment.","type":"string"},"cdate":{"description":"When the trigger was created, Y-m-d H:i:s","type":["string","null"]},"mdate":{"description":"When the trigger was last modified, Y-m-d H:i:s","type":["string","null"]}},"type":"object","additionalProperties":true}}},"type":"object"}},"type":"object","additionalProperties":true}},"type":"object"}}}},"400":{"description":"The body is JSON but not an object. Body: an `errors` array."},"403":{"description":"The user does not have the manage automations permission.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":403},"title":{"description":"Translated name of the HTTP status","type":"string"},"detail":{"description":"Always the same message","type":"string","example":"You don't have permission to perform this action."}},"type":"object"}}},"type":"object"}}}},"404":{"description":"No start trigger has this ID (detail `Automation not found`), or its automation has no start block (detail `Automation action not found`). Body: an `errors` array."},"405":{"description":"The request URI does not end in /primaryContactOnly, which happens when a query string is added. Body: an `errors` array."},"422":{"description":"The body is anything other than {\"primary_contact_only\": false}. The body is the bare message text, not JSON, although the Content-Type header says application/json.","content":{"text/plain":{"schema":{"type":"string","example":"Invalid operation: the only valid input is to set primary_contact_only to false"}}}}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/automations":{"get":{"summary":"List all automations","description":"","operationId":"list-all-automations","x-canonical-resource":"automation","parameters":[{"name":"limit","in":"query","description":"Number of automations to return. Defaults to 20, and values above 100 are reduced to 100.","schema":{"type":"integer","format":"int32","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of automations to skip, for paging.","schema":{"type":"integer","format":"int32","default":0}},{"name":"entryDateStart","in":"query","description":"When set together with `entryDateEnd`, return only automations that had at least one run entry between these dates (inclusive). Both parameters are required to apply the window. Day boundaries use the signed-in user's time zone. Each returned automation includes `entriesInWindow`, the count of runs in that window. `meta.entryWindowApplied` is true when the window was applied. `entered` and `exited` on each row remain all-time totals. When the windowed count cannot complete in time, the response falls back to the normal roster and `meta.entryWindowApplied` is false.","schema":{"type":"string","format":"date","example":"2026-04-21"}},{"name":"entryDateEnd","in":"query","description":"Inclusive end date for the entry window. Must be sent with `entryDateStart`. Format `YYYY-MM-DD`.","schema":{"type":"string","format":"date","example":"2026-10-21"}},{"name":"ids","in":"query","description":"Return only these automations. One id, or several separated by commas. Supersedes `limit`, which becomes the number of ids given.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Return only automations whose name contains this text.","schema":{"type":"string"}},{"name":"active","in":"query","description":"Split automations by whether they are live. A true value (`1` or `true`) returns every automation past draft — active, inactive and paused alike. A false value (`0` or `false`) returns drafts only, not inactive or paused automations. Omit the parameter to return all of them.","schema":{"type":"string"}},{"name":"has_message","in":"query","description":"Set to any non-empty value to return only automations that send a campaign, an SMS or a site message.","schema":{"type":"string"}},{"name":"label","in":"query","description":"Return only automations in these folders. One folder id, or several separated by commas. `-1` means automations in no folder.","schema":{"type":"string"}},{"name":"enhance","in":"query","description":"Set to any non-empty value to include each automation's block, goal, campaign, label and conversion data alongside the automations themselves.","schema":{"type":"string"}},{"name":"statusCounts","in":"query","description":"Set to any non-empty value to include a count of automations per status next to the results.","schema":{"type":"string"}},{"name":"show_has_goal","in":"query","description":"Set to any value other than `false` to mark whether each automation already has a business goal attached.","schema":{"type":"string"}},{"name":"map","in":"query","description":"Set to any truthy value when the results are being drawn as the automations map. Once more than 100 automations match, the map cannot render them all, so the results are narrowed to the automations that reference one another through their blocks. Under 100 matches it changes nothing.","schema":{"type":"string"}},{"name":"filters[name]","in":"query","description":"Filter by the automation's name. A partial match: `renew` matches `Renewal reminder`.","schema":{"type":"string"}},{"name":"filters[status]","in":"query","description":"Filter by the automation's status: 0 draft, 1 active, 2 inactive, 3 paused. Several statuses may be given separated by commas.","schema":{"type":"string"}},{"name":"filters[hidden]","in":"query","description":"Filter by whether the automation is hidden. 1 hidden, 0 not. Defaults to 0 when the parameter is omitted, so hidden automations are left out unless they are asked for.","schema":{"type":"string"}},{"name":"filters[entered]","in":"query","description":"Filter by the total number of contacts that have entered the automation.","schema":{"type":"string"}},{"name":"filters[exited]","in":"query","description":"Filter by the total number of contacts that have left the automation.","schema":{"type":"string"}},{"name":"filters[cdate]","in":"query","description":"Filter by the automation's created date.","schema":{"type":"string"}},{"name":"filters[mdate]","in":"query","description":"Filter by the automation's last modified date.","schema":{"type":"string"}},{"name":"filters[ids]","in":"query","description":"Return only these automations. One id, or several separated by commas.","schema":{"type":"string"}},{"name":"filters[tag]","in":"query","description":"Return only automations that add or remove this tag id.","schema":{"type":"integer","format":"int32"}},{"name":"filters[triggers]","in":"query","description":"Return only automations started by these trigger types, separated by commas.","schema":{"type":"string"}},{"name":"filters[actions]","in":"query","description":"Return only automations containing these action block types, separated by commas.","schema":{"type":"string"}},{"name":"filters[label_name]","in":"query","description":"Return only automations in the folder with this name.","schema":{"type":"string"}},{"name":"orders[name]","in":"query","description":"Order by the automation's name.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[status]","in":"query","description":"Order by the automation's status.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[hidden]","in":"query","description":"Order by whether the automation is hidden.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[entered]","in":"query","description":"Order by the total number of contacts that have entered the automation.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[exited]","in":"query","description":"Order by the total number of contacts that have left the automation.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[cdate]","in":"query","description":"Order by the automation's created date.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[mdate]","in":"query","description":"Order by the automation's last modified date.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[revisions]","in":"query","description":"Order by when the automation was last revised, falling back to its last modified date when it has never been revised. Sent without a direction, this orders descending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[currentContacts]","in":"query","description":"Order by the number of contacts currently moving through the automation. Sent without a direction, this orders descending.","schema":{"type":"string","enum":["ASC","DESC"]}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"automations\": [\n        {\n            \"name\": \"Email Subscription\",\n            \"cdate\": \"2018-08-06T16:28:43-05:00\",\n            \"mdate\": \"2018-08-06T16:33:10-05:00\",\n            \"userid\": \"1\",\n            \"status\": \"2\",\n            \"entered\": \"0\",\n            \"exited\": \"0\",\n            \"hidden\": \"0\",\n            \"defaultscreenshot\": \"http://img-us1.com/default-series.gif\",\n            \"screenshot\": \"https://d226aj4ao1t61q.cloudfront.net/k0x4h0lr_default-automation.png\",\n            \"links\": {\n                \"campaigns\": \"https://:account.api-us1.com/api/3/automations/1/campaigns\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/automations/1/contactGoals\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/3/automations/1/contactAutomations\",\n                \"blocks\": \"https://:account.api-us1.com/api/3/automations/1/blocks\",\n                \"goals\": \"https://:account.api-us1.com/api/3/automations/1/goals\",\n                \"sms\": \"https://:account.api-us1.com/api/3/automations/1/sms\",\n                \"sitemessages\": \"https://:account.api-us1.com/api/3/automations/1/sitemessages\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"name\": \"Test SMS Send\",\n            \"cdate\": \"2018-09-18T10:46:32-05:00\",\n            \"mdate\": \"2018-09-18T10:54:30-05:00\",\n            \"userid\": \"1\",\n            \"status\": \"1\",\n            \"entered\": \"2\",\n            \"exited\": \"2\",\n            \"hidden\": \"0\",\n            \"defaultscreenshot\": \"http://img-us1.com/default-series.gif\",\n            \"screenshot\": \"https://d226aj4ao1t61q.cloudfront.net/k0x4h0lr_default-automation.png\",\n            \"links\": {\n                \"campaigns\": \"https://:account.api-us1.com/api/3/automations/2/campaigns\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/automations/2/contactGoals\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/3/automations/2/contactAutomations\",\n                \"blocks\": \"https://:account.api-us1.com/api/3/automations/2/blocks\",\n                \"goals\": \"https://:account.api-us1.com/api/3/automations/2/goals\",\n                \"sms\": \"https://:account.api-us1.com/api/3/automations/2/sms\",\n                \"sitemessages\": \"https://:account.api-us1.com/api/3/automations/2/sitemessages\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\",\n        \"starts\": [\n            {\n                \"id\": \"2\",\n                \"series\": \"1\",\n                \"type\": \"subscribe\"\n            },\n            {\n                \"id\": \"4\",\n                \"series\": \"2\",\n                \"type\": \"subscribe\"\n            }\n        ],\n        \"filtered\": false,\n        \"smsLogs\": []\n    }\n}"}},"schema":{"type":"object","properties":{"automations":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Email Subscription"},"cdate":{"type":"string","example":"2018-08-06T16:28:43-05:00"},"mdate":{"type":"string","example":"2018-08-06T16:33:10-05:00"},"userid":{"type":"string","example":"1"},"status":{"type":"string","example":"2"},"entered":{"type":"string","example":"0"},"exited":{"type":"string","example":"0"},"entriesInWindow":{"type":"string","description":"Present when `meta.entryWindowApplied` is true: run entries in the requested entry date window.","example":"3"},"hidden":{"type":"string","example":"0"},"defaultscreenshot":{"type":"string","example":"http://img-us1.com/default-series.gif"},"screenshot":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/k0x4h0lr_default-automation.png"},"links":{"type":"object","properties":{"campaigns":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/campaigns"},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/contactGoals"},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/contactAutomations"},"blocks":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/blocks"},"goals":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/goals"},"sms":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/sms"},"sitemessages":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/sitemessages"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"},"starts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"2"},"series":{"type":"string","example":"1"},"type":{"type":"string","example":"subscribe"}}}},"filtered":{"type":"boolean","example":false,"default":true},"smsLogs":{"type":"array"},"entryWindowApplied":{"type":"boolean","description":"Present when `entryDateStart` or `entryDateEnd` was sent. True when the list was filtered to automations with entries in the window. False when the windowed count timed out and the all-time roster was returned instead."}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"422":{"description":"Invalid entry date parameters.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/automations/accountBlockEventsAggregateResults":{"post":{"summary":"Read the results of an account-wide automation events aggregate query","description":"Polls the two queries started by POST /automations/accountBlockEventsAggregateSubmit. A POST that only reads: nothing changes. While they run `status` is `RUNNING`; once `SUCCEEDED`, the log service's figures (per-automation top errors and a daily time series) are returned with each automation's name added by Hosted. Available only when the account has the AI automation integration feature on. Internal: read by the AI automation data agent.","operationId":"retrieve-account-automation-events-aggregate-results","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["triplesQueryExecutionId","timeSeriesQueryExecutionId"],"properties":{"triplesQueryExecutionId":{"description":"From the submit response","type":"string"},"timeSeriesQueryExecutionId":{"description":"From the submit response","type":"string"}},"type":"object"}}}},"responses":{"200":{"description":"The state of the queries and, once they succeed, the figures. Fields other than `status` and the added automation names are the log service's.","content":{"application/json":{"schema":{"properties":{"status":{"description":"State of the queries","type":"string","enum":["RUNNING","FAILED","SUCCEEDED"]},"automations":{"description":"When `SUCCEEDED`: per-automation figures","type":"array","items":{"properties":{"seriesId":{"description":"ID of the automation","type":["integer","string"]},"name":{"description":"Added by Hosted: the automation's name; null when it no longer exists","type":["string","null"]}},"type":"object"}}},"type":"object"}}}},"404":{"description":"The feature is off for the account. The body is an empty object."},"422":{"description":"An execution ID is missing or blank. Body: an `errors` array. The log service's own 4xx errors are passed on with their status and an `error` message."},"502":{"description":"The log service answered in an unexpected format","content":{"application/json":{"schema":{"properties":{"error":{"description":"Unexpected response format from ALS","type":"string"}},"type":"object"}}}},"503":{"description":"The log service could not be reached","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/automations/accountBlockEventsAggregateSubmit":{"post":{"summary":"Start an account-wide automation events aggregate query","description":"Starts the two log service queries (per-block counts and per-day counts) behind an account-wide aggregate of automation events and returns their execution IDs straight away; read the results with POST /automations/accountBlockEventsAggregateResults until they finish. Nothing in the account changes. Available only when the account has the AI automation integration feature on. Internal: read by the AI automation data agent.","operationId":"submit-account-automation-events-aggregate","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["startDate","endDate"],"properties":{"startDate":{"description":"First day, Y-m-d","type":"string","format":"date","example":"2026-10-01"},"endDate":{"description":"Last day, Y-m-d; not before `startDate` and at most 7 days after it, counting both","type":"string","format":"date","example":"2026-10-07"},"automationIds":{"description":"Only these automations; all of them when left out. Duplicates are dropped.","type":"array","items":{"type":"integer","minimum":1},"minItems":1}},"type":"object"}}}},"responses":{"202":{"description":"The queries were submitted","content":{"application/json":{"schema":{"properties":{"triplesQueryExecutionId":{"description":"Execution ID of the per-block query","type":"string"},"timeSeriesQueryExecutionId":{"description":"Execution ID of the per-day query","type":"string"},"status":{"description":"Always `SUBMITTED`","type":"string"}},"type":"object"}}}},"404":{"description":"The feature is off for the account. The body is an empty object."},"422":{"description":"The body fails validation: a date missing or not Y-m-d, `endDate` before `startDate`, a range over 7 days, or `automationIds` empty or not all positive integers. Body: an `errors` array. The log service's own 4xx errors are passed on with their status and an `error` message."},"502":{"description":"The log service answered in an unexpected format","content":{"application/json":{"schema":{"properties":{"error":{"description":"Unexpected response format from ALS","type":"string"}},"type":"object"}}}},"503":{"description":"The log service could not be reached","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/automations/actions":{"get":{"summary":"List the action block types the automation builder offers","description":"The action block catalog. Without `include` it is the basic list in a JSON:API-like shape (`id`, `type: automationActions`, `attributes`). With `include` the response is the builder's catalog instead: the actions available to the account (Salesforce, split, Facebook, conversion, scoring, outbound email, Microsoft and integration layer blocks shown or hidden by the account's features), plus the action categories and apps when asked for. The two shapes differ; `include` decides which one is returned. Internal: backs the automation builder's action picker.","operationId":"list-automation-action-types","parameters":[{"name":"include","in":"query","description":"Comma-separated: `categories` adds `data.categories`, `apps` adds `data.apps` (and fetches connected and marketplace apps). Any non-empty value, even one naming neither, switches to the catalog shape.","required":false,"schema":{"type":"string"},"example":"categories,apps"}],"responses":{"200":{"description":"The actions. Without `include`, `data` is a list of `{id, type, attributes}`; with it, `data` is an object with `actions` and the requested extras.","content":{"application/json":{"schema":{"properties":{"data":{"description":"A list without `include`; an object with `actions`, `categories` and `apps` with it","oneOf":[{"type":"array","items":{"properties":{"id":{"description":"Position-based ID","type":"string"},"type":{"description":"Always `automationActions`","type":"string"},"attributes":{"description":"The action's `action-key` (block type), `category`, and translated `name`, `label` and `description`","type":"object"}},"type":"object"}},{"properties":{"actions":{"type":"array","items":{"properties":{"id":{"description":"Block type, e.g. `send`","type":"string"},"name":{"description":"Translated name","type":"string"},"label":{"description":"Translated label","type":"string"},"descript":{"description":"Translated description","type":"string"},"categories":{"description":"IDs of the action categories the block appears in","type":"array","items":{"type":"string"}}},"type":"object"}},"categories":{"description":"Present with `include=categories`","type":"array","items":{"properties":{"id":{"description":"Category ID","type":"string"},"description":{"description":"Translated category name","type":"string"},"icon":{"description":"Icon name","type":"string"}},"type":"object"}},"apps":{"description":"Present with `include=apps`: native and connected apps that offer actions, sorted by name","type":"array","items":{"type":"object"}}},"type":"object"}]}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/block_groups":{"get":{"summary":"List automation action block groups","description":"The groups the automation builder's action menu sorts action blocks into: `send`, `flow`, `contact`, `crm` (only when the account has deals or accounts), `salesforce` and `cx_apps`. `name` is the untranslated group key, the same as `id`. Other verbs are answered 405 by the router before the script runs. Internal: backs the automation builder.","operationId":"list-automation-block-groups","x-canonical-resource":"automation","responses":{"200":{"description":"The groups","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"The groups, in menu order","items":{"type":"object","properties":{"id":{"type":"string","description":"Group key","example":"send"},"name":{"type":"string","description":"The same key, untranslated"}}}}}},"example":{"data":[{"id":"send","name":"send"},{"id":"flow","name":"flow"},{"id":"contact","name":"contact"}]}}}}},"x-internal":true}},"/automations/bulk/addBlocks":{"post":{"summary":"Add several blocks to an automation","description":"Adds a sequence of action blocks to an automation in one call, one after another starting at `parentBlockId`, and saves a revision marked as AI-generated so POST /automations/bulk/undo/{seriesid} can take it back. Blocks of unknown types are dropped and `end` blocks are skipped; blocks of types the account's plan does not include are not added and are listed in `requiresEntitlement`. If a block cannot be created the blocks already added are rolled back. Internal: used by AI-assisted automation building.","operationId":"bulk-add-automation-blocks","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationId":{"type":"integer","description":"ID of the automation"},"parentBlockId":{"type":"integer","description":"ID of the block of this automation to add the first new block next to"},"direction":{"type":"integer","description":"Where the first block goes relative to the parent: -1 before, 0 under (inside a branching block), 1 after. Corrected to under or after to suit the parent's type.","enum":[-1,0,1]},"blocks":{"type":"array","description":"The blocks, in order","items":{"type":"object","properties":{"type":{"type":"string","description":"Block type, e.g. `send`, `addtag`, `wait`"},"params":{"type":"object","description":"The block's settings, sanitised per block type"}},"required":["type"]}}},"required":["automationId","parentBlockId","direction","blocks"],"example":{"automationId":1,"parentBlockId":2,"direction":1,"blocks":[{"type":"send"},{"type":"addtag","params":{"tagNames":["tag"]}},{"type":"wait","params":{"waittype":"for","waittime":2,"waitdurt":"hour"}}]}}}}},"responses":{"201":{"description":"The blocks were added","content":{"application/json":{"schema":{"type":"object","properties":{"automationBlocks":{"type":"array","description":"The created blocks as stored (id, type, parent, ordernum, params, ...), each with a `readableName`","items":{"type":"object"}},"requiresEntitlement":{"type":"array","description":"Present when some blocks were left out: one entry per block type the plan does not include","items":{"type":"object","properties":{"block":{"type":"string","description":"Block type"},"entitlement":{"type":"string","description":"The entitlement it needs"},"readableName":{"type":["string","null"],"description":"Name of the block type"}}}}}}}}},"400":{"description":"A required field is missing, the parent block is not in the automation, the automation does not exist, `direction` is invalid, no valid block was given, or a block's settings are invalid (body: an `errors` array). When every block needs an entitlement the plan lacks, the body is `{\"requiresEntitlement\": [...]}` instead.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}},{"type":"object","properties":{"requiresEntitlement":{"type":"array","description":"As in the 201 response","items":{"type":"object"}}}}]}}}},"402":{"description":"The blocks would take the automation over its block limit. Body: an `errors` array, title `Too many blocks`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"500":{"description":"A block could not be created after retrying; the blocks added were rolled back. The body echoes the validated request (`parentBlockId`, `direction`, `automationId`, `blocks`, ...) so it can be retried.","content":{"application/json":{"schema":{"type":"object"}}}}},"x-internal":true}},"/automations/bulk/undo/{seriesid}":{"post":{"summary":"Undo the last bulk block addition","description":"Rolls the automation back to the revision before the latest one, provided the latest revision was saved by POST /automations/bulk/addBlocks (marked AI-generated); when there is no earlier revision, the blocks that call added are deleted. Saves the result as a new revision. Internal: used by AI-assisted automation building.","operationId":"undo-automation-bulk-block-add","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"seriesid","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Rolled back. The body is empty."},"400":{"description":"The rollback failed. Body: an `errors` array with the reason.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"403":{"description":"The user lacks the manage-automations permission, or the latest revision was not made by a bulk add. Body: an `errors` array without a detail.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"404":{"description":"No automation with this ID. Body: an `errors` array without a detail.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}}},"x-internal":true}},"/automations/bulkUpdate":{"patch":{"summary":"Bulk update automation labels, business goals and user groups","description":"Adds and removes labels, business goals and user-group access on many automations in one transaction. Every automation, label, goal and group ID is checked first; one unknown ID fails the whole request and nothing is written. Failures detected by the controller (no manage-automations permission, an unknown ID, an unexpected error) are answered with HTTP 200 and `meta.success: false`: the controller passes 403/422/500 where the legacy JsonResponse expects meta, so the status is never applied. Check `meta.success`, not the status. Internal: backs the automation list's bulk actions.","operationId":"bulk-update-automations","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["automationIds"],"properties":{"automationIds":{"description":"IDs of the automations to update. Integers, not numeric strings.","type":"array","items":{"type":"integer"},"minItems":1,"example":[123,456]},"labels":{"description":"Automation labels (folders). At least one of add or remove when present.","properties":{"add":{"description":"IDs to attach to every listed automation; already attached ones are skipped","type":"array","items":{"type":"integer"}},"remove":{"description":"IDs to detach from every listed automation","type":"array","items":{"type":"integer"}}},"type":"object"},"businessGoals":{"description":"Business goals, stored as labels. At least one of add or remove when present.","properties":{"add":{"description":"IDs to attach to every listed automation; already attached ones are skipped","type":"array","items":{"type":"integer"}},"remove":{"description":"IDs to detach from every listed automation","type":"array","items":{"type":"integer"}}},"type":"object"},"userGroups":{"description":"Non-admin user groups that may see the automation. At least one of add or remove when present.","properties":{"add":{"description":"IDs to attach to every listed automation; already attached ones are skipped","type":"array","items":{"type":"integer"}},"remove":{"description":"IDs to detach from every listed automation","type":"array","items":{"type":"integer"}}},"type":"object"}},"type":"object"},"example":{"automationIds":[123,456],"labels":{"add":[1,2],"remove":[4]}}}}},"responses":{"200":{"description":"The result. On success `meta.success` is true and `results` holds one entry per automation; on failure `meta.success` is false and `error` says why.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Present on success","type":"string","example":"Bulk update completed successfully"},"error":{"description":"Present on failure, e.g. `You do not have permission to manage automations` or `Automations with IDs [9] do not exist.`","type":"string"},"results":{"description":"Present on success, one entry per requested automation","type":"array","items":{"properties":{"automationId":{"description":"ID of the automation","type":"integer"},"labels":{"properties":{"added":{"description":"Relations created for this automation","type":"integer"},"removed":{"description":"Relations removed from this automation","type":"integer"}},"type":"object"},"businessGoals":{"properties":{"added":{"description":"Relations created for this automation","type":"integer"},"removed":{"description":"Relations removed from this automation","type":"integer"}},"type":"object"},"userGroups":{"properties":{"added":{"description":"Relations created for this automation","type":"integer"},"removed":{"description":"Relations removed from this automation","type":"integer"}},"type":"object"},"errors":{"description":"Per-automation errors; always empty today","properties":{"errors":{"type":"array","items":{"type":"string"}}},"type":"object"}},"type":"object"}},"meta":{"properties":{"success":{"description":"Whether the update was applied","type":"boolean"},"processed":{"description":"Present on success: number of automation IDs in the request","type":"integer"}},"type":"object"}},"type":"object"}}}},"422":{"description":"The body fails validation before the controller runs: `automationIds` missing, empty or not all integers, or a labels/businessGoals/userGroups object with neither `add` nor `remove`. Body: an `errors` array naming each invalid attribute."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/automations/bulk_delete":{"delete":{"summary":"Delete automations in bulk","description":"Deletes every automation listed in `seriesIds`. Each deletion is first reported to the franchise service, then the automation is deleted with its related records; when asynchronous bulk delete is on for the account, the automation row is deleted at once and its related records are removed by a background process. An ID that fails (unknown, or an error while deleting) is logged and skipped, so the response reports success whatever happened to each ID. The time limit is raised for long deletions. Other verbs are answered 405 by the router before the script runs. Internal: backs the automation list's bulk delete.","operationId":"bulk-delete-automations","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"seriesIds":{"type":"array","description":"IDs of the automations to delete","items":{"type":"integer"}}},"required":["seriesIds"],"example":{"seriesIds":[87,83]}}}}},"responses":{"200":{"description":"The request was processed. Always this body, even when some IDs were skipped.","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true"}}}}},"example":{"meta":{"success":true}}}}},"403":{"description":"The user lacks the manage-automations permission","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"422":{"description":"The body is empty or not JSON. The body is a translated plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/bulk_edit":{"post":{"summary":"Bulk edit automations","description":"Activate or deactivate every automation listed in `seriesIds` in a single call (status 1 = active, 2 = inactive). Mass mutation, not a listing.","operationId":"get_automations-1","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":true,"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Response":{"value":{"automations":[{"name":"Send Introductory Email","cdate":"2025-10-15T14:08:05-05:00","mdate":"2025-10-15T15:57:24-05:00","userid":"1","status":2,"entered":"2","exited":"2","hidden":"0","entitlements_violation":"0","source":"0","description":null,"exit_on_unsubscribe":"0","exit_on_conversion":"0","multientry":"1","links":{"campaigns":"https://account.api-us1.com/api/3/automations/87/campaigns","contactGoals":"https://account.api-us1.com/api/3/automations/87/contactGoals","contactAutomations":"https://account.api-us1.com/api/3/automations/87/contactAutomations","blocks":"https://account.api-us1.com/api/3/automations/87/blocks","goals":"https://account.api-us1.com/api/3/automations/87/goals","sms":"https://account.api-us1.com/api/3/automations/87/sms","sitemessages":"https://account.api-us1.com/api/3/automations/87/sitemessages","triggers":"https://account.api-us1.com/api/3/automations/87/triggers"},"id":"87"},{"name":"Send Text Message Reminder","cdate":"2025-07-30T12:18:17-05:00","mdate":"2025-10-15T14:07:32-05:00","userid":"1","status":2,"entered":"63","exited":"63","hidden":"0","entitlements_violation":"0","source":"0","description":"","exit_on_unsubscribe":"0","exit_on_conversion":"0","multientry":"1","links":{"campaigns":"https://account.api-us1.com/api/3/automations/83/campaigns","contactGoals":"https://account.api-us1.com/api/3/automations/83/contactGoals","contactAutomations":"https://account.api-us1.com/api/3/automations/83/contactAutomations","blocks":"https://account.api-us1.com/api/3/automations/83/blocks","goals":"https://account.api-us1.com/api/3/automations/83/goals","sms":"https://account.api-us1.com/api/3/automations/83/sms","sitemessages":"https://account.api-us1.com/api/3/automations/83/sitemessages","triggers":"https://account.api-us1.com/api/3/automations/83/triggers"},"id":"83"}]},"summary":"Response"}},"schema":{"type":"object","properties":{"automations":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Email Subscription"},"cdate":{"type":"string","example":"2018-08-06T16:28:43-05:00"},"mdate":{"type":"string","example":"2018-08-06T16:33:10-05:00"},"userid":{"type":"string","example":"1"},"status":{"type":"string","example":"2"},"entered":{"type":"string","example":"0"},"exited":{"type":"string","example":"0"},"hidden":{"type":"string","example":"0"},"defaultscreenshot":{"type":"string","example":"http://img-us1.com/default-series.gif"},"screenshot":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/k0x4h0lr_default-automation.png"},"links":{"type":"object","properties":{"campaigns":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/campaigns"},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/contactGoals"},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/contactAutomations"},"blocks":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/blocks"},"goals":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/goals"},"sms":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/sms"},"sitemessages":{"type":"string","example":"https://:account.api-us1.com/api/3/automations/1/sitemessages"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"},"starts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"2"},"series":{"type":"string","example":"1"},"type":{"type":"string","example":"subscribe"}}}},"filtered":{"type":"boolean","example":false,"default":true},"smsLogs":{"type":"array"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Response":{"value":"{}","summary":"Response"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"seriesIds":{"type":"array","description":"A list of automation IDs to be made active/inactive","items":{"type":"integer"}},"status":{"type":"integer","description":"1 = Activate, 2 = Inactive","enum":[1,2]},"reactivateAt":{"type":"string","description":"When a paused automation should become active again. Read only when status is 3 (paused) and scheduled reactivation is enabled; must be a date and time in the future and within the pause window, else 422."},"excludeDuplicates":{"type":"boolean","description":"Defaults to true."},"excludeAlreadyIn":{"type":"boolean","description":"Defaults to true."}},"required":["seriesIds"],"additionalProperties":false}}}}}},"/automations/clear_batch":{"post":{"summary":"Release contact automation runs held by a processing batch","description":"Clears the processing batch claim on the given contact automations so the processor picks them up again. A support tool: callable only from the support tools network (allowed addresses with support access) or the local development environment, and only by a user with the manage-automations permission. Internal: support tooling for stuck automation runs.","operationId":"clear-contact-automation-batch-ids","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subscriberSeriesIds":{"type":"array","description":"IDs of the contact automations (runs) to release","items":{"type":"integer"},"minItems":1}},"required":["subscriberSeriesIds"],"example":{"subscriberSeriesIds":[1201,1202]}}}}},"responses":{"200":{"description":"The claims were cleared","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","description":"Number of runs updated"}}},"example":{"count":2}}}},"403":{"description":"The request did not come from the support tools network (empty body), or the user lacks the manage-automations permission (an `errors` array)."},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"`subscriberSeriesIds` is missing, empty or not a list. The body is the plain text `No subscriberSeriesIds were provided`.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/config":{"get":{"summary":"Retrieve automation builder deal options","description":"Option lists the automation builder's deal blocks offer: which deals a deal field update applies to, and the special task assignees besides the account's users (who come from GET /users). An option list that fails to load is returned empty rather than failing the request. Other verbs are answered 405 by the router before the script runs. Internal: backs the automation builder's deal blocks.","operationId":"retrieve-automation-builder-config","x-canonical-resource":"automation","parameters":[{"name":"seriesid","in":"query","description":"ID of the automation. When it has a deal start trigger, `deal_affects` starts with `triggerdeal`. Read from the query string or a form-encoded body; may be left out.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The options","content":{"application/json":{"schema":{"type":"object","properties":{"deal_affects":{"type":"array","description":"Which deals a deal field update applies to","items":{"type":"object","properties":{"title":{"type":"string","description":"Translated label"},"value":{"type":"string","description":"Option value","enum":["triggerdeal","recentcreate","recentupdate","alldeals","allopen","allwon","alllost"]}}}},"deal_task_assignees":{"type":"array","description":"Special task assignees","items":{"type":"object","properties":{"id":{"type":"string","description":"Assignee key","enum":["account-owner","deal-owner"]},"fullname":{"type":"string","description":"Translated label"}}}}}}}}}},"x-internal":true}},"/automations/copy-status/{processId}":{"get":{"summary":"Retrieve the progress of an automation copy","description":"Polls a background automation copy started by POST /automations/series_copy, which returns the process ID. Only the user who started the copy can read it; for anyone else, and for a process that is not an automation copy, the answer is 404. Internal: polled by the app while a copy runs.","operationId":"retrieve-automation-copy-status","parameters":[{"name":"processId","in":"path","description":"ID of the copy process, as returned when the copy was started","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The copy's progress","content":{"application/json":{"schema":{"properties":{"processId":{"description":"ID of the copy process","type":"integer"},"status":{"description":"`completed` once `percentage` reaches 100","type":"string","enum":["in_progress","completed"]},"percentage":{"description":"Progress from 0 to 100, rounded","type":"integer"},"automationId":{"description":"ID of the new automation. The automation row exists from the start; its blocks and campaigns are copied while the process runs.","type":"integer"},"sourceAutomationId":{"description":"ID of the automation being copied","type":"integer"}},"type":"object"},"example":{"processId":5512,"status":"completed","percentage":100,"automationId":313,"sourceAutomationId":87}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array."},"404":{"description":"No automation copy process with this ID started by this user. Body: an `errors` array."}},"x-canonical-resource":"automation","x-internal":true}},"/automations/downgradeViolations":{"get":{"summary":"List automations that use features a downgrade would remove","description":"For a set of entitlements the account would lose, the automations whose action blocks or start triggers depend on them, with those blocks and triggers. Marked deprecated in the code: it is meant to go away once downgrades are handled automatically. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb, since it only reads query parameters. Internal: supports plan downgrades.","operationId":"list-automation-downgrade-violations","x-canonical-resource":"automation","parameters":[{"name":"entitlements","in":"query","description":"Entitlement keys the account would lose, as `entitlements[]=<key>`. Must be a list; a single value or none fails the request.","schema":{"type":"array","items":{"type":"string"}},"required":true},{"name":"automation_id","in":"query","description":"Check only this automation","schema":{"type":"integer"}}],"responses":{"200":{"description":"The affected automations, ordered by ID; an empty list when none","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the automation"},"name":{"type":"string","description":"Name of the automation"},"status":{"type":"string","description":"0 draft, 1 active, 2 inactive, 3 paused"},"url":{"type":"string","description":"Link to the automation in the app"},"triggers":{"type":"array","description":"Start triggers that would be lost: the trigger rows with a translated `name` added","items":{"type":"object"}},"actions":{"type":"array","description":"Action blocks that would be lost: the block rows with their `name` added","items":{"type":"object"}}}}}}}}},"deprecated":true,"x-internal":true}},"/automations/entitlementsLimit":{"get":{"summary":"Retrieve the automation block limit and usage","description":"The most action blocks one automation may have on the account's plan and, given an automation, a saved revision or a shared recipe, whether that one is at or over the limit. Start, end, else and split-path blocks are not counted. Only the first of `automationId`, `revisionId` and `snapshot` that is sent is used; with none, only `blockLimit` is returned. Other verbs are answered 405 by the router before the script runs. Internal: backs the automation builder's block limit warnings.","operationId":"retrieve-automation-block-limit","x-canonical-resource":"automation","parameters":[{"name":"automationId","in":"query","description":"ID of an automation to measure as stored","schema":{"type":"integer"}},{"name":"revisionId","in":"query","description":"ID of a saved automation revision to measure","schema":{"type":"integer"}},{"name":"snapshot","in":"query","description":"Share hash of a recipe to measure before importing it","schema":{"type":"string"}}],"responses":{"200":{"description":"The limit, and the usage when something was given to measure","content":{"application/json":{"schema":{"type":"object","properties":{"blockLimit":{"type":["integer","null"],"description":"Most action blocks per automation; null when the plan sets no limit"},"isAtOrOverLimit":{"type":"boolean","description":"Present when measuring: true when the blocks counted reach the limit; always false without a limit"},"isOverLimit":{"type":"boolean","description":"Present when measuring: true when the blocks counted exceed the limit; always false without a limit"}}},"example":{"blockLimit":50,"isAtOrOverLimit":false,"isOverLimit":false}}}},"400":{"description":"The automation, revision or recipe was not found or could not be read. Body: an `errors` array whose detail is the reason.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}}},"x-internal":true}},"/automations/eventStart":{"post":{"summary":"Enter contacts into automations for start events","description":"For each entry, finds the contact by email and enters it into every automation whose start trigger matches `startType` and `params`. The controller answers only POST; other verbs get 405. Entries that cannot be processed do not fail the request: they are listed under `invalid` or `error` in a 200 response. Only the account's primary admin may call it. Internal: a batch entry point for automation starts, not public API.","operationId":"start-automations-for-events","x-canonical-resource":"contactAutomations","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","description":"The start events","items":{"type":"object","properties":{"id":{"type":["string","integer"],"description":"Caller's ID for the entry, echoed in the result lists"},"email":{"type":"string","description":"Email of the contact"},"startType":{"type":"string","description":"Start trigger type, e.g. `subscribe`"},"params":{"type":"string","description":"JSON-encoded trigger parameters the automation's trigger is matched against"},"noop":{"type":"boolean","description":"Skip this entry; it is reported under `noop`"},"downstreamBlacklist":{"type":"string","description":"Pipe-separated services that must not process the entry; `hosted` skips it"}},"required":["email","startType","params"]}}},"required":["entries"]}}}},"responses":{"200":{"description":"The outcome of each entry","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"array","description":"Entries processed","items":{}},"invalid":{"type":"array","description":"Entries rejected as invalid (a required field missing, an unknown contact or automation)","items":{}},"error":{"type":"array","description":"Entries that failed with an unexpected error","items":{}},"noop":{"type":"array","description":"Entries skipped because they were marked `noop` or have `hosted` in `downstreamBlacklist`","items":{}}},"description":"Each list holds the `id` of every entry in that outcome, or the whole entry when it has no `id`"}}}},"403":{"description":"The user lacks the manage-automations permission (body `{\"success\": 0, \"message\": \"<translated message>\"}`), or the API user is not the account's primary admin (an `errors` array).","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"success":{"type":"integer","description":"Always 0"},"message":{"type":"string","description":"Translated message"}}},{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}]}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"The body has no `entries` list. The body is empty."}},"x-internal":true}},"/automations/import":{"post":{"summary":"Import a shared automation","description":"Creates a new automation in this account from an automation shared through a template-share link (GET /automations/share_series makes one), and records which link it came from. Blocks and triggers whose settings must be mapped to this account's own records are flagged as needing mapping; POST /automations/importSkip clears them. Internal: backs the automation recipe and share-link import flows.","operationId":"import-an-automation","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["url","source"],"properties":{"url":{"description":"The share link. Its host must be the configured template-share host and its path a 7-character share hash that exists.","type":"string","format":"uri","example":"https://tplshare.com/abc1234"},"source":{"description":"Free-text label for where the import started, stored with the import record","type":"string","example":"automations-ai-prompt"},"ai":{"description":"Record the new automation's source as the AI agent import instead of a plain import","type":"boolean","default":false}},"type":"object"}}}},"responses":{"200":{"description":"The automation was created","content":{"application/json":{"schema":{"properties":{"automationId":{"description":"ID of the new automation","type":"integer","example":312}},"type":"object"}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array with the message."},"404":{"description":"No shared automation for the link's hash. Body: an `errors` array, detail `Template not found`."},"422":{"description":"The body fails validation (`url` or `source` missing or blank, `url` not a URL, wrong host, not a 7-character hash, or no shared automation for it), or the shared automation cannot be imported into this account. Body: an `errors` array; import failures are reported against `url`."}},"x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/automations/importSkip":{"post":{"summary":"Skip the remaining mapping of an imported automation","description":"Finishes an import that is waiting on mapping: every block and trigger of the automation still flagged as needing mapping is rewritten with its mapping-dependent settings cleared, so it no longer waits on mapping. Internal: backs skipping the mapping step of an import.","operationId":"skip-automation-import-mapping","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["seriesid"],"properties":{"seriesid":{"description":"ID of the imported automation","type":"integer","example":312}},"type":"object"}}}},"responses":{"200":{"description":"The flagged blocks and triggers were rewritten","content":{"application/json":{"schema":{"properties":{"automationId":{"description":"The `seriesid` that was sent","type":"integer","example":312}},"type":"object"}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array with the message."},"404":{"description":"No automation with this ID. Body: an `errors` array, detail `Automation not found`."},"422":{"description":"`seriesid` is missing or not an integer, or the automation has no blocks or triggers waiting on mapping. Body: an `errors` array, reported against `seriesid`."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/automations/process":{"post":{"summary":"Process queued contact automation steps","description":"Runs a batch of queued automation entries: each entry moves one contact automation (run) on from a block, as the automation processor does, and duplicate entries are skipped as errors. The fields mirror the automation processing queue's messages. The controller answers only POST; other verbs get 405. Entries that cannot be processed do not fail the request: they are listed under `invalid` or `error` in a 200 response. Only the account's primary admin may call it. Internal: called by the automation processing workers.","operationId":"process-contact-automation-entries","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","description":"The queued entries","items":{"type":"object","properties":{"id":{"type":["string","integer"],"description":"ID of the queue entry, echoed in the result lists"},"contactAutomationId":{"type":["string","integer"],"description":"ID of the contact automation (run)"},"contactId":{"type":["string","integer"],"description":"ID of the contact"},"automationId":{"type":["string","integer"],"description":"ID of the automation"},"parentId":{"type":["string","integer"],"description":"ID of the block the run continues from"},"blockId":{"type":["string","integer"],"description":"ID of a block to enter directly"},"startAt":{"type":"string","description":"When the step becomes due"},"batchId":{"type":"string","description":"Processing batch that claimed the entry"},"noop":{"type":"boolean","description":"Skip this entry; it is reported under `noop`"}}}}},"required":["entries"],"example":{"entries":[{"id":"1","contactAutomationId":"1","contactId":"1","automationId":"1","parentId":"1"}]}}}}},"responses":{"200":{"description":"The outcome of each entry","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"array","description":"Entries processed","items":{}},"invalid":{"type":"array","description":"Entries rejected as invalid (a required field missing, an unknown contact or automation)","items":{}},"error":{"type":"array","description":"Entries that failed with an unexpected error","items":{}},"noop":{"type":"array","description":"Entries skipped because they were marked `noop` or have `hosted` in `downstreamBlacklist`","items":{}}},"description":"Each list holds the `id` of every entry in that outcome, or the whole entry when it has no `id`"}}}},"403":{"description":"The API user is not the account's primary admin. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"The body has no `entries` list. The body is empty."}},"x-internal":true}},"/automations/queue_send":{"post":{"summary":"Send a campaign queued by send time optimization","description":"Called back when the send time chosen for a contact arrives: queues the automation send block's campaign to the contact. A message that has already been queued is acknowledged without sending again. Responses are plain text, not JSON. The controller answers only POST; other verbs get 405. Only the account's primary admin may call it. Internal: called by the queue service behind send time optimization.","operationId":"send-optimized-automation-campaign","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automation_id":{"type":"integer","description":"ID of the automation"},"block_id":{"type":"integer","description":"ID of the send block"},"campaign_id":{"type":"integer","description":"ID of the campaign the block sends"},"contact_id":{"type":"integer","description":"ID of the contact"},"log_id":{"type":"integer","description":"ID of the automation log entry for the send"}},"required":["automation_id","block_id","campaign_id","contact_id","log_id"]}}}},"responses":{"200":{"description":"The message can no longer be acted on (for example a required field is missing), so it is acknowledged without sending. The body is a translated reason.","content":{"text/plain":{"schema":{"type":"string"}}}},"201":{"description":"The campaign was queued. Body: `Campaign queued successfully`.","content":{"text/plain":{"schema":{"type":"string"}}}},"202":{"description":"The campaign had already been queued for this message. Body: `Campaign already queued successfully`.","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"The API user is not the account's primary admin. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"The body is not JSON. The body is empty."},"500":{"description":"An unexpected error. The body is its message.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/recipeCategories":{"get":{"summary":"List automation recipe categories","description":"The recipe categories that hold at least one recipe, directly or through a child category, keyed by category ID. Internal: backs the recipe gallery's category filter.","operationId":"list-automation-recipe-categories","responses":{"200":{"description":"An object keyed by category ID; an empty array when there are none","content":{"application/json":{"schema":{"additionalProperties":{"properties":{"id":{"description":"ID of the category","type":"string"},"name":{"description":"Name of the category","type":"string"},"name_translation_key":{"description":"Translation key of the name","type":["string","null"]},"parentid":{"description":"ID of the parent category; `0` for a top-level one","type":"string"}},"type":"object"}},"example":{"3":{"id":"3","name":"Ecommerce","name_translation_key":null,"parentid":"0"}}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/recipeFavorites":{"get":{"summary":"List the account's favorite automation recipes","description":"IDs of the recipes marked as favorites. Favorites are shared by every user of the account, not per user. Internal: backs the recipe gallery's favorites.","operationId":"list-automation-recipe-favorites","responses":{"200":{"description":"The favorite recipe IDs","content":{"application/json":{"schema":{"type":"array","items":{"description":"ID of a recipe","type":["string","integer"]}},"example":["12","40"]}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/recipeImport":{"get":{"summary":"List which shared automation recipes the account has imported","description":"The account's records of automations imported from shared recipes, optionally limited to some share hashes. Internal: the getting-started checklist uses it to tell which recommended recipes were set up.","operationId":"list-imported-automation-recipes","x-canonical-resource":"automation","parameters":[{"name":"tplHashes","in":"query","description":"Only these share hashes, as `tplHashes[]=<hash>`","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"The import records. A list when there are some; an empty object `{}` when there are none.","content":{"application/json":{"schema":{"type":["array","object"],"items":{"type":"object","properties":{"account_id":{"type":"string","description":"ID of the account"},"tplshare_id":{"type":"string","description":"ID of the shared recipe"},"series_id":{"type":"string","description":"ID of the automation the import created"},"hash":{"type":"string","description":"Share hash of the recipe"}}}}}}},"405":{"description":"A verb other than GET. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}}},"x-internal":true}},"/automations/recipeModal":{"get":{"summary":"List every automation recipe with categories and favorites","description":"The whole recipe gallery in one response, unpaged: the recipe categories, every visible stock recipe followed by the account's purchased recipes, and the account's favorite recipe IDs. GET /automations/recipes, /recipeCategories and /recipeFavorites return the same data in parts, with paging and filters. Internal: backs the recipe picker.","operationId":"list-automation-recipe-gallery","x-canonical-resource":"automation","responses":{"200":{"description":"The gallery","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"description":"Recipe categories keyed by category ID (id, name, name_translation_key, parentid); an empty array when there are none"},"automations":{"type":"array","description":"Stock recipes, then purchased recipes","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the recipe"},"name":{"type":"string","description":"Name of the recipe"},"description":{"type":["string","null"],"description":"Description of the recipe"},"image":{"type":["string","null"],"description":"Image URL"},"hash":{"type":["string","null"],"description":"Share hash, the path of the share link POST /automations/import takes"},"categories":{"type":["string","null"],"description":"Comma-separated recipe category IDs; `purchased` for a purchased recipe"},"purchased":{"type":"string","description":"`1` for a purchased recipe, `0` for a stock recipe"}}}},"favorites":{"type":"array","description":"IDs of the account's favorite recipes","items":{"type":["string","integer"]}}}}}}},"405":{"description":"A verb other than GET. The body is empty."}},"x-internal":true}},"/automations/recipes":{"get":{"summary":"List automation recipes","description":"The visible stock automation recipes, filtered and paged, followed by every recipe the account has purchased. Purchased recipes are appended to every page and are not counted in `total`. For accounts with deals but no campaigns, a configured set of sales recipes is moved to the front of the page. Internal: backs the recipe gallery.","operationId":"list-automation-recipes","parameters":[{"name":"offset","in":"query","description":"Rows to skip. Paging applies only when both `offset` and `limit` are sent; a negative value becomes 0.","required":false,"schema":{"type":"integer"}},{"name":"limit","in":"query","description":"Recipes per page. Paging applies only when both `offset` and `limit` are sent; a negative value becomes 20.","required":false,"schema":{"type":"integer"}},{"name":"search","in":"query","description":"Only recipes whose name contains this text","required":false,"schema":{"type":"string"}},{"name":"category","in":"query","description":"Only recipes in this recipe category (an ID from GET /automations/recipeCategories); 0 or less means no filter","required":false,"schema":{"type":"integer"}},{"name":"language","in":"query","description":"Only recipes in this language. `english` and `english - uk` leave out recipes in the other languages' categories. Any other value means `any`.","required":false,"schema":{"type":"string","default":"any","enum":["any","english","english - uk","french","german","italian","portuguese","portuguese - brazil","spanish"]}}],"responses":{"200":{"description":"A page of recipes","content":{"application/json":{"schema":{"properties":{"automations":{"type":"array","items":{"properties":{"id":{"description":"ID of the recipe","type":"string"},"name":{"description":"Name of the recipe","type":"string"},"description":{"description":"Description of the recipe","type":["string","null"]},"name_translation_key":{"description":"Translation key of the name; stock recipes only","type":["string","null"]},"description_translation_key":{"description":"Translation key of the description; stock recipes only","type":["string","null"]},"image":{"description":"Image URL","type":["string","null"]},"hash":{"description":"Share hash, the path of the share link POST /automations/import takes","type":["string","null"]},"categories":{"description":"Comma-separated recipe category IDs; `purchased` for a purchased recipe","type":["string","null"]},"purchased":{"description":"`1` for a purchased recipe, `0` for a stock recipe","type":"string"},"authorid":{"description":"Purchased recipes only: ID of the author","type":"string"},"authorslug":{"description":"Purchased recipes only: the author's slug","type":"string"},"authorimage":{"description":"Purchased recipes only: the author's image URL","type":"string"}},"type":"object"}},"total":{"description":"Number of stock recipes matching the filters","type":"integer"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/screenshots":{"put":{"summary":"Refresh the preview images of automations","description":"Asks the screenshot service to re-render the preview image of each automation in the list, updating the stored image link. The response body is empty. Internal: backs refreshing automation previews in the app.","operationId":"refresh-automation-screenshots","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"integer"},"description":"IDs of the automations","example":[87,83]}}},"description":"A JSON array of automation IDs, not an object"},"responses":{"200":{"description":"The screenshots were requested. The body is empty."},"400":{"description":"The body is empty, not JSON, or an empty array. The body is empty."},"405":{"description":"A verb other than PUT. The body is empty."}},"x-internal":true}},"/automations/series_copy":{"post":{"summary":"Copy an automation","description":"Creates a copy of an automation, named with a copy suffix and saved as a draft, or as inactive when the original is not a draft, then copies its blocks and campaigns in a background process. Poll GET /automations/copy-status/{processId} with the returned `processId`. A refusal after the permission check (no permission to add, unknown automation) is answered with HTTP 200 and `succeeded: 0`. Internal: backs Copy in the automation list.","operationId":"copy-an-automation","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"seriesid":{"type":"integer","description":"ID of the automation to copy"},"ai":{"type":"boolean","description":"Record the copy's source as the AI agent copy instead of a plain copy; `true`, `1`, `on` or `yes` count as true","default":false}},"required":["seriesid"]}}},"description":"Form-encoded, as the app sends it; the same fields are also read from the query string"},"responses":{"200":{"description":"The copy was queued (`succeeded: 1` with `newid` and `processId`), or refused (`succeeded: 0` with a translated `message`): the user may not add automations, or there is no automation with this ID","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"1 on success, 0 on failure","enum":[0,1]},"message":{"type":"string","description":"Translated message"},"newid":{"type":"integer","description":"On success: ID of the new automation"},"processId":{"type":"integer","description":"On success: ID of the copy process"}}}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"`seriesid` is missing or 0. The body is a translated plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/seriesdate":{"post":{"summary":"Run the date and RSS automation trigger checks","description":"Runs one pass of the scheduled job that starts contacts on automations with date-based or RSS-based triggers, as the scheduled job would. A test hook, meant only for internal end-to-end tests. It needs an `Authorization: Bearer` token carrying the configured job secret, besides the API session. The response is always empty: the outcome the controller computes, including its 422 for an unknown `type`, is not sent. Internal: end-to-end test support.","operationId":"run-automation-date-trigger-check","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":true,"parameters":[{"name":"type","in":"query","description":"Which triggers to check: `date`, `rssTimeOfDay` or `rssHourly`. Read from the query string or a form-encoded body; leaving it out fails with a server error.","schema":{"type":"string","enum":["date","rssTimeOfDay","rssHourly"]},"required":true}],"responses":{"200":{"description":"The pass ran, or `type` was not one of the three; the body is empty either way."},"403":{"description":"The bearer token is missing or does not carry the secret. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than POST. The body is empty."}},"x-internal":true}},"/automations/serieslist/{seriesid}":{"get":{"summary":"List the lists associated with an automation","description":"The lists an automation is associated with and how each got there: chosen by the user, implied by a list-based start trigger, or all lists because the automation has neither. Unknown sub-paths of /automations/serieslist are answered 403. Internal: backs the automation builder's list settings.","operationId":"list-automation-lists","x-canonical-resource":"automation","parameters":[{"name":"seriesid","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The associations","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the association"},"seriesid":{"type":"string","description":"ID of the automation"},"listId":{"type":"string","description":"ID of the list"},"origin":{"type":["string","integer"],"description":"0 implied by a start trigger, 1 chosen by the user, 2 all lists (no lists chosen and no list-based trigger)"}}}}}}},"400":{"description":"An unexpected error. Body: `{\"error\": \"<message>\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}},"404":{"description":"No automation with this ID. Body: `{\"error\": \"Specified Series ID doesn't exist\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}},"405":{"description":"A verb other than GET, POST or DELETE. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}}},"x-internal":true},"post":{"summary":"Set the lists associated with an automation","description":"Replaces the automation's list associations: the lists sent are stored as chosen by the user, and the lists its start triggers imply are added; with no lists sent and no list-based trigger, every non-SMS list is associated. The same lists are then associated with the automation's campaigns and segments. Internal: backs the automation builder's list settings.","operationId":"set-automation-lists","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"seriesid","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lists":{"type":"array","description":"The lists the user chose; may be empty","items":{"type":"object","properties":{"listid":{"type":"integer","description":"ID of a list"}},"required":["listid"]}}},"required":["lists"],"example":{"lists":[{"listid":1},{"listid":3}]}}}}},"responses":{"201":{"description":"The stored associations","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the association"},"seriesid":{"type":"string","description":"ID of the automation"},"listid":{"type":"string","description":"ID of the list"},"origin":{"type":["string","integer"],"description":"1 chosen by the user, 0 added automatically"}}}}}}},"400":{"description":"An unexpected error. Body: `{\"error\": \"<message>\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}},"404":{"description":"No automation with this ID. Body: `{\"error\": \"Specified Series ID doesn't exist\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}},"422":{"description":"The body has no `lists` (empty body), or a list does not exist (`{\"error\": \"One or more List Ids don't exist\"}`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}}},"x-internal":true},"delete":{"summary":"Remove every list association of an automation","description":"Deletes all list associations of the automation and of its campaigns and segments. Internal: backs the automation builder's list settings.","operationId":"delete-automation-lists","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"seriesid","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Removed. The body is empty."},"400":{"description":"An unexpected error. Body: `{\"error\": \"<message>\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}},"404":{"description":"No automation with this ID. Body: `{\"error\": \"Specified Series ID doesn't exist\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong"}}}}}}},"x-internal":true}},"/automations/share_series":{"get":{"summary":"Create a share link for an automation","description":"Stores the automation's current blocks and triggers as a template share and returns its link, which POST /automations/import accepts. A GET that writes. Failures are answered with HTTP 200 and `succeeded: 0`: no automation with this ID, an automation that cannot be shared (for example one with AI dynamic data blocks or custom object triggers, or franchise-only segments), an archive over the size limit, or an error while exporting. Internal: backs Share in the automation list.","operationId":"share-an-automation","x-canonical-resource":"automation","parameters":[{"name":"seriesid","in":"query","description":"ID of the automation to share. Read from the query string or a form-encoded body.","schema":{"type":"integer"},"required":true}],"responses":{"200":{"description":"The link (`succeeded: 1`), or why the automation was not shared (`succeeded: 0`)","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"1 on success, 0 on failure","enum":[0,1]},"message":{"type":"string","description":"Translated message"},"url":{"type":"string","description":"On success: the share link, `https://<template-share host>/<hash>`"},"title":{"type":"string","description":"On some failures: a translated title for the error dialog"},"errorCode":{"type":"string","description":"On some failures: a machine-readable reason, e.g. `FILE_SIZE_EXCEEDED`"}}}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than GET. The body is empty."},"422":{"description":"`seriesid` is missing or 0. The body is a translated plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/start":{"post":{"summary":"Start automations for contacts","description":"For each entry, starts the given contact on the given automation, optionally through a specific start trigger. An entry may name the contact by `contactEmail` instead of `contactId`. The controller answers only POST; other verbs get 405. Entries that cannot be processed do not fail the request: they are listed under `invalid` or `error` in a 200 response. Only the account's primary admin may call it. Internal: a batch entry point for automation starts, not public API.","operationId":"start-contacts-on-automations","x-canonical-resource":"contactAutomations","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","description":"The starts","items":{"type":"object","properties":{"id":{"type":["string","integer"],"description":"Caller's ID for the entry, echoed in the result lists"},"contactId":{"type":"integer","description":"ID of the contact; required unless `contactEmail` finds one"},"contactEmail":{"type":"string","description":"Email of the contact, used when `contactId` is empty"},"automationId":{"type":"integer","description":"ID of the automation"},"startTriggerId":{"type":"integer","description":"ID of the start trigger the contact enters through; 0 or left out for none"},"context":{"type":"object","description":"Context passed to the start processor; empty when left out"},"noop":{"type":"boolean","description":"Skip this entry; it is reported under `noop`"},"downstreamBlacklist":{"type":"string","description":"Pipe-separated services that must not process the entry; `hosted` skips it"}},"required":["id","automationId"]}}},"required":["entries"]}}}},"responses":{"200":{"description":"The outcome of each entry","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"array","description":"Entries processed","items":{}},"invalid":{"type":"array","description":"Entries rejected as invalid (a required field missing, an unknown contact or automation)","items":{}},"error":{"type":"array","description":"Entries that failed with an unexpected error","items":{}},"noop":{"type":"array","description":"Entries skipped because they were marked `noop` or have `hosted` in `downstreamBlacklist`","items":{}}},"description":"Each list holds the `id` of every entry in that outcome, or the whole entry when it has no `id`"}}}},"403":{"description":"The user lacks the manage-automations permission (body `{\"success\": 0, \"message\": \"<translated message>\"}`), or the API user is not the account's primary admin (an `errors` array).","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"success":{"type":"integer","description":"Always 0"},"message":{"type":"string","description":"Translated message"}}},{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}]}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"The body has no `entries` list. The body is empty."}},"x-internal":true}},"/automations/startsPrimaryContactOnly":{"put":{"summary":"Turn off primary-contact-only on an automation trigger","description":"Makes a start trigger that fires for the primary contact only fire for every matching contact, and returns the automation's start block as the builder draws it. The only change it accepts is `primary_contact_only: false`; a trigger that is already multi-contact is left as it is. Internal: backs the automation builder's trigger settings.","operationId":"disable-automation-trigger-primary-contact-only","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"startid","in":"query","description":"ID of the start trigger. Read from the query string or a form-encoded body.","schema":{"type":"integer"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"primary_contact_only":{"type":"boolean","description":"Must be `false`","enum":[false]}},"required":["primary_contact_only"],"example":{"primary_contact_only":false}}}}},"responses":{"200":{"description":"The trigger now fires for every matching contact","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"Always 1"},"block":{"type":"object","description":"The automation's start block, prepared as the builder reads it"}}}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"404":{"description":"No trigger with this ID (detail `Automation not found`), or its automation has no start block (`Automation action not found`). Body: an `errors` array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"405":{"description":"A verb other than PUT. The body is empty."},"422":{"description":"The body is empty or not JSON (a translated message), or it does not set `primary_contact_only` to false (`Invalid operation: the only valid input is to set primary_contact_only to false`). The body is plain text, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/triggers":{"get":{"summary":"List the start trigger types the automation builder offers","description":"The start trigger catalog for the account: the built-in triggers, field, SMS, WhatsApp, scheduled, bounce and contact-created triggers, triggers of connected and available apps, and custom object triggers, filtered by the account's entitlements, together with the categories the trigger picker groups them under. Names and descriptions of built-in entries are translation keys, not text. Not the triggers of one automation: that is GET /automations/{id}/triggers. Internal: backs the automation builder's trigger picker.","operationId":"list-automation-trigger-types","responses":{"200":{"description":"The trigger catalog","content":{"application/json":{"schema":{"properties":{"data":{"properties":{"triggers":{"type":"array","items":{"properties":{"id":{"description":"Trigger type, e.g. `subscribe`; `layer` for an app trigger","type":"string","example":"subscribe"},"name":{"description":"Translation key of the trigger's name","type":"string"},"filter":{"description":"IDs of the categories the trigger appears in; every trigger except an unconnected app's also has `view-all`","type":"array","items":{"type":"string"}},"descript":{"description":"Translation key of the trigger's description; null for app triggers","type":["string","null"]},"description":{"description":"Description text of an app trigger; null for the others","type":["string","null"]},"uses":{"description":"Use-case tags","type":"array","items":{"type":"string"}},"added":{"description":"Date the trigger was added, as written in code (Y-m-d or Y-d-m) or the app's creation date","type":["string","null"]},"requires":{"description":"What the account needs before the trigger can be used: a translation key in `label`, with an optional `link` and `link-label`","type":"object"},"resources":{"description":"Extra data for the trigger; for an app trigger, the app's record under `cxa`","type":"object"},"path":{"description":"Icon URL of an app trigger; empty for the others","type":"string"}},"type":"object"}},"categories":{"type":"array","items":{"properties":{"id":{"description":"Category ID, referenced by `filter`","type":"string","example":"contact"},"label":{"description":"Translation key of the category name, or an app's name","type":"string"},"description":{"description":"Translation key of the category description","type":["string","null"]},"section":{"description":"Picker section the category belongs to, e.g. `standard`","type":"string"},"icon":{"description":"Icon URL, for app categories","type":["string","null"]},"weight":{"description":"Sort weight","type":"integer"}},"type":"object"}}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/ui/contactfields":{"get":{"summary":"List the contact fields the automation builder offers","description":"Standard and custom contact fields, with the options of custom fields, for the automation builder's field pickers. Titles of standard fields are translated. Only GET is routed; unknown sub-paths of /automations/ui are answered 403. Internal: backs the automation builder.","operationId":"list-automation-builder-contact-fields","x-canonical-resource":"automation","parameters":[{"name":"filters[category]","in":"query","description":"Comma-separated: `standard`, `custom`. Both when left out.","schema":{"type":"string"}},{"name":"filters[type]","in":"query","description":"Comma-separated field types to keep, e.g. `text,date`","schema":{"type":"string"}},{"name":"filters[excludes]","in":"query","description":"Comma-separated field IDs or titles to leave out","schema":{"type":"string"}}],"responses":{"200":{"description":"The fields","content":{"application/json":{"schema":{"type":"object","properties":{"contactFields":{"type":"array","description":"Standard fields first, then custom fields","items":{"type":"object","properties":{"id":{"type":["string","integer"],"description":"Field ID: a column name such as `first_name` for a standard field, a number for a custom field"},"title":{"type":"string","description":"Field title"},"type":{"type":"string","description":"Field type"},"category":{"type":"string","description":"`standard` or `custom`","enum":["standard","custom"]},"perstag":{"type":"string","description":"Personalization tag; derived from the title when the field has none"},"defval":{"type":["string","null"],"description":"Default value"},"options":{"type":"array","description":"Options of a custom field with choices","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the option"},"orderid":{"type":"string","description":"Sort order"},"value":{"type":"string","description":"Stored value"},"label":{"type":"string","description":"Label"},"isdefault":{"type":"string","description":"1 when it is the default option"}}}}}}}}}}}}},"x-internal":true}},"/automations/underConfiguredBlocks":{"get":{"summary":"List blocks of active automations that are missing settings","description":"Scans the blocks of active automations whose block types have configuration rules and returns the ones missing a required setting, with a link to each automation in the builder. At most `limit` blocks are scanned; `truncated` says whether the scan stopped there. Internal: backs the under-configured automations report.","operationId":"list-under-configured-automation-blocks","parameters":[{"name":"limit","in":"query","description":"Most blocks to scan, 1 to 20000. Digits only.","required":false,"schema":{"type":"integer","default":5000,"maximum":20000,"minimum":1}}],"responses":{"200":{"description":"The blocks found","content":{"application/json":{"schema":{"properties":{"blocks":{"type":"array","items":{"properties":{"seriesId":{"description":"ID of the automation","type":"integer"},"seriesName":{"description":"Name of the automation","type":"string"},"link":{"description":"Path of the automation in the builder","type":"string"},"blockId":{"description":"ID of the block","type":"integer"},"blockType":{"description":"Block type","type":"string"},"missingParams":{"description":"Names of the required settings the block lacks","type":"array","items":{"type":"string"}}},"type":"object"}},"automationCount":{"description":"Number of distinct automations in `blocks`","type":"integer"},"blocksScanned":{"description":"Number of blocks examined","type":"integer"},"truncated":{"description":"True when the scan reached `limit`, so more blocks may be under-configured","type":"boolean"}},"type":"object"}}}},"400":{"description":"`limit` is not an integer from 1 to 20000. Body: an `errors` array."},"403":{"description":"The user may not view automations. Body: an `errors` array."}},"x-canonical-resource":"automation","x-internal":true}},"/automations/update_cx_trigger":{"post":{"summary":"Finish importing a custom object trigger","description":"Completes the import of an automation's custom object created or updated start trigger once the app it needs is connected, mapping the trigger to the connected app's schema. Without the manage-automations permission the answer is HTTP 200 with `succeeded: 0`. Internal: backs the import mapping of custom object triggers.","operationId":"complete-automation-custom-object-trigger-import","x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"seriesid":{"type":"integer","description":"ID of the automation; read from the query string or a form-encoded body when left out of the JSON"},"startid":{"type":"integer","description":"ID of the start trigger; read from the query string or a form-encoded body when left out of the JSON"}},"example":{"seriesid":312,"startid":940}}}},"description":"A JSON object. A body that is not a JSON object fails the request."},"responses":{"200":{"description":"The trigger was mapped (`succeeded: 1`), or the user lacks the manage-automations permission (`succeeded: 0`)","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"1 on success, 0 on failure","enum":[0,1]},"message":{"type":"string","description":"Translated message"}}}}}},"405":{"description":"A verb other than POST. The body is empty."},"422":{"description":"The import could not be completed. The body is the JSON text `{\"succeeded\":0,\"message\":\"<reason>\"}`, sent as a 422 error.","content":{"text/plain":{"schema":{"type":"string"}}}}},"x-internal":true}},"/automations/validateBlock/{blockId}":{"get":{"summary":"Check that an automation block can run","description":"Validates one block against its automation's start triggers. Send email blocks are checked for a campaign and for custom object personalization tags that a custom object trigger can supply; outbound email blocks are checked against the triggers too; other block types always pass. The controller answers only GET. Internal: backs the automation builder's block checks.","operationId":"validate-an-automation-block","x-canonical-resource":"automation","parameters":[{"name":"blockId","in":"path","description":"ID of the block","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The block is valid","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"integer","description":"Always 1"}}},"example":{"success":1}}}},"404":{"description":"No block with this ID. Body: `{\"message\": \"No block with id 12 found\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Translated message"}}}}}},"405":{"description":"A verb other than GET. Body: an `errors` array, title `Method Not Allowed`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}},"422":{"description":"The block fails validation (the body is the plain-text reason, e.g. `No campaign found for send email block`), or `blockId` is not an integer (an `errors` array, title `Invalid Input Parameter`).","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"HTTP status"},"title":{"type":"string","description":"Short title; present for some errors"},"detail":{"type":"string","description":"What went wrong"}}}}}}}}}},"x-internal":true}},"/automations/{id}":{"get":{"summary":"Retrieve an automation","description":"Returns one automation's metadata (name, status, id). It does not include triggers, actions, or conditions. Use GET /automations with the search query parameter to find an automation by name when the id is not known, then call GET /automations/{id}/blocks for its contents. A row from GET /automations is not that automation unless its id matches the id you asked for.","operationId":"retrieve-an-automation","x-canonical-resource":"automation","parameters":[{"name":"id","in":"path","description":"ID of the automation to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"0 = Draft, 1 = Active, 2 = Inactive, 3 = Paused."}}}}}}}}},"deprecated":false},"put":{"summary":"Update an automation","description":"Changes an automation's name, description and entry/exit settings. It does not change the status (use POST /automations/bulk_edit) or the workflow itself. Internal: backs the automation builder's settings panel.","operationId":"update-an-automation","parameters":[{"name":"id","in":"path","description":"ID of the automation to update","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"The fields to change, wrapped in an `automation` object. Only `name`, `description`, `exit_on_unsubscribe`, `exit_on_conversion` and `multientry` are written; any other key (status, hidden, entered, ...) is ignored without an error, and a field left out keeps its value. `mdate` is set to now on every call.","required":true,"content":{"application/json":{"schema":{"required":["automation"],"properties":{"automation":{"properties":{"name":{"description":"Name of the automation","type":"string","example":"Welcome series"},"description":{"description":"Free-text description of the automation","type":"string"},"exit_on_unsubscribe":{"description":"1 to end a contact's run when the contact unsubscribes, 0 to keep it running","type":"integer","enum":[0,1],"example":0},"exit_on_conversion":{"description":"1 to end a contact's run when a conversion attributed to the automation is recorded for the contact, 0 to keep it running","type":"integer","enum":[0,1],"example":0},"multientry":{"description":"How often a contact may enter: 0 only once, 1 any number of times, 2 again only after exiting the previous run","type":"integer","enum":[0,1,2],"example":1}},"type":"object"}},"type":"object"},"example":{"automation":{"name":"Welcome series","multientry":0}}}}},"responses":{"200":{"description":"The updated automation, as GET /automations/{id} returns it. Fields that were sent echo the type they were sent with; the others are the stored strings.","content":{"application/json":{"schema":{"properties":{"automation":{"properties":{"id":{"description":"ID of the automation","type":"string","example":"87"},"name":{"description":"Name of the automation","type":"string"},"description":{"description":"Description of the automation","type":["string","null"]},"status":{"description":"0 draft, 1 active, 2 inactive, 3 paused. Not changed by this call.","type":"string","example":"1"},"cdate":{"description":"When the automation was created, ISO 8601 with offset","type":"string"},"mdate":{"description":"When the automation was last modified; this call sets it to now","type":"string"},"userid":{"description":"ID of the user who created the automation","type":"string"},"entered":{"description":"Number of times contacts have entered the automation","type":"string"},"exited":{"description":"Number of times contacts have exited the automation","type":"string"},"hidden":{"description":"1 when the automation is hidden from the automation list, else 0","type":"string"},"entitlements_violation":{"description":"1 when the automation uses a feature the account's plan does not include, which keeps it from being activated; else 0","type":"string"},"source":{"description":"How the automation was made: 0 from scratch, 1 copy, 2 import, 3 to 8 AI-generated flows","type":"string"},"exit_on_unsubscribe":{"description":"See the request field","type":["string","integer"]},"exit_on_conversion":{"description":"See the request field","type":["string","integer"]},"multientry":{"description":"See the request field","type":["string","integer"]},"links":{"description":"URLs of the automation's related resources (campaigns, contactGoals, contactAutomations, blocks, goals, sms, sitemessages, triggers)","type":"object"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is not a JSON object. Body: `{\"errors\": [{\"status\": \"400\", \"detail\": \"Request body must be a JSON object, ... given.\"}]}`."},"403":{"description":"The user lacks the manage-automations permission, or may not access this automation. Body: an `errors` array with one entry whose `detail` is `Forbidden`."},"404":{"description":"No automation with this ID. Body: `{\"message\": \"No Result found for Series with id <id>\"}`."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Update an automation (PATCH)","description":"PATCH is routed to the same action as PUT /automations/{id} and behaves identically: only the fields sent change. Changes an automation's name, description and entry/exit settings, not its status or workflow. Internal: backs the automation builder's settings panel.","operationId":"patch-an-automation","parameters":[{"name":"id","in":"path","description":"ID of the automation to update","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"The fields to change, wrapped in an `automation` object. Only `name`, `description`, `exit_on_unsubscribe`, `exit_on_conversion` and `multientry` are written; any other key (status, hidden, entered, ...) is ignored without an error, and a field left out keeps its value. `mdate` is set to now on every call.","required":true,"content":{"application/json":{"schema":{"required":["automation"],"properties":{"automation":{"properties":{"name":{"description":"Name of the automation","type":"string","example":"Welcome series"},"description":{"description":"Free-text description of the automation","type":"string"},"exit_on_unsubscribe":{"description":"1 to end a contact's run when the contact unsubscribes, 0 to keep it running","type":"integer","enum":[0,1],"example":0},"exit_on_conversion":{"description":"1 to end a contact's run when a conversion attributed to the automation is recorded for the contact, 0 to keep it running","type":"integer","enum":[0,1],"example":0},"multientry":{"description":"How often a contact may enter: 0 only once, 1 any number of times, 2 again only after exiting the previous run","type":"integer","enum":[0,1,2],"example":1}},"type":"object"}},"type":"object"},"example":{"automation":{"name":"Welcome series","multientry":0}}}}},"responses":{"200":{"description":"The updated automation, as GET /automations/{id} returns it. Fields that were sent echo the type they were sent with; the others are the stored strings.","content":{"application/json":{"schema":{"properties":{"automation":{"properties":{"id":{"description":"ID of the automation","type":"string","example":"87"},"name":{"description":"Name of the automation","type":"string"},"description":{"description":"Description of the automation","type":["string","null"]},"status":{"description":"0 draft, 1 active, 2 inactive, 3 paused. Not changed by this call.","type":"string","example":"1"},"cdate":{"description":"When the automation was created, ISO 8601 with offset","type":"string"},"mdate":{"description":"When the automation was last modified; this call sets it to now","type":"string"},"userid":{"description":"ID of the user who created the automation","type":"string"},"entered":{"description":"Number of times contacts have entered the automation","type":"string"},"exited":{"description":"Number of times contacts have exited the automation","type":"string"},"hidden":{"description":"1 when the automation is hidden from the automation list, else 0","type":"string"},"entitlements_violation":{"description":"1 when the automation uses a feature the account's plan does not include, which keeps it from being activated; else 0","type":"string"},"source":{"description":"How the automation was made: 0 from scratch, 1 copy, 2 import, 3 to 8 AI-generated flows","type":"string"},"exit_on_unsubscribe":{"description":"See the request field","type":["string","integer"]},"exit_on_conversion":{"description":"See the request field","type":["string","integer"]},"multientry":{"description":"See the request field","type":["string","integer"]},"links":{"description":"URLs of the automation's related resources (campaigns, contactGoals, contactAutomations, blocks, goals, sms, sitemessages, triggers)","type":"object"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body is not a JSON object. Body: `{\"errors\": [{\"status\": \"400\", \"detail\": \"Request body must be a JSON object, ... given.\"}]}`."},"403":{"description":"The user lacks the manage-automations permission, or may not access this automation. Body: an `errors` array with one entry whose `detail` is `Forbidden`."},"404":{"description":"No automation with this ID. Body: `{\"message\": \"No Result found for Series with id <id>\"}`."}},"x-canonical-resource":"automation","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/automations/{id}/blocks":{"get":{"summary":"Retrieve an automation's blocks","description":"Returns the trigger, actions, waits, conditions, and goals that make up one automation: each block's id, seriesid, parentid, ordernum, type, and params. This is the read for what is inside a single automation. It is not an account-wide list and not contact run history.","operationId":"retrieve-automation-blocks","x-canonical-resource":"automation","parameters":[{"name":"id","in":"path","description":"ID of the automation whose blocks to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"automationBlocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"seriesid":{"type":"string"},"parentid":{"type":"string"},"ordernum":{"type":"string"},"type":{"type":"string"},"params":{"type":"object"}}}}}}}}}},"deprecated":false}},"/automations/{id}/triggers":{"get":{"summary":"Retrieve an automation's start triggers","description":"Returns the start records for one automation in `automationTriggers`: each record's id, type, and params (for example a tag-added start has type `tagadd` and the tag name in `params.tag`). Use this with retrieve-automation-blocks when the start block only lists trigger ids and the goal needs how a contact enters. This is not GET /automations/triggers (the account-wide trigger-type catalog) and not contact run history.","operationId":"retrieve-automation-triggers","x-canonical-resource":"automation","parameters":[{"name":"id","in":"path","description":"ID of the automation whose start triggers to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"automationTriggers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"seriesid":{"type":"string"},"type":{"type":"string"},"params":{"type":"object"}}}}}}}}}},"deprecated":false}},"/automations/{seriesId}/blockEvents":{"get":{"summary":"List the block events of an automation","description":"Block-level events of an automation (contacts entering, completing and skipping blocks) read from the automations log service, paged with the log service's query execution ID and next token. Hosted adds to each event the contact's email (or phone) as `subjectDetail` and, for a skipped block, the saved skip reason as `skipped`, and reports an entered wait or goal block whose run is still there as `outcome: waiting`, dropping it when the run has moved on. Other event fields are the log service's. No permission check is made beyond the API session. Internal: a proxy over the automations log service, not public API.","operationId":"list-automation-block-events","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","description":"First day, Y-m-d","required":false,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","description":"Last day, Y-m-d","required":false,"schema":{"type":"string","format":"date"}},{"name":"blockType","in":"query","description":"Only events of this block type, e.g. `wait` or `send`","required":false,"schema":{"type":"string"}},{"name":"outcome","in":"query","description":"Only events with this outcome","required":false,"schema":{"type":"string","enum":["success","failure","waiting"]}},{"name":"blockId","in":"query","description":"Only events of this block. A positive integer.","required":false,"schema":{"type":"integer","minimum":1}},{"name":"subscriberFilter","in":"query","description":"Only events of contacts whose email contains this text, or whose phone matches when the text is all digits (optionally with a leading +). At most 1000 matching contacts are used; when none match, the result is empty without querying the log service.","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Events per page. A positive integer.","required":false,"schema":{"type":"integer","minimum":1}},{"name":"queryExecutionId","in":"query","description":"From `meta.queryExecutionId` of the previous page, to continue the same query","required":false,"schema":{"type":"string"}},{"name":"nextToken","in":"query","description":"From `meta.nextToken` of the previous page","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"A page of events","content":{"application/json":{"schema":{"properties":{"blockEvents":{"type":"array","items":{"properties":{"subjectId":{"description":"ID of the contact","type":["integer","string"]},"subjectDetail":{"description":"Added by Hosted: the contact's email, else phone; null when the contact no longer exists","type":["string","null"]},"automationRunId":{"description":"ID of the contact automation (the run)","type":["integer","string"]},"blockId":{"description":"ID of the block","type":["integer","string"]},"blockType":{"description":"Type of the block","type":"string"},"operation":{"description":"What happened, e.g. `BLOCK_ENTER`","type":"string"},"outcome":{"description":"Outcome of the event; Hosted sets `waiting` for a run still at a wait or goal block","type":"string"},"skipReasonId":{"description":"Present for a skipped block: ID of the saved skip reason","type":["integer","string"]},"skipped":{"description":"Added by Hosted for a skipped block whose reason is saved: `reason` and `extra`","type":"object"}},"type":"object"}},"meta":{"properties":{"queryExecutionId":{"description":"Pass back to read the next page of the same query","type":["string","null"]},"nextToken":{"description":"Pass back to read the next page; null on the last page","type":["string","null"]}},"type":"object"}},"type":"object"}}}},"422":{"description":"A query parameter is invalid: a date not in Y-m-d, an unknown `outcome`, or a `blockId` or `limit` that is not a positive integer. The log service's own 4xx errors are passed on with their status and message too.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What is wrong","type":"string"}},"type":"object"}}}},"502":{"description":"The log service answered in an unexpected format","content":{"application/json":{"schema":{"properties":{"error":{"description":"Unexpected response format from ALS","type":"string"}},"type":"object"}}}},"503":{"description":"The log service could not be reached","content":{"application/json":{"schema":{"properties":{"error":{"description":"Failed to connect to ALS","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/blockEventsAggregate":{"get":{"summary":"Aggregate the block events of an automation over a date range","description":"Event totals of an automation for a date range from the automations log service (by outcome, by block type, per block and per day), with contact counts from Hosted. When the log service cannot answer, the response is still 200: the event figures are empty and `blockEventsOmittedReason` is `als_unavailable`. The period and comparison fields are opt-in; without `includePeriodContactCounts` or `includePeriodComparison` they are absent. No permission check is made beyond the API session. Internal: read by the AI automation data agent.","operationId":"retrieve-automation-block-events-aggregate","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","description":"First day, Y-m-d","required":true,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","description":"Last day, Y-m-d, inclusive","required":true,"schema":{"type":"string","format":"date"}},{"name":"blockType","in":"query","description":"Only events of this block type, e.g. `wait` or `send`","required":false,"schema":{"type":"string"}},{"name":"outcome","in":"query","description":"Only events with this outcome","required":false,"schema":{"type":"string","enum":["success","failure","waiting"]}},{"name":"blockId","in":"query","description":"Only events of this block. A positive integer.","required":false,"schema":{"type":"integer","minimum":1}},{"name":"subscriberFilter","in":"query","description":"Only events of contacts whose email contains this text, or whose phone matches when the text is all digits (optionally with a leading +). At most 1000 matching contacts are used; when none match, the result is empty without querying the log service.","required":false,"schema":{"type":"string"}},{"name":"groupByBlock","in":"query","description":"Group the event figures by block","required":false,"schema":{"type":"boolean","default":false}},{"name":"includePeriodContactCounts","in":"query","description":"Add the lifetime, current and in-period contact counts","required":false,"schema":{"type":"boolean","default":false}},{"name":"includePeriodComparison","in":"query","description":"Add a comparison with the preceding period of the same length; implies `includePeriodContactCounts`","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The aggregate","content":{"application/json":{"schema":{"properties":{"aggregation":{"properties":{"totalEvents":{"description":"Number of events in the range","type":"integer"},"outcomeCounts":{"description":"Event counts keyed by outcome","type":"object"},"blockTypeCounts":{"description":"Event counts keyed by block type","type":"object"},"eventTriples":{"description":"Counts per block, block type and outcome, from the log service","type":"array","items":{"type":"object"}},"timeSeries":{"description":"Counts per day: `granularity` (`daily`) and `counts`","type":"object"},"uniqueContactsEntered":{"description":"Contacts that have entered the automation; null when the count timed out","type":["integer","null"]},"uniqueContactsCompleted":{"description":"Contacts that have completed it; null when the count timed out","type":["integer","null"]},"mostRecentEntryDate":{"description":"Latest entry, in UTC","type":["string","null"]},"blockEventsOmittedReason":{"description":"`als_unavailable` when the event figures are empty because the log service did not answer; null otherwise","type":["string","null"]},"skipReasonContext":{"description":"Present when `blockType` is given, unless the account's automation data is partly shed: context about why contacts skipped blocks of that type in the range","type":"object"},"lifetimeRunsEntered":{"description":"Opt-in: runs that ever entered","type":["integer","null"]},"lifetimeRunsExited":{"description":"Opt-in: runs that ever exited","type":["integer","null"]},"currentContactsInAutomation":{"description":"Opt-in: contacts in the automation now","type":["integer","null"]},"currentContactsIsEstimate":{"description":"Opt-in: whether `currentContactsInAutomation` is an estimate","type":["boolean","null"]},"periodContactsEntered":{"description":"Opt-in: contacts that entered in the range","type":["integer","null"]},"periodContactsCompleted":{"description":"Opt-in: contacts that completed in the range","type":["integer","null"]},"periodContactCountsOmittedReason":{"description":"Opt-in: why a period count is null","type":["string","null"],"enum":["range_exceeds_31_days","completed_awaiting_index","query_timeout","load_shed",null]},"periodComparison":{"description":"Opt-in with `includePeriodComparison`: `priorPeriod` (startDate, endDate) and, for `contactsEntered` and `contactsCompleted`, the `current`, `prior`, `absolute` change and `pctChange`","type":["object","null"]}},"type":"object"}},"type":"object"}}}},"422":{"description":"`startDate` or `endDate` missing or not Y-m-d, an unknown `outcome`, or a `blockId` that is not a positive integer","content":{"application/json":{"schema":{"properties":{"error":{"description":"What is wrong","type":"string"}},"type":"object"}}}},"503":{"description":"Automation data is shed for this account under high load. The response carries `Retry-After: 120`.","content":{"application/json":{"schema":{"properties":{"error":{"description":"The load-shed message","type":"string"},"code":{"description":"Always `AUTOMATION_DATA_LOAD_SHED`","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/contact/{subscriberId}/run/{subscriberSeriesId}":{"get":{"summary":"Retrieve the path one contact took through one automation run","description":"The data the automation builder's contact path view draws for one run: the contact, the run, the blocks the run passed through (from the automations log), how the run ended, and whether the automation was edited after the contact entered. No permission check is made beyond the API session. Internal: backs the builder's contact path view.","operationId":"retrieve-contact-automation-run-data","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}},{"name":"subscriberId","in":"path","description":"ID of the contact","required":true,"schema":{"type":"integer"}},{"name":"subscriberSeriesId","in":"path","description":"ID of the contact automation (the run)","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The run. When no contact has `subscriberId`, `subscriber` is null, `showsubscriber` is false and `subscriberSeriesEnd` is an empty array.","content":{"application/json":{"schema":{"properties":{"subscriber":{"description":"The contact's record (id, email, names and the other contact columns as strings), extended for the path view","properties":{"series":{"description":"The run's contact automation row (id, adddate, lastblock, status, ...), or null when the run is not found for this contact and automation","type":["object","null"]},"blocks":{"description":"One entry per logged step of the run, in order","type":"array","items":{"type":"object"}},"logsNotFound":{"description":"True when the automations log has no step for the run","type":"boolean"},"heldByPause":{"description":"True when the run is held because the automation is paused","type":"boolean"},"img":{"description":"URL of the contact's avatar image","type":"string"},"lastBlockStillExists":{"description":"False when the block the run last reached has since been deleted from the automation","type":"boolean"}},"type":["object","null"]},"showsubscriber":{"description":"True when the run was found","type":"boolean"},"subscriberSeriesEnd":{"description":"How the run ended (the end record's columns), or an empty array when it has not ended"},"automationModifiedSinceEntry":{"description":"True when the automation was edited after the contact entered, so the drawing may differ from the version the contact went through","type":"boolean"},"entryVersionCreatedAt":{"description":"When the automation version the contact entered was saved; null when the automation is unchanged since entry","type":["string","null"],"format":"date-time"}},"type":"object"}}}},"500":{"description":"Reading the run failed. Body: `{\"error\": \"<message>\"}`.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"contactAutomations","x-internal":true}},"/automations/{seriesId}/contactAutomations":{"get":{"summary":"List all contacts in an automation","description":"List the contacts currently in, or that have run through, a single automation. This is a paginated equivalent of filtering `/api/3/contactAutomations` by `filters[seriesid]`.","operationId":"list-all-contactautomations-for-automation","x-canonical-resource":"contactAutomations","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation to receive contacts for","schema":{"type":"integer","format":"int32"},"required":true},{"name":"filters[subscriberid]","in":"query","description":"Filter by contact ID. Supported operators: `eq`, `gt`, `gte`, `lt`, `lte`, `in`. Example: `filters[subscriberid][gt]=10`","schema":{"type":"integer","format":"int32"}},{"name":"filters[status]","in":"query","description":"Filter by run status: 1 = in progress, 2 = ended. Supported operators: `eq`, `gt`, `gte`, `lt`, `lte`, `in`. Example: `filters[status][gt]=1`","schema":{"type":"integer","format":"int32"}},{"name":"filters[lastblock]","in":"query","description":"Filter by the ID of the last automation block the contact reached. Supported operators: `eq`, `gt`, `gte`, `lt`, `lte`, `in`. Example: `filters[lastblock][gt]=5`","schema":{"type":"integer","format":"int32"}},{"name":"filters[adddate]","in":"query","description":"Filter by the date the contact entered the automation. Accepts `YYYY-MM-DD` (matches the whole day) or `YYYY-MM-DD HH:MM:SS`. Supported operators: `eq`, `gt`, `gte`, `lt`, `lte`, `in`. Example: `filters[adddate][gt]=2026-01-01`","schema":{"type":"string"}},{"name":"orders[adddate]","in":"query","description":"Order by the date the contact entered the automation","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[status]","in":"query","description":"Order by run status","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[seriesid]","in":"query","description":"Order by automation ID","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[subscriberid]","in":"query","description":"Order by contact ID","schema":{"type":"string","enum":["desc","asc"]}},{"name":"limit","in":"query","description":"The number of records to return per request. Defaults to 20 and is capped at 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomations\": [\n        {\n            \"contact\": \"1\",\n            \"seriesid\": \"2\",\n            \"startid\": \"0\",\n            \"status\": \"1\",\n            \"batchid\": null,\n            \"adddate\": \"2026-01-14T09:12:44-06:00\",\n            \"remdate\": null,\n            \"timespan\": null,\n            \"lastblock\": \"5\",\n            \"lastlogid\": \"31\",\n            \"lastdate\": \"2026-01-14T09:12:44-06:00\",\n            \"in_als\": \"0\",\n            \"completedElements\": \"3\",\n            \"totalElements\": \"7\",\n            \"completed\": \"0\",\n            \"completeValue\": \"42\",\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/3/contactAutomations/1/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactAutomations/1/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/contactAutomations/1/contactGoals\",\n                \"automationLogs\": \"https://:account.api-us1.com/api/3/contactAutomations/1/automationLogs\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactAutomations":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"1"},"seriesid":{"type":"string","example":"2"},"startid":{"type":"string","example":"0"},"status":{"type":"string","example":"1"},"batchid":{},"adddate":{"type":"string","example":"2026-01-14T09:12:44-06:00"},"remdate":{},"timespan":{},"lastblock":{"type":"string","example":"5"},"lastlogid":{"type":"string","example":"31"},"lastdate":{"type":"string","example":"2026-01-14T09:12:44-06:00"},"in_als":{"type":"string","example":"0"},"completedElements":{"type":"string","example":"3"},"totalElements":{"type":"string","example":"7"},"completed":{"type":"string","example":"0"},"completeValue":{"type":"string","example":"42"},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactAutomations/1/automation"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactAutomations/1/contact"},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/3/contactAutomations/1/contactGoals"},"automationLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contactAutomations/1/automationLogs"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/automations/{seriesId}/contactAutomations/{contactAutomationId}/steps":{"get":{"summary":"Retrieve recorded steps for one contact automation run","description":"Returns the steps recorded for one enrollment in an automation, including the skip reason saved for that contact when a step was skipped. Use the contact automation id from GET /contactAutomations or GET /contacts/{id}/contactAutomations. Returns 404 when the enrollment does not exist for that automation. An enrollment with no recorded steps returns an empty steps list; it does not explain why a contact never entered.","operationId":"retrieve-contact-automation-steps","parameters":[{"name":"seriesId","in":"path","description":"Automation id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"contactAutomationId","in":"path","description":"Contact automation enrollment id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recorded steps for the enrollment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationStepsResponseResource"}}}},"403":{"description":"The user may not view automations or this contact enrollment."},"404":{"description":"The enrollment was not found for this automation."}},"x-canonical-resource":"contactAutomations"}},"/automations/{seriesId}/contacts":{"get":{"summary":"List the contacts in an automation with their runs","description":"One row per contact that has entered the automation, with up to 20 of the contact's runs nested, newest entry first unless `orders` says otherwise. An automation that does not exist returns an empty page, not 404. Internal: backs the automation's Manage Contacts view.","operationId":"list-automation-contacts","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}},{"name":"limit","in":"query","description":"Contacts per page, 1 to 100","required":false,"schema":{"type":"integer","default":20,"maximum":100,"minimum":1}},{"name":"offset","in":"query","description":"Number of contacts to skip","required":false,"schema":{"type":"integer","default":0}},{"name":"search","in":"query","description":"A valid email address matches that email exactly; any other text matches part of the email, first name, last name, full name or phone","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Only contacts with a run in this state: `currently_in` (active), `queued` (held by a pause; applied only when the pause feature is on for the account), `completed`. `any` or an unknown value means no filter.","required":false,"schema":{"type":"string","default":"any","enum":["any","currently_in","queued","completed"]}},{"name":"lastEnteredFrom","in":"query","description":"Only contacts whose latest entry is at or after this date or date-time. An unparsable value is ignored.","required":false,"schema":{"type":"string"}},{"name":"lastEnteredTo","in":"query","description":"Only contacts whose latest entry is at or before this date or date-time; a bare `Y-m-d` date includes the whole day","required":false,"schema":{"type":"string"}},{"name":"lastCompletedFrom","in":"query","description":"Only contacts whose latest completion is at or after this date or date-time","required":false,"schema":{"type":"string"}},{"name":"lastCompletedTo","in":"query","description":"Only contacts whose latest completion is at or before this date or date-time; a bare `Y-m-d` date includes the whole day","required":false,"schema":{"type":"string"}},{"name":"hasDuplicates","in":"query","description":"Any value other than empty, `0`, `false`, `off` or `no` keeps only contacts with more than one active run in the automation","required":false,"schema":{"type":"string"}},{"name":"waitId","in":"query","description":"Only contacts with an active run currently at this wait block (also read as `waitid`)","required":false,"schema":{"type":"integer"}},{"name":"orders","in":"query","description":"Sort, as `orders[<field>]=ASC|DESC` with field `contact` (email, else phone), `entered`, `completed`, `currentRuns` or `totalRuns`. The first recognised field wins; the default is `orders[entered]=DESC`.","required":false,"style":"deepObject","explode":true,"schema":{"type":"object","additionalProperties":{"type":"string","enum":["ASC","DESC"]}}}],"responses":{"200":{"description":"A page of contacts","content":{"application/json":{"schema":{"properties":{"contacts":{"type":"array","items":{"properties":{"contactId":{"description":"ID of the contact","type":"integer"},"email":{"description":"The contact's email","type":["string","null"]},"phone":{"description":"The contact's phone","type":["string","null"]},"firstName":{"description":"The contact's first name","type":["string","null"]},"lastName":{"description":"The contact's last name","type":["string","null"]},"trigger":{"description":"Title of the trigger that started the contact's latest run, or the manual-entry title","type":"string"},"entered":{"description":"When the contact last entered","type":["string","null"],"format":"date-time"},"completed":{"description":"When the contact last completed a run","type":["string","null"],"format":"date-time"},"currentRuns":{"description":"Number of the contact's active runs","type":"integer"},"totalRuns":{"description":"Number of the contact's runs","type":"integer"},"runs":{"description":"Up to 20 of the contact's runs; only runs in the requested `status` when one is given","type":"array","items":{"properties":{"id":{"description":"ID of the contact automation (the run)","type":"integer"},"status":{"description":"State of the run","type":"string","enum":["currently_in","queued","completed"]},"trigger":{"description":"Title of the trigger that started the run","type":"string"},"entered":{"description":"When the run started","type":["string","null"],"format":"date-time"},"completed":{"description":"When the run ended","type":["string","null"],"format":"date-time"},"lastblock":{"description":"ID of the block the run last reached; 0 before the first","type":"integer"},"currentStep":{"description":"For a queued run, the localised text `Automation Paused - Waiting to enter`; otherwise `lastblock` as a string, or null when it is 0","type":["string","null"]}},"type":"object"}}},"type":"object"}},"total":{"description":"Number of contacts matching the filters","type":"integer"}},"type":"object"}}}},"403":{"description":"The user may not view automations. Body: an `errors` array."}},"x-canonical-resource":"contactAutomations","x-internal":true}},"/automations/{seriesId}/export":{"get":{"summary":"Export an automation as a JSON workflow","description":"Returns the automation as the JSON workflow format the automation schema builder reads and writes: its name and description, its triggers, its actions and their connections, and its branches. Available only to franchise (franchisor or franchisee) accounts with the automation pushdown feature on; every other account gets 404, as if the route did not exist. Internal: used by the franchise automation pushdown.","operationId":"export-an-automation","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation to export","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The automation as a workflow","content":{"application/json":{"schema":{"properties":{"workflow":{"properties":{"id":{"description":"ID of the automation","type":["integer","string"]},"name":{"description":"Name of the automation","type":"string"},"description":{"description":"Description of the automation","type":["string","null"]},"triggers":{"description":"The start triggers, in the workflow format","type":"array","items":{"type":"object"}},"actions":{"description":"The action blocks with their settings and the connections between them, in the workflow format","type":"array","items":{"type":"object"}},"branches":{"description":"Present only when the automation has if/else or split blocks","type":"array","items":{"type":"object"}}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user lacks the manage-automations permission. Body: an `errors` array with the message."},"404":{"description":"The account is not a franchise account, the pushdown feature is off for it, or the automation does not exist or could not be exported. Body: an `errors` array."},"422":{"description":"`seriesId` is 0 or negative. Body: an `errors` array, detail `Invalid automation ID provided.`"}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/pauseQueue":{"get":{"summary":"Retrieve how many contacts a paused automation is holding","description":"Counts of the runs a paused automation is holding and when the pause expires. Counts and timestamps only: the held contacts themselves are GET /automations/{seriesId}/contacts with `status=queued`. An automation that does not exist returns zeros and nulls, not 404. Internal: backs the paused automation banner and activate dialog.","operationId":"retrieve-automation-pause-queue","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The held runs","content":{"application/json":{"schema":{"properties":{"total":{"description":"Runs held by the pause","type":"integer"},"duplicateCount":{"description":"Held runs beyond one per contact","type":"integer"},"alreadyInAutomationCount":{"description":"Held contacts who already have another active run in the automation that is not held","type":"integer"},"pausedAt":{"description":"When the automation was paused","type":["string","null"],"format":"date-time"},"expiresAt":{"description":"When the pause expires: `pausedAt` plus the configured wait (30 days by default). Null when the automation is not paused or has a scheduled reactivation configured.","type":["string","null"],"format":"date-time"}},"type":"object"},"example":{"total":42,"duplicateCount":3,"alreadyInAutomationCount":1,"pausedAt":"2026-10-01T12:00:00+00:00","expiresAt":"2026-10-31T12:00:00+00:00"}}}},"403":{"description":"The user may not view automations. Body: an `errors` array."},"404":{"description":"The automation pause feature is off for the account. Body: an `errors` array."}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/splitData":{"get":{"summary":"Retrieve split test counts for an automation","description":"For every split block and split path in the automation, how many contacts have gone through it, and which split tests have a winner. No permission check is made beyond the API session. Internal: backs the split counts drawn in the automation builder.","operationId":"retrieve-automation-split-data","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The counts. Both members are empty arrays when the automation has no split blocks.","content":{"application/json":{"schema":{"properties":{"splitData":{"description":"An object keyed by split or split-path block ID; an empty array when the automation has no split blocks","additionalProperties":{"properties":{"contacts":{"description":"Contacts logged at this block","type":"integer"}},"type":"object"}},"winResults":{"description":"Split and split-path blocks whose split test has a winner. A list, or an object keyed by position when blocks without a winner were skipped.","additionalProperties":{"properties":{"id":{"description":"ID of the block","type":["string","integer"]},"winner":{"description":"The winner recorded on the split test that owns the block","type":["string","integer"]}},"type":"object"}}},"type":"object"},"example":{"splitData":{"101":{"contacts":40},"102":{"contacts":21},"103":{"contacts":19}},"winResults":[]}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/startModalsHtml":{"get":{"summary":"Render the automation trigger settings windows","description":"Server-rendered HTML for the start trigger settings window and the import trigger window of the automation builder, returned as strings inside JSON. The data those windows read is GET /automations/{seriesId}/startVariables. No permission check is made beyond the API session. Internal: backs the automation builder.","operationId":"retrieve-automation-start-modals-html","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The rendered windows","content":{"application/json":{"schema":{"properties":{"data":{"properties":{"modalHtml":{"description":"HTML of the start trigger settings window","type":"string"},"importModalHtml":{"description":"HTML of the trigger window used while importing an automation","type":"string"}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automations/{seriesId}/startVariables":{"get":{"summary":"Retrieve the data the automation trigger settings read","description":"The account data the start trigger blocks of the automation builder use for their titles and settings windows (lists, forms, pipelines, campaigns, fields, connections, events and the switches that decide which triggers are offered), without the HTML that GET /automations/{seriesId}/startModalsHtml renders. No permission check is made beyond the API session. Internal: backs the automation builder.","operationId":"retrieve-automation-start-variables","parameters":[{"name":"seriesId","in":"path","description":"ID of the automation; goals and site messages of this automation are left out of the counts","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The variables. A collection keyed by ID is a JSON object, or an empty array when it has no members.","content":{"application/json":{"schema":{"properties":{"data":{"properties":{"variables":{"properties":{"outboundEmails":{"description":"Outbound email blocks in the account's automations, keyed by block ID (id and a display name)"},"lists":{"description":"The account's lists"},"forms":{"description":"The account's top-level forms keyed by ID (id, name, layout)"},"pipes":{"description":"Deal pipelines keyed by ID; empty when the account has no deals"},"dealGroups":{"description":"The same deal pipelines as a list; empty when the account has no deals"},"allcampaigns":{"description":"The 20 most recent campaigns keyed by ID, special campaigns excluded"},"othersitemessages":{"description":"Site messages of other automations, keyed by ID"},"integrationList":{"description":"E-commerce connections keyed by ID"},"abandonedCartIntegrationList":{"description":"E-commerce connections that offer abandoned cart, keyed by ID"},"fields":{"description":"Contact fields available on the user's lists"},"dealCustomFields":{"description":"Date and date-time deal custom fields keyed by ID (id, title, type)"},"accountCustomFields":{"description":"Date and date-time account custom fields keyed by ID (id, title, type)"},"showDealDateTrigger":{"description":"Whether the account has deals","type":"boolean"},"siteTrackingEnabled":{"description":"Whether site tracking is on","type":"boolean"},"goallist":{"description":"Goal blocks of every automation, keyed by ID"},"connectedEmailAccounts":{"description":"Whether the user has a deal email account connected","type":"boolean"},"show_site_tracking":{"description":"Whether site tracking is on and the plan includes tracking","type":"boolean"},"event_list":{"description":"Tracked event names"},"show_events":{"description":"1 when event tracking is on, has events and the plan includes tracking, else 0","type":"integer"},"has_scores":{"description":"Number of active scores","type":"integer"},"has_goals":{"description":"Number of goal blocks in other automations","type":"integer"},"has_sitemessages":{"description":"Number of site messages of other automations","type":"integer"},"has_conversions":{"description":"Whether the account has visible conversions","type":"boolean"},"account_custom_field_meta":{"description":"Account custom fields (id, fieldlabel, fieldtype)","type":"array","items":{"type":"object"}},"account_custom_field_options":{"description":"Account custom field options (id, fieldtype, options)","type":"array","items":{"type":"object"}},"deal_custom_field_meta":{"description":"Deal custom fields (id, fieldlabel, fieldtype)","type":"array","items":{"type":"object"}},"deal_custom_field_options":{"description":"Deal custom field options (id, fieldtype, options)","type":"array","items":{"type":"object"}},"entitledToDeals":{"description":"Whether the account has deals","type":"boolean"},"entitledToOneToOneEmail":{"description":"Whether the account has one-to-one email","type":"boolean"},"customerAccountStandardFields":{"description":"Standard account fields, with the account owners as the owner field's options"}},"type":"object"}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/automationsProcess/cronBatch":{"post":{"summary":"Process batches of contacts released from automation wait steps","description":"Called back by the queue that offloads automation wait processing: each entry names a batch of contact automations (runs) that a wait step released, and every run in the batch is processed onward from that block's position, or from one position earlier when jumped says the runs jumped to a goal. Each entry is reported under exactly one result list, by its id: error when any run in it failed, otherwise success. An entry without batchId is invalid, and a batch with no runs counts as a success. The runs themselves never fail the request. Allows up to six minutes. Internal: called by the automation processing queue.","operationId":"process-automation-cron-batch","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["entries"],"properties":{"entries":{"description":"The queued entries","type":"array","items":{"properties":{"id":{"description":"ID of the queue message, echoed in the result lists","type":["string","integer"],"example":"b7c1d2"},"batchId":{"description":"The processing batch the wait step released; the runs carrying it are processed","type":"string"},"blockId":{"description":"ID of the wait block the batch was released from","type":["integer","string"],"example":230},"jumped":{"description":"True when the runs jumped to a goal: processing starts one block before it. Default false.","type":"boolean","example":false},"wait":{"description":"The wait block as the queue producer serialised it. Only fields.seriesid, fields.parentid and fields.ordernum are read.","properties":{"fields":{"description":"The wait block's stored columns","properties":{"seriesid":{"description":"ID of the automation","type":["integer","string"]},"parentid":{"description":"ID of the wait block's parent block","type":["integer","string"]},"ordernum":{"description":"Position of the wait block among its parent's children; processing continues after it","type":["integer","string"]}},"type":"object","additionalProperties":true}},"type":"object","additionalProperties":true}},"type":"object","additionalProperties":true}}},"type":"object"}}}},"responses":{"200":{"description":"Where each entry ended up, by entry id","content":{"application/json":{"schema":{"properties":{"success":{"description":"Entries whose runs were all processed, or whose batch had no runs","type":"array","items":{"type":["string","integer","null"]}},"invalid":{"description":"Entries without batchId","type":"array","items":{"type":["string","integer","null"]}},"error":{"description":"Entries with at least one run that failed, or whose batch could not be read; the queue retries these","type":"array","items":{"type":["string","integer","null"]}},"noop":{"description":"Always empty","type":"array","items":{"type":["string","integer","null"]}}},"type":"object"},"example":{"success":["b7c1d2"],"invalid":[],"error":[],"noop":[]}}}},"400":{"description":"The body is not JSON, or entries is missing or not an array","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always the same message","type":"string","example":"Invalid request format"}},"type":"object"}}}},"500":{"description":"The result could not be encoded as JSON","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always the same message","type":"string","example":"Internal server error"}},"type":"object"}}}}},"x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/bounceLogs":{"get":{"summary":"List all bounce logs","description":"Every bounce log entry on the account, one per bounced message with its timestamp, bounce code, contact and campaign. Filter to one contact with filters[subscriberid]. filters[tstamp] matches one exact timestamp, not a range, so there is no way to count bounces for a date range in one request; to bound by time, sort with orders[tstamp] and page until the entries pass the boundary. meta.total is the number of matching entries. Unknown filter keys are ignored rather than rejected, so the response can look filtered when it is not, and an operator on a known key such as filters[tstamp][gt] is applied as an exact match with that value, not as a range. 20 entries per request by default and at most 100; page with offset.","operationId":"list-all-bounce-logs","x-canonical-resource":"contact","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Return only the bounce logs of this contact id.","schema":{"type":"integer","format":"int32"}},{"name":"filters[tstamp]","in":"query","description":"Return only bounce logs recorded at exactly this timestamp. This is an exact match, not a range.","schema":{"type":"string","format":"date-time"}},{"name":"orders[tstamp]","in":"query","description":"Sort by the bounce timestamp.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limit","in":"query","description":"Number of bounce logs to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of bounce logs to skip before returning results. Use with limit to page.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The matching bounce logs and their total.","content":{"application/json":{"schema":{"type":"object","properties":{"bounceLogs":{"type":"array","items":{"type":"object","properties":{"tstamp":{"type":"string","example":"2021-05-12T11:30:06-05:00"},"bounceid":{"type":"string","example":"1"},"subscriberid":{"type":"string","example":"4"},"campaignid":{"type":"string","example":"11"},"messageid":{"type":"string","example":"12"},"codeid":{"type":"string","example":"48"},"email":{"type":"string","example":"uhOhBounced@example.com"},"error":{"type":"string","example":""},"source":{"type":"string","example":"Return-Path: <>\nReceived: from xxx.xxxx.xxxxxxc.com (unknown [XX.X.XX.XX]) ..."},"created_timestamp":{"type":"string","example":"2021-05-12 11:30:06"},"updated_timestamp":{"type":"string","example":"2021-05-12 11:30:06"},"created_by":{},"updated_by":{},"links":{"type":"object","properties":{"bounce":{"type":"string","example":"https://:account.api-us1.com/api/3/bounceLogs/23/bounce"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/bounceLogs/23/contact"},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/bounceLogs/23/campaign"},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/bounceLogs/23/message"},"code":{"type":"string","example":"https://:account.api-us1.com/api/3/bounceLogs/23/code"}}},"id":{"type":"string","example":"23"},"bounce":{"type":"string","example":"1"},"contact":{"type":"string","example":"4"},"campaign":{"type":"string","example":"11"},"message":{"type":"string","example":"12"},"code":{"type":"string","example":"48"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"description":"Number of matching bounce log entries."}}}}}}}}}}},"/bounces":{"post":{"summary":"Forward a bounce event","description":"Hands one email bounce, as classified by the bounce processors (mailparser-php and mta-bounce-processor), on for processing. The event is put on the bounce events queue of the campaign sending engine, or published to the bounce event stream when that queue is not used or the write to it fails; the call answers once the event is handed on, not once it is processed.\n\nThe body must be a complete bounce event with the JSON types shown: every field except `email` and `source` is required, and a number sent as a string, or a string sent as a number, is rejected. Fields not listed are ignored.\n\nThe request is answered while the account loads, before the API router runs, so any method with this body is handled the same way; POST is the method the route declares and the processors use.","operationId":"forward-a-bounce-event","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event_uuid","account_id","campaign_id","subscriber_id","bounce_type","code","reason","message_id","list_id","event_created_ts","event_published_ts"],"properties":{"event_uuid":{"type":"string","description":"Unique ID of the bounce event.","example":"1f0c6c1e-3b8f-4d59-9a37-2f0d7c7f5a10"},"account_id":{"type":"integer","description":"ID of the account that sent the email. Forwarded as given.","example":123},"campaign_id":{"type":"integer","description":"ID of the campaign that sent the email.","example":456},"subscriber_id":{"type":"integer","description":"ID of the contact the email bounced for.","example":789},"email":{"type":["string","null"],"description":"Address that bounced. Optional; forwarded as an empty string when left out or null.","example":"bounced@example.com"},"bounce_type":{"type":"string","description":"Kind of bounce as the bounce processor classified it, such as `hard` or `soft`.","example":"hard"},"code":{"type":"string","description":"Bounce code the processor assigned, sent as a string.","example":"550"},"reason":{"type":"string","description":"Reason the receiving server gave.","example":"Mailbox not found"},"source":{"type":"string","description":"Name of the processor that sent the event. Optional.","default":"unknown","example":"mailparser-php"},"message_id":{"type":"integer","description":"ID of the campaign message that bounced.","example":999},"list_id":{"type":"string","description":"IDs of the lists the email was sent to, comma-separated.","example":"1,2,3"},"event_created_ts":{"type":"string","description":"When the bounce occurred, as the processor reports it.","example":"2024-01-21T10:00:00Z"},"event_published_ts":{"type":"string","description":"When the processor published the event.","example":"2024-01-21T10:00:01Z"}}},"example":{"event_uuid":"1f0c6c1e-3b8f-4d59-9a37-2f0d7c7f5a10","account_id":123,"campaign_id":456,"subscriber_id":789,"email":"bounced@example.com","bounce_type":"hard","code":"550","reason":"Mailbox not found","source":"mailparser-php","message_id":999,"list_id":"1,2,3","event_created_ts":"2024-01-21T10:00:00Z","event_published_ts":"2024-01-21T10:00:01Z"}}}},"responses":{"200":{"description":"The event was accepted for processing. The body is the plain text `OK`, not JSON.","content":{"text/plain":{"schema":{"type":"string"},"example":"OK"}}},"400":{"description":"The body is not a complete bounce event, a field has the wrong type, or the event could not be handed on. Nothing was forwarded. The body is the plain text `Bad Request`, not JSON.","content":{"text/plain":{"schema":{"type":"string"},"example":"Bad Request"}}}},"deprecated":false,"x-internal":true}},"/brandings":{"get":{"summary":"List all brandings","description":"List all existing branding resources","operationId":"brandings","x-canonical-resource":"brandings","parameters":[{"name":"api_key","in":"query","description":"ActiveCampaign API key","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"brandings\": [\n    {\n\t\t\"groupid\": \"3\",\n\t\t\"siteName\": \"ActiveCampaign Email Marketing\",\n\t\t\"siteLogo\": \"http:\\/\\/mysite.com\\/logo.jpg\",\n\t\t\"siteLogoSmall\": \"http:\\/\\/mysite.com\\/logo_small.jpg\",\n\t\t\"headerTextValue\": \"my custom text header\",\n\t\t\"headerHtmlValue\": \"<p>my custom HTML header<\\/p>\",\n\t\t\"footerTextValue\": \"my custom text footer\",\n\t\t\"footerHtmlValue\": \"<p>my custom HTML footer<\\/p>\",\n\t\t\"copyright\": \"1\",\n\t\t\"version\": \"1\",\n\t\t\"license\": \"1\",\n\t\t\"links\": \"1\",\n\t\t\"help\": \"1\",\n\t\t\"adminTemplateHtm\": \"\",\n\t\t\"adminTemplateCss\": \"\",\n\t\t\"publicTemplateHtm\": \"\",\n\t\t\"publicTemplateCss\": \"\",\n\t\t\"favicon\": null,\n\t\t\"id\": \"1\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"brandings":{"type":"array","items":{"type":"object","properties":{"groupid":{"type":"string","example":"3"},"siteName":{"type":"string","example":"ActiveCampaign Email Marketing"},"siteLogo":{"type":"string","example":"http://mysite.com/logo.jpg"},"siteLogoSmall":{"type":"string","example":"http://mysite.com/logo_small.jpg"},"headerTextValue":{"type":"string","example":"my custom text header"},"headerHtmlValue":{"type":"string","example":"<p>my custom HTML header</p>"},"footerTextValue":{"type":"string","example":"my custom text footer"},"footerHtmlValue":{"type":"string","example":"<p>my custom HTML footer</p>"},"copyright":{"type":"string","example":"1"},"version":{"type":"string","example":"1"},"license":{"type":"string","example":"1"},"links":{"type":"string","example":"1"},"help":{"type":"string","example":"1"},"adminTemplateHtm":{"type":"string","example":""},"adminTemplateCss":{"type":"string","example":""},"publicTemplateHtm":{"type":"string","example":""},"publicTemplateCss":{"type":"string","example":""},"favicon":{},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/brandings/{id}":{"get":{"summary":"Retrieve a branding","description":"Retrieve an existing branding resource","operationId":"get-branding","x-canonical-resource":"brandings","parameters":[{"name":"id","in":"path","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"branding\": {\n\t\t\"groupid\": \"3\",\n\t\t\"siteName\": \"ActiveCampaign Email Marketing\",\n\t\t\"siteLogo\": \"http:\\/\\/mysite.com\\/logo.jpg\",\n\t\t\"siteLogoSmall\": \"http:\\/\\/mysite.com\\/logo_small.jpg\",\n\t\t\"headerTextValue\": \"my custom text header\",\n\t\t\"headerHtmlValue\": \"<p>my custom HTML header<\\/p>\",\n\t\t\"footerTextValue\": \"my custom text footer\",\n\t\t\"footerHtmlValue\": \"<p>my custom HTML footer<\\/p>\",\n\t\t\"copyright\": \"1\",\n\t\t\"version\": \"1\",\n\t\t\"license\": \"1\",\n\t\t\"links\": \"1\",\n\t\t\"help\": \"1\",\n\t\t\"adminTemplateHtm\": \"\",\n\t\t\"adminTemplateCss\": \"\",\n\t\t\"publicTemplateHtm\": \"\",\n\t\t\"publicTemplateCss\": \"\",\n\t\t\"favicon\": null,\n\t\t\"id\": \"1\"\n\t}\n}"}},"schema":{"type":"object","properties":{"branding":{"type":"object","properties":{"groupid":{"type":"string","example":"3"},"siteName":{"type":"string","example":"ActiveCampaign Email Marketing"},"siteLogo":{"type":"string","example":"http://mysite.com/logo.jpg"},"siteLogoSmall":{"type":"string","example":"http://mysite.com/logo_small.jpg"},"headerTextValue":{"type":"string","example":"my custom text header"},"headerHtmlValue":{"type":"string","example":"<p>my custom HTML header</p>"},"footerTextValue":{"type":"string","example":"my custom text footer"},"footerHtmlValue":{"type":"string","example":"<p>my custom HTML footer</p>"},"copyright":{"type":"string","example":"1"},"version":{"type":"string","example":"1"},"license":{"type":"string","example":"1"},"links":{"type":"string","example":"1"},"help":{"type":"string","example":"1"},"adminTemplateHtm":{"type":"string","example":""},"adminTemplateCss":{"type":"string","example":""},"publicTemplateHtm":{"type":"string","example":""},"publicTemplateCss":{"type":"string","example":""},"favicon":{},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a branding","description":"Update an existing branding resource","operationId":"update-branding","x-canonical-resource":"brandings","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Branding ID","schema":{"type":"integer","format":"int32","default":1},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"branding":{"properties":{"groupid":{"type":"integer","description":"The group ID. This value will always be 3.","default":3,"format":"int32"},"siteName":{"type":"string","description":"Title of software. Example: 'ActiveCampaign Email Marketing'"},"siteLogo":{"type":"string"},"siteLogoSmall":{"type":"string","description":"URL of small logo. Small logos appear in the header of the admin panel."},"headerTextValue":{"type":"string","description":"Content of non-removable header. Example: text header content"},"headerHtmlValue":{"type":"string","description":"Content of non-removable header. Example: <p>header content here</p>"},"footerTextValue":{"type":"string","description":"Content of non-removable footer. Example: text footer content"},"footerHtmlValue":{"type":"string","description":"Content of non-removable footer. Example: <p>footer content here</p>"},"copyright":{"type":"boolean","description":"unknown"},"version":{"type":"boolean","description":"unknown"},"license":{"type":"boolean","description":"unknown"},"links":{"type":"boolean","description":"External links. To enable (which is the default) exclude this parameter entirely. To disable (remove our branding), just pass this parameter with any value."},"help":{"type":"string"},"adminTemplateHtm":{"type":"string","description":"The actual HTML template (ONLY AVAILABLE FOR CERTAIN PLANS)"},"adminTemplateCss":{"type":"string","description":"The actual CSS. Example: test color: green; (ONLY AVAILABLE FOR CERTAIN PLANS)"},"publicTemplateHtm":{"type":"string","description":"The actual HTML template (ONLY AVAILABLE FOR CERTAIN PLANS)"},"publicTemplateCss":{"type":"string","description":"The actual CSS. Example: test color: green; (ONLY AVAILABLE FOR CERTAIN PLANS)"},"favicon":{"type":"string","description":"URL of the favicon."},"zendeskWidgetEnabled":{"type":["boolean","integer"]},"admin_template_htm_backup":{"type":["string","null"]},"admin_template_css_backup":{"type":["string","null"]}},"required":[],"type":"object"}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"branding\": {\n\t\t\"groupid\": \"3\",\n\t\t\"siteName\": \"ActiveCampaign Email Marketing\",\n\t\t\"siteLogo\": \"http:\\/\\/mysite.com\\/logo.jpg\",\n\t\t\"siteLogoSmall\": \"http:\\/\\/mysite.com\\/logo_small.jpg\",\n\t\t\"headerTextValue\": \"my custom text header\",\n\t\t\"headerHtmlValue\": \"<p>my custom HTML header<\\/p>\",\n\t\t\"footerTextValue\": \"my custom text footer\",\n\t\t\"footerHtmlValue\": \"<p>my custom HTML footer<\\/p>\",\n\t\t\"copyright\": \"1\",\n\t\t\"version\": \"1\",\n\t\t\"license\": \"1\",\n\t\t\"links\": \"1\",\n\t\t\"help\": \"1\",\n\t\t\"adminTemplateHtm\": \"\",\n\t\t\"adminTemplateCss\": \"\",\n\t\t\"publicTemplateHtm\": \"\",\n\t\t\"publicTemplateCss\": \"\",\n\t\t\"favicon\": null,\n\t\t\"id\": \"1\"\n\t}\n}"}},"schema":{"type":"object","properties":{"branding":{"type":"object","properties":{"groupid":{"type":"string","example":"3"},"siteName":{"type":"string","example":"ActiveCampaign Email Marketing"},"siteLogo":{"type":"string","example":"http://mysite.com/logo.jpg"},"siteLogoSmall":{"type":"string","example":"http://mysite.com/logo_small.jpg"},"headerTextValue":{"type":"string","example":"my custom text header"},"headerHtmlValue":{"type":"string","example":"<p>my custom HTML header</p>"},"footerTextValue":{"type":"string","example":"my custom text footer"},"footerHtmlValue":{"type":"string","example":"<p>my custom HTML footer</p>"},"copyright":{"type":"string","example":"1"},"version":{"type":"string","example":"1"},"license":{"type":"string","example":"1"},"links":{"type":"string","example":"1"},"help":{"type":"string","example":"1"},"adminTemplateHtm":{"type":"string","example":""},"adminTemplateCss":{"type":"string","example":""},"publicTemplateHtm":{"type":"string","example":""},"publicTemplateCss":{"type":"string","example":""},"favicon":{},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/businessGoals/data":{"get":{"summary":"List business goals (agent-oriented read)","description":"A read-optimized listing of business goals, separate from GET /initiatives/{initiativeId}. Returned directly from InitiativeAgentDataService::getInitiatives(). Conversions are always included inline for every business goal; conversion trigger detail (conversionEvents) is only populated on the single-goal endpoint, never here. Assets (automations, campaigns, forms, sms) are included inline only when includeAssets=true -- otherwise every assets list comes back empty.","operationId":"list-business-goals","parameters":[{"name":"limit","in":"query","description":"Number of business goals per page, 1 to 100.","schema":{"type":"integer"}},{"name":"page","in":"query","description":"Page to return, starting at 1.","schema":{"type":"integer"}},{"name":"isArchived","in":"query","description":"1 to list archived business goals, 0 to list active ones.","schema":{"type":"integer","enum":[0,1]}},{"name":"search","in":"query","description":"Only business goals whose name contains this text.","schema":{"type":"string"}},{"name":"includeAssociationCounts","in":"query","description":"Accepted by the underlying query DTO shared with GET /initiatives, but currently has no effect on this endpoint: InitiativeAgentDataController::getInitiatives() never reads GetInitiativesQuery::getShouldIncludeAssociationCounts(), and InitiativeAgentDataService::getInitiatives() has no parameter for it. The response never carries association counts regardless of this value.","schema":{"type":"string","default":"false"}},{"name":"includeConversionLabels","in":"query","description":"Accepted by the underlying query DTO shared with GET /initiatives, but currently has no effect on this endpoint: InitiativeAgentDataController::getInitiatives() never reads GetInitiativesQuery::getShouldIncludeConversionLabels(), and InitiativeAgentDataService::getInitiatives() has no parameter for it. Conversions are already returned inline on every business goal regardless of this value -- this flag does not gate them here (it does on GET /initiatives).","schema":{"type":"string","default":"false"}},{"name":"includeAssets","in":"query","description":"When true, each business goal's `assets` object is populated with its linked automations, campaigns, forms and SMS broadcasts. When false (default), `assets` is still present on every business goal but every list inside it is empty.","schema":{"type":"string","default":"false","enum":["true","false"]}},{"name":"useOverviewConfig","in":"query","description":"When true, results are restricted to and ordered by the account's configured goals overview sort order (falling back to favorited goals), instead of the normal paginated listing.","schema":{"type":"string","default":"0"}},{"name":"orders","in":"query","description":"A single column-to-direction mapping, e.g. `orders[created_timestamp]=DESC`. Only the first key is honored if more than one is supplied. Column must be one of `folder`, `updated_timestamp`, `created_timestamp`; direction is case-insensitive and normalized to `ASC`/`DESC`.","style":"deepObject","explode":true,"schema":{"maxProperties":1,"minProperties":1,"properties":{"folder":{"type":"string","enum":["ASC","DESC"]},"updated_timestamp":{"type":"string","enum":["ASC","DESC"]},"created_timestamp":{"type":"string","enum":["ASC","DESC"]}},"type":"object","default":{"created_timestamp":"DESC"},"additionalProperties":false}},{"name":"filters","in":"query","description":"A field-to-value map applied as additional equality filters, e.g. `filters[source]=1`. `goal_type`, `goal_value` and `conversion_target_status` resolve against the goal's linked conversion folder; every other key filters the business goal's own record directly. Keys are restricted to the set below and an unlisted key is rejected with 422. Empty string and null values are ignored.","style":"deepObject","explode":true,"schema":{"properties":{"id":{"type":"integer"},"groupid":{"type":"integer"},"folder":{"type":"string"},"color":{"type":"string"},"created_timestamp":{"type":"string"},"updated_timestamp":{"type":"string"},"created_by":{"type":"integer"},"updated_by":{"type":"integer"},"description":{"type":"string"},"is_initiative":{"type":"integer","enum":[0,1]},"is_archived":{"type":"integer","enum":[0,1]},"archived_date":{"type":"string"},"use_target_end_date":{"type":"integer","enum":[0,1]},"target_end_date":{"type":"string"},"source":{"type":"integer","enum":[0,1,2,3,4]},"template":{"type":"string"},"goal_type":{"type":"integer"},"goal_value":{"type":"number"},"conversion_target_status":{"type":"string"}},"type":"object","default":{},"additionalProperties":false}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessGoalAgentListResponse"}}}}},"x-canonical-resource":"business_goal"}},"/businessGoals/data/{initiativeId}":{"get":{"summary":"Retrieve a business goal (agent-oriented read)","description":"A read-optimized, single-record view of one business goal, separate from GET /initiatives/{initiativeId}. Returned directly from InitiativeAgentDataService::getInitiative(). Unlike the list endpoint, assets are always populated here (no includeAssets flag), and each conversion's conversionEvents (trigger detail) is always included when present.","operationId":"retrieve-business-goal-data","parameters":[{"name":"initiativeId","in":"path","description":"The business goal's id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessGoalAgentData"}}}},"404":{"description":"404 -- no business goal exists for the given initiativeId. Body shape not confirmed (thrown as AC\\Http\\Exception\\NotFoundHttpException, whose serialization is not defined in this codebase)."}},"x-canonical-resource":"business_goal"}},"/calendarRel/sync":{"post":{"summary":"Sync a calendar feed's pipeline relationships","description":"Replaces the pipelines (deal groups) a calendar feed includes with exactly the given set: relationships to the listed pipelines are created where missing, and every other relationship of the feed is deleted. The creations and deletions run in one transaction, so a failure leaves the feed's relationships unchanged. An empty calendarRel array deletes every relationship of the feed. The response's calendarRels array holds only the newly created relationships; ids of deleted relationships are returned in meta.deletedCalendarRelIds, and meta is omitted when nothing was deleted. 404 if the calendar feed does not exist. Pipeline ids are not checked against existing pipelines or the user's pipeline access, and the feed is not checked to belong to the user; no user permission is checked beyond API access. Internal: backs the calendar feed settings in the app. POST only; other methods get 405.","operationId":"sync-a-calendar-feeds-pipeline-relationships","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["calendar","calendarRel"],"properties":{"calendar":{"type":"integer","description":"ID of the calendar feed whose pipeline relationships are replaced."},"calendarRel":{"type":"array","items":{"type":"integer"},"description":"Pipeline (deal group) ids the feed must include. Every entry must be a non-zero integer; a 0 or a value that is not a number fails with 422."}}},"examples":{"Request Example":{"value":{"calendar":3,"calendarRel":[1,2]}}}}}},"responses":{"200":{"description":"The feed's new relationships, and the ids of any it deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendarRels\": [\n        {\n            \"calendar\": \"3\",\n            \"dealGroup\": 2,\n            \"cdate\": \"2026-10-15T08:53:46-05:00\",\n            \"mdate\": \"2026-10-15T08:53:46-05:00\",\n            \"links\": {\n                \"calendar\": \"https://youraccountname.api-us1.com/api/3/calendarRels/41/calendar\",\n                \"calendarRel\": \"https://youraccountname.api-us1.com/api/3/calendarRels/41/calendarRel\"\n            },\n            \"id\": \"41\"\n        }\n    ],\n    \"meta\": {\n        \"deletedCalendarRelIds\": [\n            \"40\"\n        ]\n    }\n}"}},"schema":{"type":"object","properties":{"calendarRels":{"type":"array","description":"The newly created relationships only; relationships that already existed are not repeated here. Empty when nothing was created.","items":{"type":"object","properties":{"calendar":{"description":"ID of the calendar feed.","type":"string","example":"3"},"dealGroup":{"description":"ID of the pipeline (deal group) the feed now includes.","type":"integer","example":2},"cdate":{"description":"When the relationship was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-10-15T08:53:46-05:00"},"mdate":{"description":"When the relationship was last updated, in ISO 8601 with UTC offset; the same as cdate for a new relationship.","type":"string","example":"2026-10-15T08:53:46-05:00"},"links":{"type":"object","description":"URLs of the relationship's related resources.","properties":{"calendar":{"type":"string","description":"URL of the calendar feed of this relationship."},"calendarRel":{"type":"string","description":"URL of the pipeline of this relationship."}}},"id":{"description":"ID of the new calendar feed relationship; use it with GET or DELETE /calendarRels/{id}.","type":"string","example":"41"}}}},"meta":{"type":"object","description":"Present only when relationships were deleted.","properties":{"deletedCalendarRelIds":{"description":"IDs of the calendar feed relationships this request deleted.","type":"array","items":{"type":"string"},"example":["40"]}}}}}}}},"404":{"description":"No calendar feed has the id in calendar.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Calendar with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which calendar feed id was not found.","type":"string","example":"No Result found for Calendar with id 999999"}}}}}},"422":{"description":"The body is not valid and nothing changed: calendar is missing or empty, calendarRel is missing or not an array, or calendarRel has an entry that is 0 or not a number (the response has the errors shape shown). An empty or non-JSON body also fails with 422, but with an empty response body.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"Translated message saying which rule the body broke.","type":"string"}}}}}}},"deprecated":false,"x-internal":true}},"/calendarRel/syncExcept":{"post":{"summary":"Sync a calendar feed's pipeline relationships by exclusion","description":"Makes a calendar feed include every pipeline (deal group) the API user can access except the given ones: relationships to those pipelines are created where missing, and every other relationship of the feed is deleted, including ones to the excluded pipelines and to pipelines the user cannot access. The creations and deletions run in one transaction, so a failure leaves the feed's relationships unchanged. An empty calendarRel array relates the feed to every pipeline the user can access. The response's calendarRels array holds only the newly created relationships; ids of deleted relationships are returned in meta.deletedCalendarRelIds, and meta is omitted when nothing was deleted. 404 if the calendar feed does not exist. The feed is not checked to belong to the user; no user permission is checked beyond API access. Internal: backs the calendar feed settings in the app. POST only; other methods get 405.","operationId":"sync-a-calendar-feeds-pipeline-relationships-by-exclusion","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["calendar","calendarRel"],"properties":{"calendar":{"type":"integer","description":"ID of the calendar feed whose pipeline relationships are replaced."},"calendarRel":{"type":"array","items":{"type":"integer"},"description":"Pipeline (deal group) ids the feed must NOT include. Every entry must be a non-zero integer; a 0 or a value that is not a number fails with 422."}}},"examples":{"Request Example":{"value":{"calendar":3,"calendarRel":[4]}}}}}},"responses":{"200":{"description":"The feed's new relationships, and the ids of any it deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendarRels\": [\n        {\n            \"calendar\": \"3\",\n            \"dealGroup\": 1,\n            \"cdate\": \"2026-10-15T08:53:47-05:00\",\n            \"mdate\": \"2026-10-15T08:53:47-05:00\",\n            \"links\": {\n                \"calendar\": \"https://youraccountname.api-us1.com/api/3/calendarRels/42/calendar\",\n                \"calendarRel\": \"https://youraccountname.api-us1.com/api/3/calendarRels/42/calendarRel\"\n            },\n            \"id\": \"42\"\n        }\n    ],\n    \"meta\": {\n        \"deletedCalendarRelIds\": [\n            \"41\"\n        ]\n    }\n}"}},"schema":{"type":"object","properties":{"calendarRels":{"type":"array","description":"The newly created relationships only; relationships that already existed are not repeated here. Empty when nothing was created.","items":{"type":"object","properties":{"calendar":{"description":"ID of the calendar feed.","type":"string","example":"3"},"dealGroup":{"description":"ID of the pipeline (deal group) the feed now includes.","type":"integer","example":2},"cdate":{"description":"When the relationship was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-10-15T08:53:46-05:00"},"mdate":{"description":"When the relationship was last updated, in ISO 8601 with UTC offset; the same as cdate for a new relationship.","type":"string","example":"2026-10-15T08:53:46-05:00"},"links":{"type":"object","description":"URLs of the relationship's related resources.","properties":{"calendar":{"type":"string","description":"URL of the calendar feed of this relationship."},"calendarRel":{"type":"string","description":"URL of the pipeline of this relationship."}}},"id":{"description":"ID of the new calendar feed relationship; use it with GET or DELETE /calendarRels/{id}.","type":"string","example":"41"}}}},"meta":{"type":"object","description":"Present only when relationships were deleted.","properties":{"deletedCalendarRelIds":{"description":"IDs of the calendar feed relationships this request deleted.","type":"array","items":{"type":"string"},"example":["40"]}}}}}}}},"404":{"description":"No calendar feed has the id in calendar.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Calendar with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which calendar feed id was not found.","type":"string","example":"No Result found for Calendar with id 999999"}}}}}},"422":{"description":"The body is not valid and nothing changed: calendar is missing or empty, calendarRel is missing or not an array, or calendarRel has an entry that is 0 or not a number (the response has the errors shape shown). An empty or non-JSON body also fails with 422, but with an empty response body.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"Translated message saying which rule the body broke.","type":"string"}}}}}}},"deprecated":false,"x-internal":true}},"/calendarUser/sync":{"post":{"summary":"Set the users of a calendar feed","description":"Internal: backs the user picker of a calendar feed in the app. Makes the users of the calendar feed in `calendar` exactly the users in `calendarUser`: relations to listed users are created where missing, and relations to users not listed are deleted, in one transaction. A calendar feed lists the open tasks assigned to its owner and to its calendar users, so the owner is removed from the list and never stored as a calendar user. The user IDs are not checked against existing users, and no permission is checked. Only POST is routed; other methods get 405.","operationId":"sync-calendar-users","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarUserSyncRequest"},"example":{"calendar":"1","calendarUser":["2","3"]}}}},"responses":{"200":{"description":"The calendar feed's users were updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarUserSyncResult"}}}},"404":{"description":"No calendar feed with the ID in `calendar`","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found","example":"No Result found for Calendar with id 9"}}}}}},"422":{"description":"Nothing was changed: the body is empty or not JSON (the response body is then empty), `calendar` is missing or empty, `calendarUser` is not an array, or an entry of `calendarUser` is zero or not a number. Except for an empty body, the response body is `{\"errors\": \"<message>\"}` with the message as a string.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"string","description":"What is wrong with the request"}}}}}}},"deprecated":false,"x-internal":true}},"/calendarUser/syncExcept":{"post":{"summary":"Set a calendar feed to every user except some","description":"Internal: the \"all users except\" choice of the calendar feed user picker in the app. Makes the users of the calendar feed in `calendar` every user the signed-in user can access except those in `calendarUser`: relations to those users are created where missing, and relations to the listed users are deleted, in one transaction. A calendar feed lists the open tasks assigned to its owner and to its calendar users, so the owner is removed from the list and never stored as a calendar user. No permission is checked. Only POST is routed; other methods get 405.","operationId":"sync-calendar-users-except","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarUserSyncRequest"},"example":{"calendar":"1","calendarUser":["2","3"]}}}},"responses":{"200":{"description":"The calendar feed's users were updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarUserSyncResult"}}}},"404":{"description":"No calendar feed with the ID in `calendar`","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found","example":"No Result found for Calendar with id 9"}}}}}},"422":{"description":"Nothing was changed: the body is empty or not JSON (the response body is then empty), `calendar` is missing or empty, `calendarUser` is not an array, or an entry of `calendarUser` is zero or not a number. Except for an empty body, the response body is `{\"errors\": \"<message>\"}` with the message as a string.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"string","description":"What is wrong with the request"}}}}}}},"deprecated":false,"x-internal":true}},"/calendars":{"post":{"summary":"Create a calendar feed","description":"","operationId":"create-a-calendar-feed","x-canonical-resource":"calendars","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"calendar":{"properties":{"title":{"type":"string","description":"Title of the calendar feed"},"type":{"type":"string","description":"Possible Values: 'All', 'Deals', or 'Contacts'"},"notification":{"type":"boolean","description":"Whether or not this calendar has notifications"}},"required":["title","type"],"type":"object","additionalProperties":false}}},"examples":{"Request Example":{"value":{"calendar":{"title":"Calendar Title","type":"All","notification":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendar\": {\n        \"title\": \"Calendar Title\",\n        \"type\": \"All\",\n        \"userid\": \"1\",\n        \"notification\": 1,\n        \"cdate\": \"2018-11-15T22:26:35-06:00\",\n        \"mdate\": \"2018-11-15T22:26:35-06:00\",\n        \"token\": \"0123456789abcdef0123456789abcdef\",\n        \"links\": {\n            \"calendarRels\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarRels\",\n            \"calendarUsers\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"calendar":{"type":"object","properties":{"title":{"type":"string","example":"Calendar Title"},"type":{"type":"string","example":"All"},"userid":{"type":"string","example":"1"},"notification":{"type":"integer","example":1,"default":0},"cdate":{"type":"string","example":"2018-11-15T22:26:35-06:00"},"mdate":{"type":"string","example":"2018-11-15T22:26:35-06:00"},"token":{"type":"string","example":"0123456789abcdef0123456789abcdef"},"links":{"type":"object","properties":{"calendarRels":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarRels"},"calendarUsers":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers"}}},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"get":{"summary":"List all calendar feeds","description":"","operationId":"list-all-calendar-feeds","x-canonical-resource":"calendars","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendars\": [\n        {\n            \"userid\": \"1\",\n            \"title\": \"Calendar Title\",\n            \"type\": \"All\",\n            \"token\": \"fedcba9876543210fedcba9876543210\",\n            \"notification\": \"0\",\n            \"cdate\": \"2018-11-15T22:36:05-06:00\",\n            \"mdate\": \"2018-11-15T22:36:05-06:00\",\n            \"links\": {\n                \"calendarRels\": \"https://:account.api-us1.com/api/:version/calendars/2/calendarRels\",\n                \"calendarUsers\": \"https://:account.api-us1.com/api/:version/calendars/2/calendarUsers\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"calendars":{"type":"array","items":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"title":{"type":"string","example":"Calendar Title"},"type":{"type":"string","example":"All"},"token":{"type":"string","example":"fedcba9876543210fedcba9876543210"},"notification":{"type":"string","example":"0"},"cdate":{"type":"string","example":"2018-11-15T22:36:05-06:00"},"mdate":{"type":"string","example":"2018-11-15T22:36:05-06:00"},"links":{"type":"object","properties":{"calendarRels":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/2/calendarRels"},"calendarUsers":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/2/calendarUsers"}}},"id":{"type":"string","example":"2"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/calendars/{id}":{"get":{"summary":"Retrieve a calendar feed","description":"","operationId":"list-all-calendar-feeds-1","x-canonical-resource":"calendars","parameters":[{"name":"id","in":"path","description":"ID of the calendar feed to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendar\": {\n        \"userid\": \"1\",\n        \"title\": \"Calendar Title\",\n        \"type\": \"All\",\n        \"token\": \"0123456789abcdef0123456789abcdef\",\n        \"notification\": \"1\",\n        \"cdate\": \"2018-11-15T22:26:35-06:00\",\n        \"mdate\": \"2018-11-15T22:26:35-06:00\",\n        \"links\": {\n            \"calendarRels\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarRels\",\n            \"calendarUsers\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"calendar":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"title":{"type":"string","example":"Calendar Title"},"type":{"type":"string","example":"All"},"token":{"type":"string","example":"0123456789abcdef0123456789abcdef"},"notification":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2018-11-15T22:26:35-06:00"},"mdate":{"type":"string","example":"2018-11-15T22:26:35-06:00"},"links":{"type":"object","properties":{"calendarRels":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarRels"},"calendarUsers":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers"}}},"id":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Calendar with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Calendar with id 1"}}}}}}},"deprecated":false},"put":{"summary":"Update a calendar feed","description":"","operationId":"update-a-calendar-feed","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the calendar feed to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"calendar":{"properties":{"title":{"type":"string","description":"Title of the calendar feed"},"type":{"type":"string","description":"Possible Values: 'All', 'Deals', or 'Contacts'"},"notification":{"type":"boolean","description":"Whether or not this calendar has notifications"}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"calendar":{"title":"Calendar Title","type":"Deals","notification":0}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"calendar\": {\n        \"userid\": \"1\",\n        \"title\": \"Calendar Title\",\n        \"type\": \"Deals\",\n        \"token\": \"0123456789abcdef0123456789abcdef\",\n        \"notification\": 0,\n        \"cdate\": \"2018-11-15T22:26:35-06:00\",\n        \"mdate\": \"2018-11-16T02:11:40-06:00\",\n        \"links\": {\n            \"calendarRels\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarRels\",\n            \"calendarUsers\": \"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"calendar":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"title":{"type":"string","example":"Calendar Title"},"type":{"type":"string","example":"Deals"},"token":{"type":"string","example":"0123456789abcdef0123456789abcdef"},"notification":{"type":"integer","example":0,"default":0},"cdate":{"type":"string","example":"2018-11-15T22:26:35-06:00"},"mdate":{"type":"string","example":"2018-11-16T02:11:40-06:00"},"links":{"type":"object","properties":{"calendarRels":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarRels"},"calendarUsers":{"type":"string","example":"https://:account.api-us1.com/api/:version/calendars/1/calendarUsers"}}},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a calendar feed","description":"","operationId":"remove-a-calendar-feed","x-canonical-resource":"calendars","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the calendar feed to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/campaign":{"post":{"summary":"Create Campaign","description":"","operationId":"create-campaign","requestBody":{"content":{"application/json":{"schema":{"required":["name","type"],"properties":{"name":{"description":"Name of the campaign. Required and must not be empty.","type":"string"},"type":{"description":"Type of the campaign. Required; one of single, recurring, split, responder, reminder, special, activerss or text.","type":"string"},"canSplitContent":{"description":"Whether the campaign can split its content. Stored as the campaign split_content flag; false when omitted.","type":"boolean","default":false}},"type":"object"},"examples":{"Create Campaign":{"summary":"Create a single campaign","value":{"canSplitContent":false,"type":"single","name":"Campaign Name"}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"id":{"description":"ID of the campaign that was created.","type":"integer","default":0,"example":149},"name":{"description":"Name of the campaign as stored.","type":"string","example":"Campaign Name"},"type":{"description":"Type of the campaign as stored.","type":"string","example":"single"},"canSplitContent":{"description":"Whether the campaign can split its content, as stored.","type":"boolean","default":true,"example":false}},"type":"object"},"examples":{"Result":{"summary":"The campaign as stored","value":"{\n    \"id\": 149,\n    \"name\": \"Campaign Name\",\n    \"type\": \"single\",\n    \"canSplitContent\": false\n}"}}}}},"400":{"description":"400","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One message per problem with the body: a required field that is missing or empty, a field that is not allowed, one of the wrong type, or a type outside the allowed values.","type":"array","items":{"type":"string","example":"Field name is required"}}},"type":"object"},"examples":{"Result":{"summary":"A body with no name and a type that is not a string","value":"{\n    \"errors\": [\n        \"Field name is required\",\n        \"Field type must be of type string\"\n    ]\n}"}}}}}},"deprecated":false,"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false}},"/campaign/approve":{"get":{"summary":"Continue sending a campaign after its approval","description":"Called by the campaign approvals service once a campaign held for approval has been approved, to let it send. The approval is identified by its ID and authenticated by its verification hash. Despite the GET verb this changes state. When the send was initialized by the sending engine, the approval is handed back to it to send. Otherwise the campaign is set to sending, the rest of its send runs and the campaign sent webhook fires; when that approval was already used and no newer approval of the campaign is waiting, nothing is done and the answer is still the success body. The code in the body tells the caller whether to retry: 1 is permanent, 2 is temporary. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameters are read from the query string only.","operationId":"approve-a-campaign-send","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"query","description":"ID of the account approval record, not of the campaign.","required":true,"schema":{"type":"integer"},"example":7},{"name":"hash","in":"query","description":"Verification hash of the approval, as the approval request carried it.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The approval was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignApprovalResult"},"example":{"message":"Campaign has been approved.","code":0}}}},"400":{"description":"The hash does not match the approval. Permanent: code 1.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignApprovalResult"},"example":{"message":"Invalid arguments found when trying to auto-approve a campaign.","code":1}}}},"500":{"description":"The approval could not be completed, for example on a database failure: a CampaignApprovalResult with code 2, so the caller should retry. When id or hash is missing the file never runs and the body is the generic error object instead.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CampaignApprovalResult"},{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"A generic message that names no cause.","example":"Something went wrong on our end. Please try again later"}}}]},"example":{"message":"Temporary failure trying to auto-approve a campaign.","code":2}}}}},"deprecated":false,"x-internal":true}},"/campaign/cleanup":{"get":{"summary":"Finish a campaign send","description":"Runs the cleanup at the end of a campaign send, for the sending engine. The caller names the send, because the campaign row alone does not reliably say which send is finishing. Despite the GET verb this changes state: the send totals are recorded on the campaign and its messages, the status becomes completed for a one-time campaign, scheduled for a recurring one (whose next send is scheduled) or stays stopped, the content of the sent messages is archived, carbon copies go to the addresses the lists name for them, the contacts' sent counts are updated and the send's working table is dropped. A campaign that is already completed is left as it is and still answers 200. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameters are read from the query string only.","operationId":"clean-up-a-campaign-send","x-canonical-resource":"campaign","parameters":[{"name":"campaignId","in":"query","description":"ID of the campaign whose send finished.","required":true,"schema":{"type":"integer"},"example":12},{"name":"sendId","in":"query","description":"ID of the send that finished.","required":true,"schema":{"type":"integer"},"example":345}],"responses":{"200":{"description":"The cleanup ran. The body is empty."},"500":{"description":"The cleanup failed, or a parameter is missing. A failed cleanup has an empty body; a missing parameter answers the generic error object.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"A generic message that names no cause.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/campaign/count":{"get":{"summary":"Count the recipients of a campaign","description":"The number of contacts the campaign would be sent to if it were sent now, as the campaign summary step of the legacy campaign builder shows it: the contacts on its lists, narrowed by its segment when it has one. Unlike GET /campaign/{campaignId}/final-send-count this always waits for the count. Also says whether the count is over the account sending limit. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; campaign may also be sent form-encoded.","operationId":"retrieve-campaign-recipient-count","x-canonical-resource":"campaign","parameters":[{"name":"campaign","in":"query","description":"ID of the campaign to count.","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"The recipient count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRecipientCount"},"example":{"numberOfRecipients":1250,"numberOfRecipientsFormatted":"1,250","numRecipientsPastLimit":false}}}},"403":{"description":"The account has no campaigns feature.","content":{"application/json":{"schema":{"type":"object","required":["success","message"],"properties":{"success":{"type":"integer","description":"Always 0.","example":0},"message":{"type":"string","description":"Why the request was refused, in the language of the account."},"result_code":{"type":"integer","description":"Always 0. Present only when the request carries no user.","example":0},"result_message":{"type":"string","description":"The same text as message. Present only when the request carries no user."},"result_output":{"type":"string","description":"Always json. Present only when the request carries no user.","example":"json"}}}}}},"404":{"description":"No campaign with this ID, including when campaign is missing. Body: errors, a list with one item carrying status, title and detail."}},"deprecated":false,"x-internal":true}},"/campaign/delete":{"post":{"summary":"Delete a campaign named by a form parameter","description":"The address the legacy messages page deletes a campaign through, kept for backward compatibility. It deletes the campaign exactly as DELETE /campaigns/{id} does, with the same checks, and differs only in where the ID comes from and in the success body. The ID is read from a form-encoded body or from the query string; a JSON body is not read, so it fails as a missing ID. The route declares no method: any HTTP method is answered the same way; POST is the documented verb and the one the app sends.","operationId":"delete-a-campaign-by-parameter","requestBody":{"description":"The campaign to delete. May be given in the query string instead.","required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"required":["id"],"properties":{"id":{"description":"ID of the campaign to delete, a positive whole number.","type":"integer","example":42}},"type":"object"}}}},"responses":{"200":{"description":"The campaign was deleted","content":{"application/json":{"schema":{"required":["succeeded","message"],"properties":{"succeeded":{"description":"Always 1 on a 200: a refused delete is an error status, not 0.","type":"integer","example":1},"message":{"description":"Confirmation, in the language of the account.","type":"string","example":"Campaign deleted."}},"type":"object"}}}},"403":{"description":"The account has no campaigns feature, or the user may not delete campaigns. Body: errors, a list with one item carrying status, title and detail."},"404":{"description":"No campaign with this ID, or the delete was refused for it, which includes a campaign outside the lists the user may reach; the two cannot be told apart. Body: errors, a list with one item carrying status, title and detail."},"422":{"description":"The ID is missing or not a positive whole number. Body: errors, a list with one item carrying status, title, detail and source.pointer (/data/attributes/id)."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaign/determineWinner":{"get":{"summary":"Determine the winner of a split campaign","description":"Completes a split (A/B) campaign whose split type is not even: picks the winning message by the measure the test uses and sends it to the rest of the audience. Called from outside the product, so the caller presents the campaign's verification hash, and the campaign must still be waiting for a winner: a non-even split campaign that is sending and has no winning message yet. The same work as the scheduled winner check, on demand. Despite the GET verb this changes state. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameters are read from the query string only. Errors are plain text, not JSON.","operationId":"determine-a-split-campaign-winner","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"query","description":"ID of the split campaign.","required":true,"schema":{"type":"integer"},"example":12},{"name":"hash","in":"query","description":"Verification hash of the campaign.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The winner was determined. The body is empty."},"400":{"description":"The hash does not match, or the campaign is not waiting for a winner.","content":{"text/plain":{"schema":{"type":"string","example":"Could not determine the winner of this split campaign."}}}},"500":{"description":"The winner could not be determined; the plain-text body names the error. When id or hash is missing the file never runs and the body is the generic JSON error object instead.","content":{"text/plain":{"schema":{"type":"string","example":"Error determining split campaign winner: ..."}},"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"A generic message that names no cause.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/campaign/init":{"get":{"summary":"Start initializing a campaign send","description":"For a send triggered by another service: queues the background initialization of the campaign, the step that resolves its recipients and prepares the send, and returns without waiting for it. Despite the GET verb this changes state. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameter is read from the query string only.","operationId":"initialize-a-campaign-send","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"query","description":"ID of the campaign to initialize.","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"The initialization was queued. The body is empty."},"500":{"description":"The initialization could not be queued, or id is missing. A failed queueing has an empty body; a missing id answers the generic error object.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"A generic message that names no cause.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/campaign/interactionRate":{"get":{"summary":"Retrieve the average open rate of recent campaigns","description":"The average unique open rate of the 10 most recently sent campaigns that track opens or links and reached at least one contact, as a percentage rounded to two decimals. Campaigns with a 0% rate are left out of the average; 0 when there is nothing to average. Text-only campaigns are not counted, and a user who is not an admin sees only campaigns on their lists. The value is cached for an hour per user group. Other methods are refused with 405.","operationId":"retrieve-campaign-interaction-rate","x-canonical-resource":"campaign","responses":{"200":{"description":"The rate, under meta.","content":{"application/json":{"schema":{"type":"object","required":["meta"],"properties":{"meta":{"type":"object","description":"Holds the rate.","required":["interactionRate"],"properties":{"interactionRate":{"type":"number","description":"Average unique open rate, in percent.","example":23.45}}}}},"example":{"meta":{"interactionRate":23.45}}}}},"405":{"description":"The method is not GET. The Allow header says GET. Body: errors, a list with one item carrying status and title."},"500":{"description":"The rate could not be computed. The body is empty."}},"deprecated":false,"x-internal":true}},"/campaign/interactionTrend":{"get":{"summary":"Retrieve the open rate trend of recent campaigns","description":"Chart data for the unique open rates of the most recently sent campaigns that track opens or links, newest first: one point per campaign that reached at least one contact and was opened, with the rate capped at 100. With a single point it is repeated so a line can be drawn. When no campaign was opened at all, graph holds ten placeholder values, series holds a dash for each and extras.empty is true. A user who is not an admin sees only campaigns on their lists. The result is cached for an hour per period and listid. While the recognize-external-api-calls feature flag is on for the account, the file sends nothing and the response is 200 with an empty body. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameters may also be sent form-encoded. The file also reads id, messageid, from and to, which do not change the result.","operationId":"retrieve-campaign-interaction-trend","x-canonical-resource":"campaign","parameters":[{"name":"period","in":"query","description":"Number of recently sent campaigns to chart; 10 when left out or 0.","required":false,"schema":{"type":"integer"},"example":10},{"name":"listid","in":"query","description":"ID of a list to limit the campaigns to; 0, the default, means every list the user may see.","required":false,"schema":{"type":"integer"},"example":0}],"responses":{"200":{"description":"The chart data, or an empty body while the recognize-external-api-calls feature flag is on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignInteractionTrend"}}}}},"deprecated":false,"x-internal":true}},"/campaign/subscribers":{"get":{"summary":"Send the recipients of a campaign send to the sending engine","description":"Called by the sending engine during a send: reads the recipients from the send's working table, the winner batch for the winning message of a split campaign, and forwards them to the sending engine 5,000 at a time. Nothing is returned in the response. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb; the parameters are read from the query string only.","operationId":"forward-campaign-send-subscribers","x-canonical-resource":"campaign","parameters":[{"name":"campaignId","in":"query","description":"ID of the campaign being sent.","required":true,"schema":{"type":"integer"},"example":12},{"name":"sendId","in":"query","description":"ID of the send whose recipients to forward.","required":true,"schema":{"type":"integer"},"example":345}],"responses":{"200":{"description":"The recipients were forwarded. The body is empty."},"500":{"description":"There is no such campaign, or the recipients could not be read or forwarded, with an empty body; or a parameter is missing or sendId is not a number, with the generic error object.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"A generic message that names no cause.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/campaign/{campaignId}/final-send-count":{"get":{"summary":"Retrieve the number of contacts a campaign would be sent to","description":"Counts the contacts the campaign would be sent to if it were sent now, the count the campaign summary shows before sending: the contacts on its lists, narrowed by its segment when it has one. A campaign with a segment is counted by the segment service, which can answer before the count is ready; numberOfRecipients is then null and runId names the run, which GET /campaign/{campaignId}/final-send-count/{runId} polls. Also says whether the count is over the account sending limit. Errors are plain text, not JSON.","operationId":"retrieve-campaign-final-send-count","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to count recipients for","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The recipient count, or a pending segment count run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalSendCountResult"},"example":{"numberOfRecipients":1250,"numberOfRecipientsFormatted":"1,250","numRecipientsPastLimit":false,"runId":null}}}},"400":{"description":"The segment service gave no answer for the count. The body is the plain-text message.","content":{"text/plain":{"schema":{"type":"string","example":"Did not receive a response for contact count"}}}},"404":{"description":"No campaign with this ID, or its recipients could not be resolved. The body is a plain-text sentence naming the campaign ID.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The segment count run ended without a result. The body is the plain-text message.","content":{"text/plain":{"schema":{"type":"string","example":"Segment Unable to Calculate"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaign/{campaignId}/final-send-count/{runId}":{"get":{"summary":"Poll a pending campaign recipient count","description":"The same count as GET /campaign/{campaignId}/final-send-count, for a campaign whose segment count was not ready: the runId from that response asks the segment service for the same run instead of starting a new one. While the run is still going numberOfRecipients stays null; poll again. For a campaign without a segment the runId is ignored, the lists are counted directly and the runId is echoed back. Errors are plain text, not JSON.","operationId":"retrieve-campaign-final-send-count-for-run","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to count recipients for","required":true,"schema":{"type":"integer"}},{"name":"runId","in":"path","description":"The runId returned by an earlier count of this campaign","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The recipient count, or the run still pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalSendCountResult"}}}},"400":{"description":"The segment service gave no answer for the count. The body is the plain-text message.","content":{"text/plain":{"schema":{"type":"string","example":"Did not receive a response for contact count"}}}},"404":{"description":"No campaign with this ID, or its recipients could not be resolved. The body is a plain-text sentence naming the campaign ID.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The segment count run ended without a result. The body is the plain-text message.","content":{"text/plain":{"schema":{"type":"string","example":"Segment Unable to Calculate"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaign/{campaignId}/messages":{"get":{"summary":"List the messages attached to a campaign","description":"The campaign message associations of one campaign: one for a regular campaign, one per variant for a split (A/B) campaign, each with the sending statistics kept on it. The same records as GET /campaignMessages, scoped to the campaign in the path; only access to that campaign is checked, not to each association. filters and orders have no effect on this resource. Needs the campaigns feature on the account and access to the campaign.","operationId":"list-campaign-messages-of-a-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of associations to return; 20 by default, at most 100. The string null returns up to 1000.","required":false,"schema":{"type":"integer"},"example":20},{"name":"offset","in":"query","description":"Number of associations to skip; 0 by default.","required":false,"schema":{"type":"integer"},"example":0},{"name":"ids","in":"query","description":"Comma-separated association IDs to return instead of a page; the limit becomes the number of IDs given.","required":false,"schema":{"type":"string"},"example":"1,2"},{"name":"include","in":"query","description":"Comma-separated relationships to sideload: campaign adds a campaigns list, message a messages list.","required":false,"schema":{"type":"string"},"example":"message"}],"responses":{"200":{"description":"The associations and their total","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAttachedMessageList"}}}},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-internal":true},"post":{"summary":"Add a message variant to a split campaign","description":"Adds a variant to a split (A/B) campaign the way the campaign designer does: the message in the body is copied and the copy is attached, so the association returned carries a new message ID, not the one sent. A split campaign holds at most 5 messages. Copying exposes the source message, so when it belongs to a campaign the user must be able to access that campaign too. Only messageid is read from the body. The campaign must be a split campaign in draft, scheduled, paused or disabled status. Needs the campaigns feature on the account and access to the campaign.","operationId":"attach-a-message-to-a-split-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the split campaign to add the message to","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["campaignMessage"],"properties":{"campaignMessage":{"description":"The message to copy into the campaign.","required":["messageid"],"properties":{"messageid":{"description":"ID of the message to copy, a positive whole number. A numeric string is accepted.","type":"integer","example":3}},"type":"object"}},"type":"object"},"example":{"campaignMessage":{"messageid":3}}}}},"responses":{"201":{"description":"The association of the copy that was attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAttachedMessageItem"}}}},"400":{"description":"The body has no campaignMessage object, or its messageid is not a positive whole number. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign or the campaign the source message belongs to. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"409":{"description":"The campaign is not a split campaign, is past the statuses its messages may change in, already holds 5 messages, or the message could not be copied. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/campaign/{campaignId}/messages/percentages":{"get":{"summary":"Retrieve the split percentages of a campaign","description":"The share of the recipients each message attached to the campaign is sent to, as stored on its campaign message association. Works for any campaign; only the percentages of a split (A/B) campaign mean anything. Needs the campaigns feature on the account and access to the campaign.","operationId":"retrieve-campaign-message-percentages","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The percentage of every attached message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMessagePercentages"},"example":{"campaignId":12,"messages":[{"messageId":3,"percentage":45},{"messageId":4,"percentage":45}],"meta":{"success":true}}}}},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-internal":true},"put":{"summary":"Set the split percentages of a campaign","description":"Rewrites the percentage of every message attached to a split (A/B) campaign in one call, with the rules of the campaign wizard. For an even split the values sent are ignored and every message gets an equal share, 100 divided by the number of messages and rounded. For any other split type, which sends the winning message to the rest of the audience afterwards, the percentages must add up to 99 or less. The initial split percentage of each association is set to the same value. The response is what was stored. The campaign must be a split campaign in draft, scheduled, paused or disabled status. Needs the campaigns feature on the account and access to the campaign.","operationId":"update-campaign-message-percentages","parameters":[{"name":"campaignId","in":"path","description":"ID of the split campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMessagePercentagesUpdate"},"example":{"messages":[{"messageId":3,"percentage":45},{"messageId":4,"percentage":45}]}}}},"responses":{"200":{"description":"The percentages that were stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMessagePercentages"}}}},"400":{"description":"The body has no non-empty messages list, an entry has no messageId, a messageId or percentage is not a positive whole number, the list does not cover exactly the attached messages, or the percentages break the split rules. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"409":{"description":"The campaign is not a split campaign, or is past the statuses its messages may change in. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/campaign/{campaignId}/messages/{id}":{"get":{"summary":"Retrieve one message attached to a campaign","description":"One campaign message association, by its own ID, provided it belongs to the campaign in the path: an association of another campaign is a 404 here. The same record as GET /campaignMessages/{id}. Needs the campaigns feature on the account and access to the campaign.","operationId":"retrieve-a-campaign-message-of-a-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"id","in":"path","description":"ID of the campaign message association, not of the message","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The association","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAttachedMessageItem"}}}},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID, no association with this ID, or the association belongs to another campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-internal":true},"delete":{"summary":"Remove a message variant from a campaign","description":"Removes a variant the way the campaign designer does: the association is deleted and so is the message itself, with its markup, links and files. Unlike DELETE /campaignMessages/{id}, which deletes only the association, the message is gone afterwards. The last message of a campaign cannot be removed. The campaign must be in draft, scheduled, paused or disabled status; it does not have to be a split campaign. Needs the campaigns feature on the account and access to the campaign.","operationId":"detach-a-message-from-a-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"id","in":"path","description":"ID of the campaign message association to remove, not of the message","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The message was removed","content":{"application/json":{"schema":{"required":["meta"],"properties":{"meta":{"description":"Outcome of the request.","required":["success"],"properties":{"success":{"description":"Always true on a 200.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"meta":{"success":true}}}}},"403":{"description":"The account has no campaigns feature, or the user may not access the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"404":{"description":"No campaign with this ID, no association with this ID, or the association belongs to another campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."},"409":{"description":"The campaign is past the statuses its messages may change in, or the message could not be removed, for example because it is the only message of the campaign. Body: errors, a list with one item carrying status (the HTTP status, as a string) and detail."}},"x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaign/{campaignId}/rssCheck":{"get":{"summary":"Check the RSS feeds of a campaign","description":"Fetches every RSS feed the campaign uses, the feed of an RSS-triggered campaign and the feeds in the HTML and text bodies of its messages, and reports for each whether it answered with items. Used to find a broken feed before it stops a send. The file is api/3/campaign/rssCheck.php and reads the campaign ID from the path segment after campaign, so the bare /campaign/rssCheck answers 400. Errors are plain text, not JSON.","operationId":"check-campaign-rss-feeds","x-canonical-resource":"campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign whose feeds to check.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The result of every feed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRssCheck"}}}},"400":{"description":"The ID is 0, or there is no campaign with this ID on the lists the user may see.","content":{"text/plain":{"schema":{"type":"string","example":"Bad request. No such campaign id 12"}}}},"405":{"description":"The method is not GET.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only GET supported."}}}},"500":{"description":"Checking the feeds failed. The plain-text body names the error.","content":{"text/plain":{"schema":{"type":"string","example":"Exception processing rss: ..."}}}}},"deprecated":false,"x-internal":true}},"/campaignDomainValidation/validateToken":{"post":{"summary":"Validate a sending domain verification token","description":"Verifies a sending (campaign) domain with the token from the verification email sent when the domain's validation was requested. The token must belong to a validation changed in the last 7 days, and `domain` must name the unverified domain of that validation; the domain is then marked verified. Internal: backs the domain verification page the link in the email opens. Only POST is accepted; any other method is answered 405 with an `Allow` header and a JSON `errors` list.","operationId":"validate-campaign-domain-token","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain","token"],"properties":{"domain":{"type":"string","description":"Name of the domain to verify.","example":"example.com"},"token":{"type":"string","description":"Token from the verification email.","example":"6f1c2a9e-4b7d-4c1e-9a3f-2d8b5e7c1a40"}}},"example":{"domain":"example.com","token":"6f1c2a9e-4b7d-4c1e-9a3f-2d8b5e7c1a40"}}}},"responses":{"200":{"description":"The domain is verified.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDomainValidationTokenResult"},"example":{"meta":{"success":true}}}}},"422":{"description":"The domain was not verified: see `meta.message`. Also answered, with `meta.success` true, when `token` or `domain` is missing or empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDomainValidationTokenResult"},"example":{"meta":{"success":false,"message":"Invalid Token or Domain"}}}}},"500":{"description":"The body is not a JSON object.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Generic error text.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/campaignLanguages":{"get":{"summary":"List the languages a campaign can be translated into","description":"The languages the campaign translation feature can translate a message into, each as a language code and its name. The list comes from the machine translation service the feature uses, without its automatic-detection entry, and is cached for 24 hours.","operationId":"list-all-campaign-languages","parameters":[{"name":"searchString","in":"query","description":"Only return languages whose name contains this text, ignoring case. Codes are not searched. Empty or omitted returns every language.","required":false,"schema":{"type":"string"},"example":"span"}],"responses":{"200":{"description":"The languages, in the order the translation service lists them.","content":{"application/json":{"schema":{"required":["campaignLanguages","meta"],"properties":{"campaignLanguages":{"description":"The matching languages.","type":"array","items":{"required":["code","label"],"properties":{"code":{"description":"Language code, as the translation service names it.","type":"string","example":"es-MX"},"label":{"description":"Name of the language.","type":"string","example":"Spanish (Mexico)"}},"type":"object"}},"meta":{"required":["total"],"properties":{"total":{"description":"Number of languages returned, after `searchString` is applied.","type":"integer","example":2}},"type":"object"}},"type":"object"},"example":{"campaignLanguages":[{"code":"es","label":"Spanish"},{"code":"es-MX","label":"Spanish (Mexico)"}],"meta":{"total":2}}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaignMessages":{"post":{"summary":"Create a campaign message","description":"Associate a message with a campaign, which is the association a split (A/B) campaign uses to send more than one message.\n\n`campaignid` is required; a request without it is a `400`.\n\nOnly `campaignid`, `messageid` and `percentage` may be written. Every other field of a campaign message is a counter maintained by the sending code, and is ignored when it is submitted.\n\nThe request needs the campaigns feature to be enabled for the account, and the caller has to have access to the campaign, otherwise the request is a `403`. A body without a `campaignMessage` object is a `400`.","operationId":"create-a-campaign-message","x-canonical-resource":"campaign_message","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignMessage":{"type":"object","properties":{"campaignid":{"type":"integer","format":"int32","description":"Id of the campaign the message belongs to.","example":1},"messageid":{"type":"integer","format":"int32","description":"Id of the message the campaign sends.","example":3},"percentage":{"type":"integer","format":"int32","description":"Share of the campaign's recipients this message is sent to, for a split (A/B) campaign. `PUT /campaign/{campaignId}/messages/percentages` sets the whole split in one request instead, validating that the shares add up.","example":50}},"required":["campaignid"],"additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"campaignMessage":{"campaignid":1,"messageid":3,"percentage":50}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"schema":{"type":"object","properties":{"campaignMessage":{"type":"object","properties":{"messageid":{"type":"string","description":"id of the message this row reports on","example":"3"},"campaignid":{"type":"string","description":"id of the campaign","example":"1"},"percentage":{"type":"string","description":"share of the campaign's recipients this message was sent to","example":"50"},"sourcesize":{"type":"string","description":"size of the source list at send time","example":"0"},"send_amt":{"type":"string","description":"number of sends attempted for this message","example":"500"},"total_amt":{"type":"string","description":"number of sends delivered for this message","example":"500"},"opens":{"type":"string","description":"total opens, including repeat opens","example":"241"},"uniqueopens":{"type":"string","description":"number of contacts who opened at least once","example":"180"},"linkclicks":{"type":"string","description":"total link clicks, including repeat clicks","example":"64"},"uniquelinkclicks":{"type":"string","description":"number of distinct links clicked","example":"51"},"subscriberclicks":{"type":"string","description":"number of contacts who clicked at least one link","example":"48"},"forwards":{"type":"string","description":"total forwards","example":"2"},"uniqueforwards":{"type":"string","description":"number of contacts who forwarded at least once","example":"2"},"hardbounces":{"type":"string","description":"number of hard bounces","example":"1"},"softbounces":{"type":"string","description":"number of soft bounces","example":"3"},"unsubscribes":{"type":"string","description":"number of unsubscribes","example":"2"},"unsubreasons":{"type":"string","description":"number of unsubscribes that included a reason","example":"1"},"updates":{"type":"string","description":"number of contacts who updated their profile","example":"0"},"socialshares":{"type":"string","description":"number of social shares","example":"0"},"replies":{"type":"string","description":"total replies","example":"5"},"uniquereplies":{"type":"string","description":"number of contacts who replied at least once","example":"4"},"spamcheck_score":{"type":"string","description":"spam check score, `-1` when the message has not been checked","example":"-1"},"spamcheck_max":{"type":"string","description":"maximum possible spam check score","example":"0"},"initial_split_percentage":{"type":"string","description":"split percentage this message started with","example":"50"},"verified_opens":{"type":"string","description":"opens confirmed as human","example":"241"},"verified_unique_opens":{"type":"string","description":"unique opens confirmed as human","example":"180"},"screenshot":{"type":"string","description":"URL of the rendered preview image of the message","example":"//:account.img-us3.com/_screenshot_/915e875e-c68f-4683-9ee9-5e18f947a5fd.jpeg"},"subject":{"type":"string","description":"subject line of the message","example":"Your journey starts here"},"repair_timestamp":{"type":["string","null"],"description":"timestamp of the last statistics repair, `null` when the row has never been repaired","example":null},"links":{"type":"object","properties":{"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/campaign"},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/message"}}},"id":{"type":"string","description":"id of the campaign message row","example":"1"},"campaign":{"type":"string","description":"id of the related campaign","example":"1"},"message":{"type":"string","description":"id of the related message","example":"3"}}}}}}}},"400":{"description":"400"},"403":{"description":"403"}}}},"/campaignMessages/{id}":{"delete":{"summary":"Delete a campaign message","description":"Delete the association between a campaign and a message. The message itself is not deleted; use [`DELETE /messages/{id}`](https://developers.activecampaign.com/reference/delete-a-message) for that.\n\nThe request needs the campaigns feature to be enabled for the account, and the caller has to have access to the campaign the message belongs to, otherwise the request is a `403`.","operationId":"delete-a-campaign-message","x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of the campaign message","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200"},"403":{"description":"403"},"404":{"description":"404"}}},"put":{"summary":"Update a campaign message","description":"Update the association between a campaign and a message.\n\nSubmitting a `campaignid` moves the message to that campaign, which requires access to both the campaign the message belongs to and the campaign it is moved to.\n\nOnly `campaignid`, `messageid` and `percentage` may be written. Every other field of a campaign message is a counter maintained by the sending code, and is ignored when it is submitted.\n\nThe request needs the campaigns feature to be enabled for the account, and the caller has to have access to the campaign, otherwise the request is a `403`. A body without a `campaignMessage` object is a `400`.","operationId":"update-a-campaign-message","x-canonical-resource":"campaign_message","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of the campaign message","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignMessage":{"type":"object","properties":{"campaignid":{"type":"integer","format":"int32","description":"Id of the campaign the message belongs to.","example":1},"messageid":{"type":"integer","format":"int32","description":"Id of the message the campaign sends.","example":3},"percentage":{"type":"integer","format":"int32","description":"Share of the campaign's recipients this message is sent to, for a split (A/B) campaign. `PUT /campaign/{campaignId}/messages/percentages` sets the whole split in one request instead, validating that the shares add up.","example":50}},"additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"campaignMessage":{"campaignid":1,"messageid":3,"percentage":50}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"campaignMessage":{"type":"object","properties":{"messageid":{"type":"string","description":"id of the message this row reports on","example":"3"},"campaignid":{"type":"string","description":"id of the campaign","example":"1"},"percentage":{"type":"string","description":"share of the campaign's recipients this message was sent to","example":"50"},"sourcesize":{"type":"string","description":"size of the source list at send time","example":"0"},"send_amt":{"type":"string","description":"number of sends attempted for this message","example":"500"},"total_amt":{"type":"string","description":"number of sends delivered for this message","example":"500"},"opens":{"type":"string","description":"total opens, including repeat opens","example":"241"},"uniqueopens":{"type":"string","description":"number of contacts who opened at least once","example":"180"},"linkclicks":{"type":"string","description":"total link clicks, including repeat clicks","example":"64"},"uniquelinkclicks":{"type":"string","description":"number of distinct links clicked","example":"51"},"subscriberclicks":{"type":"string","description":"number of contacts who clicked at least one link","example":"48"},"forwards":{"type":"string","description":"total forwards","example":"2"},"uniqueforwards":{"type":"string","description":"number of contacts who forwarded at least once","example":"2"},"hardbounces":{"type":"string","description":"number of hard bounces","example":"1"},"softbounces":{"type":"string","description":"number of soft bounces","example":"3"},"unsubscribes":{"type":"string","description":"number of unsubscribes","example":"2"},"unsubreasons":{"type":"string","description":"number of unsubscribes that included a reason","example":"1"},"updates":{"type":"string","description":"number of contacts who updated their profile","example":"0"},"socialshares":{"type":"string","description":"number of social shares","example":"0"},"replies":{"type":"string","description":"total replies","example":"5"},"uniquereplies":{"type":"string","description":"number of contacts who replied at least once","example":"4"},"spamcheck_score":{"type":"string","description":"spam check score, `-1` when the message has not been checked","example":"-1"},"spamcheck_max":{"type":"string","description":"maximum possible spam check score","example":"0"},"initial_split_percentage":{"type":"string","description":"split percentage this message started with","example":"50"},"verified_opens":{"type":"string","description":"opens confirmed as human","example":"241"},"verified_unique_opens":{"type":"string","description":"unique opens confirmed as human","example":"180"},"screenshot":{"type":"string","description":"URL of the rendered preview image of the message","example":"//:account.img-us3.com/_screenshot_/915e875e-c68f-4683-9ee9-5e18f947a5fd.jpeg"},"subject":{"type":"string","description":"subject line of the message","example":"Your journey starts here"},"repair_timestamp":{"type":["string","null"],"description":"timestamp of the last statistics repair, `null` when the row has never been repaired","example":null},"links":{"type":"object","properties":{"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/campaign"},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/message"}}},"id":{"type":"string","description":"id of the campaign message row","example":"1"},"campaign":{"type":"string","description":"id of the related campaign","example":"1"},"message":{"type":"string","description":"id of the related message","example":"3"}}}}}}}},"400":{"description":"400"},"403":{"description":"403"},"404":{"description":"404"}}}},"/campaignReport/openTrend":{"get":{"summary":"Retrieve the campaign open trend","description":"How many distinct contacts opened campaign email in a date window, bucketed by hour of the day or by day of the week, across the account's campaigns; for a user who is not an admin, only campaigns sent to lists the user may access. Internal: a v3 form of the hour and week open trend that API v1 serves as `report_trend_read_all`. Hours and weekdays are in the timezone of the user making the request, offset in whole hours; the window itself is matched against the stored open timestamps. A contact who opened in several buckets is counted once in each. Every bucket is always present, with 0 hits when nobody opened in it.","operationId":"retrieve-campaign-open-trend","parameters":[{"name":"source","in":"query","description":"Which open records to count: `links` for opens recorded by the tracking pixel, `mpp` for opens attributed to Apple Mail Privacy Protection.","required":true,"schema":{"type":"string","enum":["links","mpp"]},"example":"links"},{"name":"type","in":"query","description":"How to bucket the opens: `hour` for the 24 hours of the day, `week` for the seven days of the week.","required":true,"schema":{"type":"string","enum":["hour","week"]},"example":"hour"},{"name":"startDate","in":"query","description":"First day of the window, Y-m-d. Opens from 00:00:00 on this day are counted.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the window, Y-m-d, no earlier than startDate. Opens up to 23:59:59 on this day are counted.","required":true,"schema":{"type":"string"},"example":"2026-09-30"},{"name":"listIds[]","in":"query","description":"Count only opens of campaigns sent to these lists. Every ID must be positive and, for a user who is not an admin, one of the lists the user may access. Left out, an admin gets every list and any other user the lists the user may access.","schema":{"type":"array","items":{"type":"string"}},"example":[3,5]},{"name":"tagIds[]","in":"query","description":"Count only opens by contacts carrying at least one of these contact tags. Every ID must be positive and name an existing contact tag.","schema":{"type":"array","items":{"type":"string"}},"example":[7]}],"responses":{"200":{"description":"The buckets in order: hours 00 to 23 for `hour`, Monday to Sunday for `week`.","content":{"application/json":{"schema":{"properties":{"items":{"description":"24 buckets for `hour`, 7 for `week`.","type":"array","items":{"properties":{"label":{"description":"Name of the bucket: the hour as `HH (h AM)` for `hour`, the translated weekday name for `week`.","type":"string","example":"05 (5 AM)"},"hits":{"description":"Number of distinct contacts who opened in the bucket.","type":"integer","example":42}},"type":"object"}}},"type":"object"},"example":{"items":[{"label":"00 (12 AM)","hits":3},{"label":"01 (1 AM)","hits":0}]}}}},"422":{"description":"A query parameter is missing or invalid: an unknown source or type, a date not in Y-m-d, an endDate before startDate, a list or tag ID that is not positive, a list the user may not access, a non-admin user with no lists, or a tag that is not an existing contact tag.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed check.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always `Invalid attribute`.","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the value.","type":"string","example":"This value should not be blank."},"source":{"description":"Which parameter failed.","properties":{"pointer":{"description":"`/data/attributes/` followed by the parameter name.","type":"string","example":"/data/attributes/startDate"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns":{"get":{"summary":"List all campaigns","description":"","operationId":"list-all-campaigns","x-canonical-resource":"campaign","parameters":[{"name":"orders[sdate]","in":"query","description":"Order campaigns by send date","schema":{"type":"string","default":"ASC"}},{"name":"orders[ldate]","in":"query","description":"Order campaigns by last send date","schema":{"type":"string"}},{"name":"filters[seriesid]","in":"query","description":"Filter to return the campaigns from the targeted automationId/seriesIds","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"campaigns\": [\n        {\n            \"type\": \"single\",\n            \"userid\": \"1\",\n            \"segmentid\": \"0\",\n            \"bounceid\": \"-1\",\n            \"realcid\": \"0\",\n            \"sendid\": \"0\",\n            \"threadid\": \"0\",\n            \"seriesid\": \"0\",\n            \"formid\": \"1\",\n            \"basetemplateid\": \"90a1d1ab6ad33e95708caf6472dc1724f698c694\",\n            \"basemessageid\": \"0\",\n            \"addressid\": \"0\",\n            \"source\": \"web\",\n            \"name\": \"Opt In Email\",\n            \"cdate\": \"2018-08-17T13:47:31-05:00\",\n            \"mdate\": \"2018-08-17T13:47:31-05:00\",\n            \"sdate\": null,\n            \"ldate\": null,\n            \"send_amt\": \"0\",\n            \"total_amt\": \"0\",\n            \"opens\": \"0\",\n            \"uniqueopens\": \"0\",\n            \"linkclicks\": \"0\",\n            \"uniquelinkclicks\": \"0\",\n            \"subscriberclicks\": \"0\",\n            \"forwards\": \"0\",\n            \"uniqueforwards\": \"0\",\n            \"hardbounces\": \"0\",\n            \"softbounces\": \"0\",\n            \"unsubscribes\": \"0\",\n            \"unsubreasons\": \"0\",\n            \"updates\": \"0\",\n            \"socialshares\": \"0\",\n            \"replies\": \"0\",\n            \"uniquereplies\": \"0\",\n            \"status\": \"0\",\n            \"public\": \"1\",\n            \"mail_transfer\": \"0\",\n            \"mail_send\": \"0\",\n            \"mail_cleanup\": \"0\",\n            \"mailer_log_file\": \"0\",\n            \"tracklinks\": \"all\",\n            \"tracklinksanalytics\": \"0\",\n            \"trackreads\": \"1\",\n            \"trackreadsanalytics\": \"1\",\n            \"analytics_campaign_name\": \"\",\n            \"tweet\": \"0\",\n            \"facebook\": \"0\",\n            \"survey\": \"\",\n            \"embed_images\": \"0\",\n            \"htmlunsub\": \"0\",\n            \"textunsub\": \"0\",\n            \"htmlunsubdata\": null,\n            \"textunsubdata\": null,\n            \"recurring\": \"day1\",\n            \"willrecur\": \"0\",\n            \"split_type\": \"even\",\n            \"split_content\": \"0\",\n            \"split_offset\": \"2\",\n            \"split_offset_type\": \"day\",\n            \"split_winner_messageid\": \"0\",\n            \"split_winner_awaiting\": \"0\",\n            \"responder_offset\": \"0\",\n            \"responder_type\": \"subscribe\",\n            \"responder_existing\": \"0\",\n            \"reminder_field\": \"sdate\",\n            \"reminder_format\": null,\n            \"reminder_type\": \"month_day\",\n            \"reminder_offset\": \"0\",\n            \"reminder_offset_type\": \"day\",\n            \"reminder_offset_sign\": \"+\",\n            \"reminder_last_cron_run\": null,\n            \"activerss_interval\": \"day1\",\n            \"activerss_url\": null,\n            \"activerss_items\": \"10\",\n            \"ip4\": \"643992596\",\n            \"laststep\": \"designer\",\n            \"managetext\": \"0\",\n            \"schedule\": \"0\",\n            \"scheduleddate\": null,\n            \"waitpreview\": \"0\",\n            \"deletestamp\": null,\n            \"replysys\": \"0\",\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/campaigns/1/user\",\n                \"automation\": \"https://:account.api-us1.com/api/3/campaigns/1/automation\",\n                \"campaignMessage\": \"https://:account.api-us1.com/api/3/campaigns/1/campaignMessage\",\n                \"campaignMessages\": \"https://:account.api-us1.com/api/3/campaigns/1/campaignMessages\",\n                \"links\": \"https://:account.api-us1.com/api/3/campaigns/1/links\",\n                \"campaignLists\": \"https://:account.api-us1.com/api/3/campaigns/1/campaignLists\"\n            },\n            \"id\": \"1\",\n            \"user\": \"1\",\n            \"automation\": null\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"single"},"userid":{"type":"string","example":"1"},"segmentid":{"type":"string","example":"0"},"bounceid":{"type":"string","example":"-1"},"realcid":{"type":"string","example":"0"},"sendid":{"type":"string","example":"0"},"threadid":{"type":"string","example":"0"},"seriesid":{"type":"string","example":"0"},"formid":{"type":"string","example":"1"},"basetemplateid":{"type":"string","example":"90a1d1ab6ad33e95708caf6472dc1724f698c694"},"basemessageid":{"type":"string","example":"0"},"addressid":{"type":"string","example":"0"},"source":{"type":"string","example":"web"},"name":{"type":"string","example":"Opt In Email"},"cdate":{"type":"string","example":"2018-08-17T13:47:31-05:00"},"mdate":{"type":"string","example":"2018-08-17T13:47:31-05:00"},"sdate":{},"ldate":{},"send_amt":{"type":"string","example":"0"},"total_amt":{"type":"string","example":"0"},"opens":{"type":"string","example":"0"},"uniqueopens":{"type":"string","example":"0"},"linkclicks":{"type":"string","example":"0"},"uniquelinkclicks":{"type":"string","example":"0"},"subscriberclicks":{"type":"string","example":"0"},"forwards":{"type":"string","example":"0"},"uniqueforwards":{"type":"string","example":"0"},"hardbounces":{"type":"string","example":"0","description":"Hard bounces recorded for this campaign, cumulative for the campaign, as a string."},"softbounces":{"type":"string","example":"0","description":"Soft bounces recorded for this campaign, cumulative for the campaign, as a string."},"unsubscribes":{"type":"string","example":"0","description":"Contacts who unsubscribed from this campaign's emails, cumulative for the campaign, as a string."},"unsubreasons":{"type":"string","example":"0"},"updates":{"type":"string","example":"0"},"socialshares":{"type":"string","example":"0"},"replies":{"type":"string","example":"0"},"uniquereplies":{"type":"string","example":"0"},"status":{"type":"string","example":"0"},"public":{"type":"string","example":"1"},"mail_transfer":{"type":"string","example":"0"},"mail_send":{"type":"string","example":"0"},"mail_cleanup":{"type":"string","example":"0"},"mailer_log_file":{"type":"string","example":"0"},"tracklinks":{"type":"string","example":"all"},"tracklinksanalytics":{"type":"string","example":"0"},"trackreads":{"type":"string","example":"1"},"trackreadsanalytics":{"type":"string","example":"1"},"analytics_campaign_name":{"type":"string","example":""},"tweet":{"type":"string","example":"0"},"facebook":{"type":"string","example":"0"},"survey":{"type":"string","example":""},"embed_images":{"type":"string","example":"0"},"htmlunsub":{"type":"string","example":"0"},"textunsub":{"type":"string","example":"0"},"htmlunsubdata":{},"textunsubdata":{},"recurring":{"type":"string","example":"day1"},"willrecur":{"type":"string","example":"0"},"split_type":{"type":"string","example":"even"},"split_content":{"type":"string","example":"0"},"split_offset":{"type":"string","example":"2"},"split_offset_type":{"type":"string","example":"day"},"split_winner_messageid":{"type":"string","example":"0"},"split_winner_awaiting":{"type":"string","example":"0"},"responder_offset":{"type":"string","example":"0"},"responder_type":{"type":"string","example":"subscribe"},"responder_existing":{"type":"string","example":"0"},"reminder_field":{"type":"string","example":"sdate"},"reminder_format":{},"reminder_type":{"type":"string","example":"month_day"},"reminder_offset":{"type":"string","example":"0"},"reminder_offset_type":{"type":"string","example":"day"},"reminder_offset_sign":{"type":"string","example":"+"},"reminder_last_cron_run":{},"activerss_interval":{"type":"string","example":"day1"},"activerss_url":{},"activerss_items":{"type":"string","example":"10"},"ip4":{"type":"string","example":"643992596"},"laststep":{"type":"string","example":"designer"},"managetext":{"type":"string","example":"0"},"schedule":{"type":"string","example":"0"},"scheduleddate":{},"waitpreview":{"type":"string","example":"0"},"deletestamp":{},"replysys":{"type":"string","example":"0"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/user"},"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/automation"},"campaignMessage":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/campaignMessage"},"campaignMessages":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/campaignMessages"},"links":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/links"},"campaignLists":{"type":"string","example":"https://:account.api-us1.com/api/3/campaigns/1/campaignLists"}}},"id":{"type":"string","example":"1"},"user":{"type":"string","example":"1"},"automation":{}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/campaigns/bulk-delete":{"delete":{"summary":"Delete multiple campaigns (older spelling)","description":"The older spelling of DELETE /campaigns/bulk_delete, kept as an alias: both addresses are served by the same file and handler, so the request, the responses and the permission rules are exactly those of DELETE /campaigns/bulk_delete. Use that address instead.\n\nDelete several campaigns in one call. This is the v3 equivalent of the v1 `campaign_delete_list` action.\n\nThe body selects what to delete, in one of three shapes:\n\n- `{\"ids\": [1, 2]}` — the given campaigns\n- `[1, 2]` — a bare array of ids, equivalent to the above\n- `{\"deleteFirst\": 5}` — the oldest N campaigns in the account, where N is between 1 and 10\n\n`ids` and `deleteFirst` are mutually exclusive.\n\nDeletion is not transactional: campaigns are removed one at a time, so a call can partially succeed. `deleted` lists the ids that were removed and `failed` the ids that were not, each with a reason. When nothing at all could be removed the request answers `404`.\n\nRequires permission to delete campaigns, and the account must have the Campaigns module enabled.","operationId":"delete-multiple-campaigns-older-spelling","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"IDs of the campaigns to delete. Must be a non-empty list of positive integers."},"deleteFirst":{"type":"integer","format":"int32","description":"Delete the oldest N campaigns in the account, between 1 and 10. Mutually exclusive with `ids`."}}},"examples":{"Delete by id":{"value":{"ids":[1,2,3]}},"Delete the oldest campaigns":{"value":{"deleteFirst":5}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 1,\n    \"message\": \"Campaigns deleted\",\n    \"deleted\": [\n        1,\n        2\n    ],\n    \"failed\": [\n        {\n            \"id\": 3,\n            \"reason\": \"Campaign not found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32","description":"`1` when at least one campaign was deleted."},"message":{"type":"string"},"deleted":{"type":"array","items":{"type":"integer","format":"int32"},"description":"IDs of the campaigns that were deleted."},"failed":{"type":"array","description":"Campaigns that could not be deleted.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"reason":{"type":"string"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Bad request. \\\"ids\\\" and \\\"deleteFirst\\\" are mutually exclusive.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"You do not have a permission to delete campaigns\",\n    \"deleted\": [],\n    \"failed\": []\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"},"deleted":{"type":"array"},"failed":{"type":"array"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Campaign not found\",\n    \"deleted\": [],\n    \"failed\": [\n        {\n            \"id\": 3,\n            \"reason\": \"Campaign not found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"},"deleted":{"type":"array"},"failed":{"type":"array"}}}}}},"405":{"description":"405","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Method not supported. Only DELETE supported.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}},"deprecated":false,"x-internal":true}},"/campaigns/bulk_delete":{"delete":{"summary":"Delete multiple campaigns","description":"Delete several campaigns in one call. This is the v3 equivalent of the v1 `campaign_delete_list` action.\n\nThe body selects what to delete, in one of three shapes:\n\n- `{\"ids\": [1, 2]}` — the given campaigns\n- `[1, 2]` — a bare array of ids, equivalent to the above\n- `{\"deleteFirst\": 5}` — the oldest N campaigns in the account, where N is between 1 and 10\n\n`ids` and `deleteFirst` are mutually exclusive.\n\nDeletion is not transactional: campaigns are removed one at a time, so a call can partially succeed. `deleted` lists the ids that were removed and `failed` the ids that were not, each with a reason. When nothing at all could be removed the request answers `404`.\n\nRequires permission to delete campaigns, and the account must have the Campaigns module enabled.","operationId":"delete-multiple-campaigns","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"IDs of the campaigns to delete. Must be a non-empty list of positive integers."},"deleteFirst":{"type":"integer","format":"int32","description":"Delete the oldest N campaigns in the account, between 1 and 10. Mutually exclusive with `ids`."}},"additionalProperties":false},"examples":{"Delete by id":{"value":{"ids":[1,2,3]}},"Delete the oldest campaigns":{"value":{"deleteFirst":5}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 1,\n    \"message\": \"Campaigns deleted\",\n    \"deleted\": [\n        1,\n        2\n    ],\n    \"failed\": [\n        {\n            \"id\": 3,\n            \"reason\": \"Campaign not found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32","description":"`1` when at least one campaign was deleted."},"message":{"type":"string"},"deleted":{"type":"array","items":{"type":"integer","format":"int32"},"description":"IDs of the campaigns that were deleted."},"failed":{"type":"array","description":"Campaigns that could not be deleted.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"reason":{"type":"string"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Bad request. \\\"ids\\\" and \\\"deleteFirst\\\" are mutually exclusive.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"You do not have a permission to delete campaigns\",\n    \"deleted\": [],\n    \"failed\": []\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"},"deleted":{"type":"array"},"failed":{"type":"array"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Campaign not found\",\n    \"deleted\": [],\n    \"failed\": [\n        {\n            \"id\": 3,\n            \"reason\": \"Campaign not found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"},"deleted":{"type":"array"},"failed":{"type":"array"}}}}}},"405":{"description":"405","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Method not supported. Only DELETE supported.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}},"deprecated":false}},"/campaigns/createAutomation":{"post":{"summary":"Create an empty automation","description":"Creates a new, empty automation with status 0 owned by the authenticated user and returns its ID, so the app can open it in the automation builder; called from the campaign flow. The name is read from the automationName query parameter, or from a form field of that name; an empty name gets the default \"Automation N\", where N is one more than the number of automations the user owns. Requires the manage automations permission. Only POST is accepted: any other method answers 405 with a plain-text body.","operationId":"create-an-empty-automation","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"automationName","in":"query","description":"Name of the new automation. Required; an empty value gets the default name.","required":true,"schema":{"type":"string"},"example":"Welcome series"}],"responses":{"200":{"description":"The automation was created","content":{"application/json":{"schema":{"type":"object","properties":{"automationId":{"type":"integer","description":"ID of the new automation.","example":42}}},"example":{"automationId":42}}}},"400":{"description":"automationName was not sent. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Bad Request. Include automationName as a query param"}}}},"403":{"description":"The user may not manage automations. Body: errors, a list with one item carrying status 403, title and detail, the localized no-permission message."},"405":{"description":"The method is not POST. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only POST supported."}}}}},"deprecated":false,"x-internal":true}},"/campaigns/currentWinner/{campaignId}":{"get":{"summary":"Retrieve the current winner of a split campaign","description":"The message currently winning the campaign's split test, by the engagement the test measures (opens or clicks), or the declared winner once one is set. When no variant has recorded any engagement yet, hasEngagement is false and winner is the campaign's first message, a fallback rather than a result. Used by the automation split campaign editor. A campaign that does not exist, or a database failure, answers 200 with meta.success false and meta.message.","operationId":"retrieve-split-campaign-current-winner","parameters":[{"name":"campaignId","in":"path","description":"ID of the split campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The winner, or meta.success false with the reason","content":{"application/json":{"schema":{"properties":{"winner":{"description":"ID of the winning message, as a string. Absent when meta.success is false.","type":"string","example":"7"},"hasEngagement":{"description":"False when no variant recorded engagement of the measured type, so winner is only the fallback first message. Absent when meta.success is false.","type":"boolean","example":true},"meta":{"description":"Outcome.","properties":{"success":{"description":"False when the campaign does not exist or the counts could not be read.","type":"boolean","example":true},"message":{"description":"Present only when success is false, for example \"No Result found for Campaign with id 12\".","type":"string"}},"type":"object"}},"type":"object"},"example":{"winner":"7","hasEngagement":true,"meta":{"success":true}}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/emitSentEvent":{"get":{"summary":"Record that the account sent a campaign","description":"Records a campaign_sent product event, dated today, for the account in ActiveCampaign's own usage tracking (its CRM event tracking and Pendo). Nothing about any campaign is read or changed, and no campaign is named: the call only marks that the account has sent a campaign. Called by the app after a campaign is sent. Always answers 200 with an empty body; a failure to record the event is logged and not reported.","operationId":"emit-campaign-sent-event","responses":{"200":{"description":"The event was recorded, or the failure to record it was logged. The body is empty."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/labels":{"post":{"summary":"Apply a label to a campaign","description":"Applies a label (folder) to a campaign by creating the association between them. Used by the campaigns list to label campaigns. When the campaign already carries the label nothing is created and the response is 200 with a message saying so. Answers 400 when the body has no campaignFolder or its campaign or folder is not a number, 403 when the label is archived, and 404 when the campaign or the label does not exist.","operationId":"create-a-campaign-label","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["campaignFolder"],"properties":{"campaignFolder":{"description":"The association to create.","required":["campaign","folder"],"properties":{"campaign":{"description":"ID of the campaign to label.","type":"integer","example":12},"folder":{"description":"ID of the label (folder) to apply. An archived label is refused.","type":"integer","example":3}},"type":"object"}},"type":"object"},"example":{"campaignFolder":{"campaign":12,"folder":3}}}}},"responses":{"200":{"description":"The campaign already carries the label; nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Says the association already exists.","type":"string","example":"CampaignFolder with campaign id 12 and folder id 3 already exists"}},"type":"object"}}}},"201":{"description":"The label was applied. The body carries the new association under campaignFolder; IDs are echoed in the type they were sent.","content":{"application/json":{"schema":{"properties":{"campaignFolder":{"description":"The created association.","properties":{"campaignid":{"description":"ID of the campaign the label is applied to.","example":"12"},"folderid":{"description":"ID of the label (folder) applied to the campaign.","example":"3"},"campaign":{"description":"The same ID as campaignid, under the relationship name.","example":"12"},"folder":{"description":"The same ID as folderid, under the relationship name.","example":"3"},"created_timestamp":{"description":"When the label was applied, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"updated_timestamp":{"description":"When the association last changed, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"links":{"description":"URLs of the related campaign and label.","properties":{"folder":{"description":"URL of the label.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/folder"},"campaign":{"description":"URL of the campaign.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/campaign"}},"type":"object"},"id":{"description":"ID of the campaign label association.","example":"41"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body has no campaignFolder, or its campaign or folder is missing or not a number. Body: errors, a list with one item carrying status 400, title and detail (\"A campaignFolder must be provided\", \"A campaign id must be provided\" or \"A folder or label id must be provided\")."},"403":{"description":"The label is archived. Body: errors, a list with one item carrying status 403, title and detail (\"Initiative with id 3 is archived and cannot have campaigns associated with it.\")."},"404":{"description":"The label or the campaign does not exist. Body: message, a sentence naming what was not found."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"List campaign labels","description":"Lists the associations between campaigns and labels (folders): one row per label applied to a campaign, not the labels themselves. Used by the campaigns list to show and filter by label. Paged with limit and offset; filters[...] and orders[...] are not supported on this collection and are ignored. Served by the inherited ResultController list action.","operationId":"list-campaign-labels","parameters":[{"name":"limit","in":"query","description":"Number of associations to return, at most 100. Defaults to 20.","required":false,"schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of associations to skip. Defaults to 0.","required":false,"schema":{"type":"integer","default":0}},{"name":"ids","in":"query","description":"Comma-separated association IDs to return; when sent, the page size is the number of IDs given.","required":false,"schema":{"type":"string"},"example":"41,42"},{"name":"include_folder","in":"query","description":"1 adds the label's title and color to each row and leaves out associations whose label no longer exists.","required":false,"schema":{"type":"integer","enum":[0,1]}},{"name":"include","in":"query","description":"Comma-separated relationships to sideload as top-level collections: campaign, folder, or both.","required":false,"schema":{"type":"string"},"example":"folder"}],"responses":{"200":{"description":"One page of associations","content":{"application/json":{"schema":{"properties":{"campaignFolders":{"description":"The campaign label associations.","type":"array","items":{"properties":{"campaignid":{"description":"ID of the campaign the label is applied to.","type":"string","example":"12"},"folderid":{"description":"ID of the label (folder) applied to the campaign.","type":"string","example":"3"},"created_timestamp":{"description":"When the label was applied, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"updated_timestamp":{"description":"When the association last changed, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"created_by":{"description":"ID of the user who applied the label; null when not recorded.","type":["string","null"]},"updated_by":{"description":"ID of the user who last changed the association; null when not recorded.","type":["string","null"]},"title":{"description":"Name of the label. Only present when include_folder=1.","type":"string","example":"Spring promotions"},"color":{"description":"Colour of the label. Only present when include_folder=1.","type":"string"},"campaign":{"description":"The same ID as campaignid, under the relationship name.","type":"string","example":"12"},"folder":{"description":"The same ID as folderid, under the relationship name.","type":"string","example":"3"},"links":{"description":"URLs of the related campaign and label.","properties":{"folder":{"description":"URL of the label.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/folder"},"campaign":{"description":"URL of the campaign.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/campaign"}},"type":"object"},"id":{"description":"ID of the campaign label association.","type":"string","example":"41"}},"type":"object"}},"meta":{"description":"Paging information.","properties":{"total":{"description":"Total number of associations.","type":"integer","example":2}},"type":"object"}},"type":"object"},"example":{"campaignFolders":[{"campaignid":"12","folderid":"3","created_timestamp":"2026-09-28 17:45:11","updated_timestamp":"2026-09-28 17:45:11","created_by":null,"updated_by":null,"campaign":"12","folder":"3","links":{"folder":"https://:account.api-us1.com/api/3/campaignFolders/41/folder","campaign":"https://:account.api-us1.com/api/3/campaignFolders/41/campaign"},"id":"41"}],"meta":{"total":1}}}}}},"deprecated":false,"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/labels/bulkCreate":{"post":{"summary":"Apply labels to campaigns in bulk","description":"Applies several labels to campaigns in one call. The body is a bare JSON array of campaign and label (folder) ID pairs, not wrapped in a key. Duplicate pairs in the body are dropped; a pair that is malformed is skipped and reported in errors by its index; a pair whose campaign or label does not exist, or whose campaign already carries the label, is skipped silently. When any pair names an archived label the whole request is refused with 403, and when any pair names a label that does not exist it is refused with 404, before anything is created.","operationId":"bulk-create-campaign-labels","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"required":["campaign","folder"],"properties":{"campaign":{"description":"ID of the campaign to label.","type":"integer","example":12},"folder":{"description":"ID of the label (folder) to apply.","type":"integer","example":3}},"type":"object"}},"example":[{"campaign":12,"folder":3},{"campaign":13,"folder":3}]}}},"responses":{"200":{"description":"Nothing was created: the body was empty (\"No data provided\", meta.success true, no errors key) or no pair was valid (\"No valid labels provided\", with errors, and meta.success true only when errors is empty).","content":{"application/json":{"schema":{"properties":{"message":{"description":"No data provided, or No valid labels provided.","type":"string","example":"No valid labels provided"},"errors":{"description":"The malformed pairs that were skipped, as in the 201 response. Absent for an empty body.","type":"array","items":{"type":"object"}},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"False when pairs were rejected as malformed.","type":"boolean","example":true}},"type":"object"}},"type":"object"}}}},"201":{"description":"At least one label was applied","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Labels created successfully\".","type":"string","example":"Labels created successfully"},"added":{"description":"How many associations were created.","type":"integer","example":2},"errors":{"description":"The malformed pairs that were skipped.","type":"array","items":{"properties":{"index":{"description":"Position of the pair in the request array.","type":"integer","example":1},"error":{"description":"Why the pair was skipped.","type":"string","example":"A folder or label id must be provided"}},"type":"object"}},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"}},"type":"object"}}}},"403":{"description":"A pair names an archived label. Body: errors, a list with one item carrying status 403, title and detail."},"404":{"description":"A pair names a label that does not exist. Body: message, a sentence naming it."},"500":{"description":"The associations could not be saved. Body: message, errors and meta.success false."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/campaigns/labels/bulkDelete":{"delete":{"summary":"Remove labels from campaigns in bulk","description":"Removes several campaign label associations by their IDs. The labels and the campaigns themselves are kept. When any ID does not exist the request is refused with 404, and when any association belongs to an archived label it is refused with 403, before anything is removed. No ids at all answers 200 with \"Nothing to delete\".","operationId":"bulk-delete-campaign-labels","parameters":[{"name":"ids","in":"query","description":"Comma-separated IDs of the campaign label associations to remove (the id of each campaignFolder, not of the label).","required":true,"schema":{"type":"string"},"example":"41,42"}],"responses":{"200":{"description":"The associations were removed, or there was nothing to remove","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"Labels deleted successfully\", or \"Nothing to delete\" when no ids were sent.","type":"string","example":"Labels deleted successfully"},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"}},"type":"object"}}}},"403":{"description":"An association belongs to an archived label. Body: errors, a list with one item carrying status 403, title and detail."},"404":{"description":"An ID does not exist. Body: message, a sentence naming it."},"500":{"description":"The associations could not be removed. Body: error, the reason, and meta.success false."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/campaigns/labels/{id}":{"delete":{"summary":"Remove a label from a campaign","description":"Removes one campaign label association. The label and the campaign are kept. Answers 404 when the association does not exist, and 403 when its label is archived or the user may not access it.","operationId":"delete-a-campaign-label","parameters":[{"name":"id","in":"path","description":"ID of the campaign label association (the id of the campaignFolder, not of the label)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The label is archived (body: errors, a list with one item carrying status 403, title and detail \"Initiative with id 3 is archived and cannot have campaigns removed from it.\") or the user may not access the association (body: errors, one item with status \"403\" and detail \"Forbidden\")."},"404":{"description":"No association with this ID. Body: message, a sentence naming it."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"Retrieve a campaign label","description":"Retrieves one association between a campaign and a label (folder). Served by the inherited ResultController get action. Answers 404 when the association does not exist and 403 when the user may not access it.","operationId":"retrieve-a-campaign-label","parameters":[{"name":"id","in":"path","description":"ID of the campaign label association (the id of the campaignFolder, not of the label)","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The association, under campaignFolder","content":{"application/json":{"schema":{"properties":{"campaignFolder":{"description":"The association.","properties":{"campaignid":{"description":"ID of the campaign the label is applied to.","type":"string","example":"12"},"folderid":{"description":"ID of the label (folder) applied to the campaign.","type":"string","example":"3"},"created_timestamp":{"description":"When the label was applied, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"updated_timestamp":{"description":"When the association last changed, as Y-m-d H:i:s.","type":"string","example":"2026-09-28 17:45:11"},"created_by":{"description":"ID of the user who applied the label; null when not recorded.","type":["string","null"]},"updated_by":{"description":"ID of the user who last changed the association; null when not recorded.","type":["string","null"]},"campaign":{"description":"The same ID as campaignid, under the relationship name.","type":"string","example":"12"},"folder":{"description":"The same ID as folderid, under the relationship name.","type":"string","example":"3"},"links":{"description":"URLs of the related campaign and label.","properties":{"folder":{"description":"URL of the label.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/folder"},"campaign":{"description":"URL of the campaign.","type":"string","example":"https://:account.api-us1.com/api/3/campaignFolders/41/campaign"}},"type":"object"},"id":{"description":"ID of the campaign label association.","type":"string","example":"41"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not access the association. Body: errors, a list with one item carrying status \"403\" and detail \"Forbidden\"."},"404":{"description":"No association with this ID. Body: message, a sentence naming the ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Why nothing was found.","type":"string"}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/messagesRecipientCount/{campaignId}":{"get":{"summary":"Count a campaign's recipients by preferred language","description":"For a campaign translated into several languages: how many active contacts on the campaign's lists there are for each preferred language, read from the custom field the account designates as its preferred-language field. A value that is not a supported language, or no value, is counted under a null languageCode. Despite its name, messages holds one row per language, not per message. A database failure answers 200 with meta.success false and an empty messages list.","operationId":"list-campaign-recipient-counts-by-language","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The counts","content":{"application/json":{"schema":{"properties":{"messages":{"description":"One row per preferred language.","type":"array","items":{"properties":{"languageCode":{"description":"The supported language code; null for contacts with no or an unsupported preferred language.","type":["string","null"],"example":"es"},"recipientCount":{"description":"Number of distinct active contacts, as a numeric string.","type":"string","example":"120"}},"type":"object"}},"meta":{"description":"Outcome.","properties":{"success":{"description":"False when the counts could not be read.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"messages":[{"languageCode":"es","recipientCount":"120"},{"languageCode":null,"recipientCount":"880"}],"meta":{"success":true}}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/moderationStatus/{campaignId}":{"get":{"summary":"Retrieve the moderation status of a campaign","description":"Whether the campaign needs approval before it can be sent, and where that approval stands. Only franchisee accounts whose franchisor requires approval moderate campaigns; for every other account the status is always 0. On a moderated account a campaign that has not been submitted yet reports 1. The app uses it to decide whether Send is allowed. When the status cannot be determined, including when the campaign does not exist, the response is 503 with a null status, so the caller keeps sending blocked.","operationId":"retrieve-campaign-moderation-status","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The moderation status","content":{"application/json":{"schema":{"properties":{"moderationStatus":{"description":"0 needs no approval, 1 requires approval and has not been submitted, 2 pending approval, 3 approved, 4 approval expired, 5 rejected.","type":"integer","enum":[0,1,2,3,4,5],"example":0},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"moderationStatus":0,"meta":{"success":true}}}}},"503":{"description":"The status could not be determined, for example because the campaign does not exist. Body: moderationStatus null and meta.success false.","content":{"application/json":{"schema":{"properties":{"moderationStatus":{"description":"Always null.","type":"null"},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always false.","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/moderationStatusList":{"get":{"summary":"List the moderation statuses of several campaigns","description":"The moderation status of each campaign named in campaignIds, as GET /campaigns/moderationStatus/{campaignId} reports it for one. IDs that match no campaign are left out, and no campaignIds gives an empty list. The campaigns list uses it to show which campaigns await approval. When the statuses cannot be determined the response is 503 with meta.success false and the statuses gathered so far, so a partial list is not read as \"no approval needed\".","operationId":"list-campaign-moderation-statuses","parameters":[{"name":"campaignIds","in":"query","description":"Comma-separated IDs of the campaigns.","required":false,"schema":{"type":"string"},"example":"12,13"}],"responses":{"200":{"description":"The statuses","content":{"application/json":{"schema":{"properties":{"moderationStatusList":{"description":"One item per campaign found.","type":"array","items":{"properties":{"campaignId":{"description":"ID of the campaign, as a string.","type":"string","example":"12"},"moderationStatus":{"description":"0 needs no approval, 1 requires approval and has not been submitted, 2 pending approval, 3 approved, 4 approval expired, 5 rejected.","type":"integer","enum":[0,1,2,3,4,5],"example":2}},"type":"object"}},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"moderationStatusList":[{"campaignId":"12","moderationStatus":2}],"meta":{"success":true}}}}},"503":{"description":"The statuses could not be determined. Body: moderationStatusList with any statuses gathered before the failure, and meta.success false."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/perstags":{"get":{"summary":"List the personalization tags usable in conditional content","description":"The personalization tags a conditional content block can test, with their labels, for the campaign editor's condition picker. The tag-exists and tag-doesn't-exist conditions are left out. id is the position of the tag in this list, not a stored ID. Only GET is accepted; any other method answers 405 with a plain-text body.","operationId":"list-conditional-content-personalization-tags","x-canonical-resource":"personalizations","responses":{"200":{"description":"The tags, as a bare JSON array","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Position of the tag in the list, from 0.","example":0},"tag":{"type":"string","description":"The tag as written in content, with its percent signs.","example":"%FIRSTNAME%"},"label":{"type":"string","description":"Human-readable name of the tag.","example":"First Name"}}}},"example":[{"id":0,"tag":"%FIRSTNAME%","label":"First Name"}]}}},"405":{"description":"The method is not GET. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported."}}}}},"deprecated":false,"x-internal":true}},"/campaigns/recover/{campaignId}":{"get":{"summary":"Restart the sending pipeline of a stalled campaign","description":"Maintenance endpoint: restarts the sending pipeline of a one-off campaign that stalled while sending, from the last pipeline step it completed (initialization completed, sending threads created, sending after approval, or approval created). The campaign must be sending (status 2), or pending approval (status 7) when it stalled after its approval request was created; automation (series) campaigns recover on their own and are refused. Start and completion are recorded in the campaign send audit log. Despite being a GET, the call restarts sending. Every outcome, including a refusal or an error, answers 200 with a plain-text sentence describing it; the response is sent with a Content-Type of application/json although the body is not JSON.","operationId":"recover-a-stalled-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to recover","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"What happened, as one sentence of plain text: \"Recovery process complete from from step: {step}. Result: {result}\" on success, otherwise why the campaign was not recovered (for example \"Campaign 12 needs to be in status=2 to recover, it has status 5\" or \"Exception during recovery: ...\").","content":{"text/plain":{"schema":{"type":"string","example":"Campaign 12 needs to be in status=2 to recover, it has status 5"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/reporting/permissions":{"get":{"summary":"Check whether the user may see campaign reports","description":"Whether the authenticated user may open campaign reports: always true for a user in the main admin group; otherwise true only when the account is entitled to campaigns and the user's group has the campaign reports permission. The app uses it to decide whether to show campaign reporting.","operationId":"retrieve-campaign-reporting-access","responses":{"200":{"description":"The answer","content":{"application/json":{"schema":{"properties":{"hasAccess":{"description":"True when the user may see campaign reports.","type":"boolean","example":true}},"type":"object"},"example":{"hasAccess":true}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/search":{"get":{"summary":"Search campaigns by their message content","description":"Finds campaigns the user may see whose message subject, preheader, HTML body or text body contains q (case-insensitive substring match). Only campaigns that can still be edited (draft, scheduled, paused or disabled) and automation campaigns are searched. A split campaign yields one result per message. Results are read newest-modified first, then each page is re-ordered by importance_score, highest first. limit and offset are required: leaving either out fails validation. Answers 422 when a query parameter is invalid.","operationId":"search-campaigns","parameters":[{"name":"limit","in":"query","description":"Number of results to return, from 1 to 100. Required.","required":true,"schema":{"type":"string"},"example":"20"},{"name":"offset","in":"query","description":"Number of results to skip, 0 or more. Required.","required":true,"schema":{"type":"string"},"example":"0"},{"name":"q","in":"query","description":"Text to find in the subject, preheader, HTML body or text body of the campaign messages. Leave out to list every searchable campaign.","schema":{"type":"string"},"example":"spring sale"},{"name":"fullData","in":"query","description":"1 to include html, text, markup_html and markup_css in each result; 0, the default, returns them as null. Any non-empty value other than 0 counts as 1.","schema":{"type":"integer","default":0,"enum":[0,1]},"example":0},{"name":"modifiedAfter","in":"query","description":"Only campaigns modified on or after this day, as Y-m-d.","schema":{"type":"string"},"example":"2026-09-01"},{"name":"modifiedBefore","in":"query","description":"Only campaigns modified on or before this day, as Y-m-d. Must be later than modifiedAfter when both are sent.","schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"One page of matches","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always true.","type":"boolean","example":true},"data":{"description":"The search echoed back with its results.","properties":{"search_query":{"description":"The q sent; null when none was sent.","type":["string","null"],"example":"spring sale"},"total_count":{"description":"How many campaign messages match in total.","type":"integer","example":3},"limit":{"description":"The limit applied.","type":"integer","example":20},"offset":{"description":"The offset applied.","type":"integer","example":0},"fullData":{"description":"Whether the message bodies are included.","type":"boolean","example":false},"modifiedAfter":{"description":"The modifiedAfter applied, as Y-m-d; null when none was sent.","type":["string","null"],"example":"2026-09-01"},"modifiedBefore":{"description":"The modifiedBefore applied, as Y-m-d; null when none was sent.","type":["string","null"],"example":null},"results":{"description":"The matching campaign messages; empty when nothing matches.","type":"array","items":{"properties":{"asset_type":{"description":"Always campaign_email.","type":"string","example":"campaign_email"},"campaign_id":{"description":"ID of the campaign.","type":"integer","example":12},"message_id":{"description":"ID of the matching message.","type":"integer","example":7},"campaign_name":{"description":"Name of the campaign.","type":"string","example":"Spring sale"},"subject":{"description":"Subject of the message.","type":"string","example":"Our spring sale starts today"},"from_name":{"description":"From name of the message.","type":"string","example":"Example Store"},"from_email":{"description":"From address of the message.","type":"string","example":"news@example.com"},"preheader_text":{"description":"Preheader of the message.","type":["string","null"],"example":"Up to 30% off"},"html":{"description":"HTML body of the message when fullData is set; otherwise null.","type":["string","null"],"example":null},"text":{"description":"Text body of the message when fullData is set; otherwise null.","type":["string","null"],"example":null},"markup_html":{"description":"Editor source HTML of the message when fullData is set and the message has editor markup; otherwise null.","type":["string","null"],"example":null},"markup_css":{"description":"Editor source CSS of the message when fullData is set and the message has editor markup; otherwise null.","type":["string","null"],"example":null},"campaign_type":{"description":"Type of the campaign, as on the campaign record (single, split, ...).","type":"string","example":"single"},"match_location":{"description":"Where q was found, as a comma-separated list of subject, preheader, html_body and text_body; none when no q was sent, unknown when the match is not in those fields.","type":"string","example":"subject, html_body"},"lifecycle_status":{"description":"The campaign status as the app labels it, translated to the user's language (for example Draft or Paused).","type":"string","example":"Draft"},"created_date":{"description":"When the campaign was created, as stored (Y-m-d H:i:s).","type":"string","example":"2026-09-01 10:00:00"},"modified_date":{"description":"When the campaign was last modified, as stored (Y-m-d H:i:s).","type":["string","null"],"example":"2026-09-02 11:30:00"},"sent_date":{"description":"When the campaign is scheduled to send or was sent, as stored (Y-m-d H:i:s); null when not set.","type":["string","null"],"example":null},"editor_version":{"description":"Version of the editor the campaign was built in, as stored.","type":"string","example":"3"},"importance_score":{"description":"Ranking score from 0 to 70: up to 50 for recent activity (sent, else modified, else created; decays to 0 over a year) plus 15 for a draft or 20 for a scheduled campaign.","type":"number","example":61.37}},"type":"object"}}},"type":"object"}},"type":"object"}}}},"422":{"description":"A query parameter is invalid: limit missing or not a whole number from 1 to 100, offset missing or not a whole number of 0 or more, or modifiedAfter or modifiedBefore not a Y-m-d date, or modifiedBefore not after modifiedAfter. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/sendingStatus":{"get":{"summary":"List the campaigns scheduled or modified around a date, by status","description":"Every campaign in the account scheduled to send, or last modified, within a day either side of a date, grouped by status. Defaults to now. Not permission-filtered: it covers all the account's campaigns. Only GET is accepted; any other method answers 405 with a plain-text body. Known defect: a forDate value is converted to a Unix timestamp before it reaches the date comparison, which expects a date string, so do not rely on forDate.","operationId":"list-campaign-sending-status-around-a-date","x-canonical-resource":"campaign","parameters":[{"name":"forDate","in":"query","description":"The date to look around, in any format strtotime accepts. Leave out to use now; see the description for the known defect when it is sent.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"The campaigns, grouped by status name","content":{"application/json":{"schema":{"type":"object","properties":{"Scheduled":{"type":"array","description":"Campaigns whose status is 1 (Scheduled).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Sending":{"type":"array","description":"Campaigns whose status is 2 (Sending).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Paused":{"type":"array","description":"Campaigns whose status is 3 (Paused).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Stopped":{"type":"array","description":"Campaigns whose status is 4 (Stopped).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Finished":{"type":"array","description":"Campaigns whose status is 5 (Finished).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Disabled":{"type":"array","description":"Campaigns whose status is 6 (Disabled).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}},"Pending Approval":{"type":"array","description":"Campaigns whose status is 7 (Pending Approval).","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the campaign.","example":"12"},"name":{"type":"string","description":"Name of the campaign.","example":"Spring sale"},"type":{"type":"string","description":"Type of the campaign (single, split, ...).","example":"single"},"status":{"type":"string","description":"Status code of the campaign, matching the group it is listed under.","example":"1"},"sdate":{"type":"string","nullable":true,"description":"Scheduled send date, as stored (Y-m-d H:i:s).","example":"2026-10-15 09:00:00"},"scheduledDate":{"type":"string","nullable":true,"description":"The same value as sdate.","example":"2026-10-15 09:00:00"},"pastScheduleDate":{"type":"string","description":"\"1\" when the scheduled send date is still in the future, \"0\" otherwise; the name says the opposite of what the value measures.","example":"0"},"emailsSent":{"type":"string","description":"Number of emails sent so far.","example":"500"}}}}}}}}},"405":{"description":"The method is not GET. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only GET supported."}}}}},"deprecated":false,"x-internal":true}},"/campaigns/statistics":{"get":{"summary":"List personalization tags with how many contacts have data for them","description":"Every personalization tag the user can insert into a campaign (the standard contact tags, list name, geo tags and the custom field tags of the user's lists) with how many contacts have a value for it, how many distinct values there are, the coverage rate and a sample value. On accounts with more than 15,000 contacts the counts come from a random sample of 15,000 and are scaled up to the full contact count, so they are estimates; coverage_rate is measured on the sample. Used by the campaign editor to suggest tags that will render for most recipients. An internal error answers 200 with success false.","operationId":"list-personalization-tag-statistics","responses":{"200":{"description":"The statistics, or success false with a message when they could not be computed","content":{"application/json":{"schema":{"properties":{"success":{"description":"False when the statistics could not be computed; the other fields are then absent and message explains.","type":"boolean","example":true},"message":{"description":"Present only when success is false: \"Error retrieving personalization tag statistics\".","type":"string","example":"Error retrieving personalization tag statistics"},"total":{"description":"Number of contacts in the account; 0 when it has none or the statistics query failed.","type":"integer","example":52000},"total_eligible":{"description":"Number of contacts the counts were measured on: the sample size when sampling, otherwise the same as total.","type":"integer","example":15000},"data":{"description":"One item per personalization tag; empty when the account has no contacts.","type":"array","items":{"properties":{"tag_source":{"description":"standard for the built-in contact, list and geo tags; custom for custom field tags.","type":"string","enum":["standard","custom"],"example":"standard"},"tag":{"description":"The tag as written in content, with its percent signs.","type":"string","example":"%FIRSTNAME%"},"label":{"description":"Human-readable name of the tag.","type":"string","example":"First Name"},"field_type":{"description":"Type of data behind the tag: email or text for the standard tags, the custom field type for custom field tags.","type":"string","example":"text"},"filled_count":{"description":"How many contacts have a value for the tag, as a numeric string; scaled up from the sample when sampling.","type":"string","example":"41200"},"unique_values":{"description":"How many distinct values the tag has, as a numeric string; scaled up from the sample when sampling, which can overestimate. Null for tags whose distinct values are not counted.","type":["string","null"],"example":"3870"},"coverage_rate":{"description":"Percentage of the measured contacts with a value, with two decimals.","type":"string","example":"79.23"},"default_value":{"description":"The default value of a custom field tag; null when none or for standard tags.","type":["string","null"],"example":null},"sample_value":{"description":"An example value taken from the contacts; null when none was found.","type":["string","null"],"example":"Jane"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"personalizations","x-internal":true}},"/campaigns/test-preview":{"post":{"summary":"Preview a campaign message","description":"Render a campaign message for one address and return it parsed into headers and bodies, without sending anything. This is the v3 equivalent of the `preview` action of the v1 `campaign_send` action.\n\nRendering personalizes the message for `toEmail`. Unlike [Send a test of a campaign](/reference/send-a-campaign-test), no email is delivered and no test-send limit applies. ","operationId":"preview-a-campaign-message","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignId":{"type":"integer","format":"int32","description":"ID of the campaign. Must be a JSON integer."},"messageId":{"type":"integer","format":"int32","description":"ID of the message to preview. Must be a JSON integer."},"toEmail":{"type":"string","description":"Address the preview is personalized for."}},"required":["campaignId","messageId","toEmail"],"additionalProperties":false},"examples":{"Request Example":{"value":{"campaignId":1,"messageId":1,"toEmail":"someone@example.com"}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"subject\": \"Welcome!\",\n    \"contentType\": \"multipart/alternative\",\n    \"fromHeader\": \"Sender <sender@example.com>\",\n    \"toHeader\": \"someone@example.com\",\n    \"fromEmail\": \"sender@example.com\",\n    \"fromName\": \"Sender\",\n    \"toEmail\": \"someone@example.com\",\n    \"toName\": \"\",\n    \"emailSource\": \"Content-Type: multipart/alternative; boundary=\\\"_=_swift_1234_=_\\\"\\n...\",\n    \"content\": {\n        \"text\": \"Welcome!\",\n        \"textCharacterSet\": \"utf-8\",\n        \"html\": \"<html><body>Welcome!</body></html>\",\n        \"htmlCharacterSet\": \"utf-8\"\n    }\n}"}},"schema":{"type":"object","properties":{"subject":{"type":"string","description":"Rendered subject."},"contentType":{"type":"string","description":"Content type of the rendered message."},"fromHeader":{"type":"string","description":"Rendered `From` header."},"toHeader":{"type":"string","description":"Rendered `To` header."},"fromEmail":{"type":"string"},"fromName":{"type":"string"},"toEmail":{"type":"string"},"toName":{"type":"string"},"emailSource":{"type":"string","description":"The raw MIME source of the rendered message."},"content":{"type":"object","properties":{"text":{"type":"string","description":"Rendered plain-text body."},"textCharacterSet":{"type":"string"},"html":{"type":"string","description":"Rendered HTML body."},"htmlCharacterSet":{"type":"string"}}}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Incorrect campaignId"}},"schema":{"type":"string"}}}},"405":{"description":"405","content":{"text/plain":{"examples":{"Result":{"value":"Method not supported. Only POST supported."}},"schema":{"type":"string"}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"Error trying to fetch sources"}},"schema":{"type":"string"}}}}},"deprecated":false}},"/campaigns/test-send":{"post":{"summary":"Send a test of a campaign","description":"Send a test email of a campaign message to a single address. This is the v3 equivalent of the `test` action of the v1 `campaign_send` action.\n\nThe test is subject to the account's test-send limits and to sender-domain verification. Prefix the address with `+` to send through the regular mail server instead of the test mail server.\n\nResponses are plain text, not JSON: `200` carries `test email sent`, and every caller-fixable failure (over the test limit, unverified sending domain, disallowed recipient, invalid RSS feed) carries `400` with the reason. `500` means the send failed without an attributable reason. ","operationId":"send-a-campaign-test","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignId":{"type":"integer","format":"int32","description":"ID of the campaign to test. Must be a JSON integer."},"messageId":{"type":"integer","format":"int32","description":"ID of the message to test. Must be a JSON integer. For a split campaign this selects the variant."},"subject":{"type":"string","description":"Subject line to use for the test message."},"toEmail":{"type":"string","description":"Address the test is sent to. Prefix with `+` to use the regular mail server instead of the test mail server."}},"required":["campaignId","messageId","subject","toEmail"],"additionalProperties":false},"examples":{"Request Example":{"value":{"campaignId":1,"messageId":1,"subject":"Test: Welcome!","toEmail":"someone@example.com"}}}}}},"responses":{"200":{"description":"200","content":{"text/plain":{"examples":{"Result":{"value":"test email sent"}},"schema":{"type":"string"}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"exceeded test send limit"}},"schema":{"type":"string"}}}},"405":{"description":"405","content":{"text/plain":{"examples":{"Result":{"value":"Method not supported. Only POST supported."}},"schema":{"type":"string"}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"No Test Email was sent"}},"schema":{"type":"string"}}}}},"deprecated":false}},"/campaigns/translations/messageMarkups/{messageId}":{"get":{"summary":"Retrieve the editor markup of a campaign message","description":"The editor source of a campaign message, its HTML and CSS as the campaign editor stores them, before they are compiled into the sendable email. Used by the campaign translation editor. Answers 404 when the message has no stored editor markup.","operationId":"retrieve-campaign-message-markup","parameters":[{"name":"messageId","in":"path","description":"ID of the message","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The markup","content":{"application/json":{"schema":{"properties":{"html":{"description":"The editor source HTML.","type":["string","null"]},"css":{"description":"The editor source CSS.","type":["string","null"],"example":""}},"type":"object"}}}},"404":{"description":"The message has no stored editor markup. Body: message, a sentence naming the message ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Why nothing was found.","type":"string","example":"CampaignMessageMarkup not found for message ID: 7"}},"type":"object"}}}}},"x-canonical-resource":"message","x-internal":true},"put":{"summary":"Replace the editor markup of a campaign message","description":"Saves new editor source HTML for a campaign message and rebuilds the sendable email from it: the HTML is stored as the message's editor markup, compiled with the stored CSS, and the compiled email is written to the message. Used by the campaign translation editor to save a translated message. The message is taken from messageId in the body; the messageId in the path is not read. A missing campaignId, messageId or html is not an error status: the response is 200 with an empty object and meta.message naming what is missing. Answers 404 when the message has no stored editor markup.","operationId":"update-campaign-message-markup","parameters":[{"name":"messageId","in":"path","description":"ID of the message. Not read: the message is taken from messageId in the body.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["campaignId","messageId","html"],"properties":{"campaignId":{"description":"ID of the campaign the message belongs to, used when rebuilding the sendable email.","type":"integer","example":12},"messageId":{"description":"ID of the message to update.","type":"integer","example":7},"html":{"description":"The new editor source HTML. Must not be empty.","type":"string"}},"type":"object"}}}},"responses":{"200":{"description":"The saved markup, or meta.message naming a missing field","content":{"application/json":{"schema":{"properties":{"html":{"description":"The editor source HTML as saved. Absent when a field was missing.","type":["string","null"]},"css":{"description":"The editor source CSS, unchanged. Absent when a field was missing.","type":["string","null"]},"meta":{"description":"Present only when a field was missing.","properties":{"message":{"description":"\"campaignId parameter is required!\", \"messageId parameter is required!\" or \"html is required!\".","type":"string","example":"html is required!"}},"type":"object"}},"type":"object"}}}},"404":{"description":"The message has no stored editor markup. Body: message, a sentence naming the message ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Why nothing was found.","type":"string","example":"CampaignMessageMarkup not found for message ID: 7"}},"type":"object"}}}}},"x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/translations/report/{campaignId}":{"get":{"summary":"Retrieve the per-language report of a translated campaign","description":"One row per message of a campaign sent in several languages, with the language, split percentage and the send, open, click and bounce rates of each message, highest message ID first. Used by the campaign report for translated campaigns. Read from the reporting aggregates, so a campaign without them returns an empty list. Answers 503 with meta.retryable true when the reporting database could not be read after retrying.","operationId":"retrieve-campaign-translation-report","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The per-message rows","content":{"application/json":{"schema":{"properties":{"messages":{"description":"One row per message of the campaign. Every value is a string as the database returns it.","type":"array","items":{"properties":{"message_id":{"description":"ID of the message.","type":"string","example":"7"},"subject":{"description":"Subject of the message.","type":["string","null"],"example":"Our spring sale starts today"},"preheader_text":{"description":"Preheader of the message.","type":["string","null"]},"fromemail":{"description":"From address of the message.","type":["string","null"],"example":"news@example.com"},"percentage":{"description":"Share of the recipients the message was sent to, as a percentage.","type":["string","null"],"example":"50"},"total_sends":{"description":"Number of sends of the message.","type":["string","null"],"example":"500"},"open_rate":{"description":"Unique opens as a percentage of sends; null when nothing was sent.","type":["string","null"]},"click_rate":{"description":"Unique clicks as a percentage of sends; null when nothing was sent.","type":["string","null"]},"click_to_open_rate":{"description":"Unique clicks as a percentage of unique opens; null when nothing was opened.","type":["string","null"]},"bounce_rate":{"description":"Bounces as a percentage of sends; null when nothing was sent.","type":["string","null"]},"language_code":{"description":"Code of the language the message is written in.","type":["string","null"],"example":"es"}},"type":"object"}}},"type":"object"}}}},"503":{"description":"The reporting database could not be read. Retry later.","content":{"application/json":{"schema":{"properties":{"messages":{"description":"Always null.","type":"null"},"meta":{"description":"Retry hint.","properties":{"retryable":{"description":"Always true.","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"messages":null,"meta":{"retryable":true}}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/validateCampaigns":{"post":{"summary":"Keep the campaign IDs the user may access","description":"Takes a list of campaign IDs and returns those that exist and that the user may access: campaigns the user created, campaigns sent to a list in one of the user's groups, campaigns with no list yet, or any campaign for the primary admin. Changes nothing. Answers 422 when ids is missing, empty or holds something other than positive numbers.","operationId":"filter-accessible-campaign-ids","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignsValidationRequest"},"example":{"ids":[12,13,99]}}}},"responses":{"200":{"description":"The accessible IDs","content":{"application/json":{"schema":{"properties":{"ids":{"description":"The requested IDs that exist and the user may access, as integers; IDs that do not exist or are not accessible are left out.","type":"array","items":{"type":"integer"}}},"type":"object"},"example":{"ids":[12,13]}}}},"400":{"description":"The body is not valid JSON. Body: errors, a list with one item carrying status \"400\" and detail."},"422":{"description":"ids is missing, empty, not a list, or holds a value that is not a positive number. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the field (for example /data/attributes/ids[0])."}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/campaigns/{campaignId}/audit-log":{"get":{"summary":"List the send pipeline checkpoints of a campaign","description":"The checkpoints the campaign recorded as it passed through its sending pipeline (initialization, transfer, approval, sending and cleanup, plus any recovery), newest first, with the counts recorded at each. Used by support tooling to see where a campaign's send got to. meta.count is the total number of checkpoints. limit and offset are required: leaving either out fails validation. Answers 422 when a query parameter is invalid.","operationId":"list-campaign-send-audit-log","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of checkpoints to return, 1 or more. Required.","required":true,"schema":{"type":"string"},"example":"10"},{"name":"offset","in":"query","description":"Number of checkpoints to skip, 0 or more. Required.","required":true,"schema":{"type":"string"},"example":"0"}],"responses":{"200":{"description":"One page of checkpoints","content":{"application/json":{"schema":{"properties":{"meta":{"description":"Paging information.","properties":{"count":{"description":"Total number of checkpoints recorded for the campaign.","type":"integer","example":2}},"type":"object"},"audits":{"description":"The checkpoints, newest first; empty when none are recorded.","type":"array","items":{"properties":{"id":{"description":"ID of the checkpoint record.","type":"integer","example":501},"campaignId":{"description":"ID of the campaign.","type":"integer","example":12},"sendId":{"description":"ID of the send the checkpoint belongs to; 0 when none.","type":"integer","example":0},"seriesId":{"description":"ID of the automation that sent the campaign; 0 for a campaign not sent by an automation.","type":"integer","example":0},"segmentId":{"description":"ID of the segment the campaign was sent to; 0 when none.","type":"integer","example":0},"campaignStatus":{"description":"Status code of the campaign when the checkpoint was recorded.","type":"integer","example":2},"campaignType":{"description":"Type of the campaign when the checkpoint was recorded.","type":["string","null"],"example":"single"},"campaignPhase":{"description":"Pipeline phase the checkpoint belongs to, for example init, transfer, approval, send, cleanup or recover.","type":["string","null"],"example":"send"},"checkpointName":{"description":"Name of the checkpoint, such as start or complete.","type":["string","null"],"example":"start"},"numContacts":{"description":"Number of contacts recorded at the checkpoint.","type":"integer","example":1000},"numSent":{"description":"Number of sends recorded at the checkpoint.","type":"integer","example":0},"numFailed":{"description":"Number of failed sends recorded at the checkpoint.","type":"integer","example":0},"extra":{"description":"Additional context recorded with the checkpoint, as string values keyed by name; null when none.","type":["object","null"],"example":null}},"type":"object"}}},"type":"object"}}}},"422":{"description":"limit or offset is missing or invalid: limit must be a whole number of 1 or more, offset a whole number of 0 or more. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/declareWinner":{"post":{"summary":"Declare the winner of an automation split campaign","description":"Declares the winning message of a split campaign sent by an automation and turns the rest of the send into a single campaign: the winner is recorded on the split campaign, and a copy of it containing only the winning message is created as a scheduled single campaign in the same automation. With no message in the path the winner is worked out from the engagement the test measures, falling back to the first message when none was recorded; POST /campaigns/{campaignId}/declareWinner/{messageId} names it instead. Takes no body. Failures answer 200 with meta.success false.","operationId":"declare-split-campaign-winner","parameters":[{"name":"campaignId","in":"path","description":"ID of the split campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The winner was declared, or meta.success false with the reason","content":{"application/json":{"schema":{"properties":{"campaignId":{"description":"ID of the single campaign created from the winner,, as a string. Absent when meta.success is false.","type":"string","example":"45"},"meta":{"description":"Outcome.","properties":{"success":{"description":"False when the campaign is not an automation split campaign, does not exist, or the winner could not be set.","type":"boolean","example":true},"message":{"description":"Present only when success is false: \"Campaign is not a series split campaign\", \"Error while trying to set the winner\", \"No Result found for Campaign with id {campaignId}\" or a database error.","type":"string"}},"type":"object"}},"type":"object"},"example":{"campaignId":"45","meta":{"success":true}}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{campaignId}/declareWinner/{messageId}":{"post":{"summary":"Declare a chosen message the winner of an automation split campaign","description":"Declares the winning message of a split campaign sent by an automation and turns the rest of the send into a single campaign: the winner is recorded on the split campaign, and a copy of it containing only the winning message is created as a scheduled single campaign in the same automation. The winner is the message named in the path. Takes no body. Failures answer 200 with meta.success false.","operationId":"declare-split-campaign-winner-message","parameters":[{"name":"campaignId","in":"path","description":"ID of the split campaign","required":true,"schema":{"type":"integer"}},{"name":"messageId","in":"path","description":"ID of the message to declare the winner","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The winner was declared, or meta.success false with the reason","content":{"application/json":{"schema":{"properties":{"campaignId":{"description":"ID of the single campaign created from the winner,, as a string. Absent when meta.success is false.","type":"string","example":"45"},"meta":{"description":"Outcome.","properties":{"success":{"description":"False when the campaign is not an automation split campaign, does not exist, or the winner could not be set.","type":"boolean","example":true},"message":{"description":"Present only when success is false: \"Campaign is not a series split campaign\", \"Error while trying to set the winner\", \"No Result found for Campaign with id {campaignId}\" or a database error.","type":"string"}},"type":"object"}},"type":"object"},"example":{"campaignId":"45","meta":{"success":true}}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{campaignId}/edit/moderationStatus":{"put":{"summary":"Approve or reject a campaign awaiting moderation","description":"Records the franchisor's decision on a campaign that needs approval, by setting its moderation status to approved (3) or rejected (5). Only those two values are accepted. Nothing else about the campaign changes, and the action itself checks no campaign permission. Answers 404 when the campaign does not exist and 400 for any other status.","operationId":"update-campaign-moderation-status","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["status"],"properties":{"status":{"description":"3 to approve the campaign, 5 to reject it. Must be a JSON number.","type":"integer","enum":[3,5],"example":3}},"type":"object"}}}},"responses":{"200":{"description":"The status was set","content":{"application/json":{"schema":{"properties":{"campaignId":{"description":"ID of the campaign.","type":"integer","example":12},"moderation_status":{"description":"The status now set.","type":"integer","example":3},"meta":{"description":"Outcome flag.","properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"}},"type":"object"}}}},"400":{"description":"status is missing or is not 3 or 5. Body: message \"Invalid moderation status\" and meta.success false."},"404":{"description":"No campaign with this ID. Body: message \"Campaign not found\" and meta.success false."},"500":{"description":"The campaign could not be updated. Body: message \"Unable to update campaign\" and meta.success false."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{campaignId}/enable":{"put":{"summary":"Schedule a campaign","description":"Enable a campaign for sending, setting its status to `scheduled` (1).\n\nOnly a campaign whose status is `draft` (0) or `disabled` (6) can be enabled. For a one-off campaign this also queues the sending engine, so the campaign sends at its existing scheduled date; for a recurring or RSS campaign the next scheduled date is recalculated from the campaign's recurrence settings when it is re-enabled. The scheduled date itself cannot be set here - use `PUT /api/3/campaigns/{id}/edit`.\n\nThis endpoint reports business-rule failures in the response body rather than with an\nerror status: an unknown campaign, an automation (\"series\") campaign, a completed campaign and a\ntransition that is not allowed from the campaign's current status all return `200` with `succeeded`\nset to `0`. The `message` text is localized to the account language, so match on `succeeded` rather\nthan on the message.","operationId":"schedule-a-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"campaignId","in":"path","description":"id of the campaign whose status is being changed","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Status updated":{"value":"{\n\t\"succeeded\":1,\n\t\"message\":\"Campaign updated.\"\n}"},"Campaign is neither a draft nor disabled":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"<localized error message>\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","example":1},"message":{"type":"string","example":"Campaign updated."}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Bad request. Campaign id must be non-zero."}}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"An error occurred while updating the campaign status."}}}}}},"deprecated":false}},"/campaigns/{campaignId}/finish":{"post":{"summary":"Finish setting up a campaign and start it","description":"The last step of the campaign builder: checks that the campaign is ready to send, records the authenticated user as its owner, saves its summary settings and starts it, sending now or scheduling it for its send date (split campaigns keep their split settings). Takes no body; everything is read from the stored campaign. Readiness failures, such as no recipient list, no subject, a send date in the past or a campaign that can no longer be modified, answer 400 with every reason in message. Whether the start itself succeeded is reported in succeeded.","operationId":"finish-a-campaign","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to finish","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The campaign was saved; succeeded says whether it was started","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"1 when the campaign was started or scheduled, 0 when starting it failed.","type":"integer","enum":[0,1],"example":1},"message":{"description":"What happened, as the campaign builder reports it; \"Campaign saved.\" when there is nothing more to say.","type":"string","example":"Campaign saved."}},"type":"object"},"example":{"succeeded":1,"message":"Campaign saved."}}}},"400":{"description":"The campaign is not ready to send, does not exist, or could not be started. Body: succeeded 0 and message, either \"Validation failed: \" followed by every reason (for example \"Recipient list is required. Subject is required.\") or \"Campaign failed to initialize! \" followed by the error.","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always 0.","type":"integer","example":0},"message":{"description":"Why the campaign was not finished.","type":"string","example":"Validation failed: Recipient list is required."}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{campaignId}/pause":{"put":{"summary":"Pause a sending campaign","description":"Pause a campaign that is currently sending, setting its status to `paused` (3).\n\nOnly a campaign whose status is `sending` (2) can be paused. Pausing clears the send date on the campaign's most recent process row, which stops the sending engine from picking it up again; a campaign whose process has already finished everything it was given cannot be paused and returns `succeeded: 0` with `Process not found.`.\n\nThis endpoint reports business-rule failures in the response body rather than with an\nerror status: an unknown campaign, an automation (\"series\") campaign, a completed campaign and a\ntransition that is not allowed from the campaign's current status all return `200` with `succeeded`\nset to `0`. The `message` text is localized to the account language, so match on `succeeded` rather\nthan on the message.","operationId":"pause-a-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"campaignId","in":"path","description":"id of the campaign whose status is being changed","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Status updated":{"value":"{\n\t\"succeeded\":1,\n\t\"message\":\"<localized success message>\"\n}"},"Campaign is not sending":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"<localized error message>\"\n}"},"No process to pause":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"Process not found.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","example":1},"message":{"type":"string","example":"<localized success message>"}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Bad request. Campaign id must be non-zero."}}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"An error occurred while updating the campaign status."}}}}}},"deprecated":false}},"/campaigns/{campaignId}/reportAggregateRevenues":{"get":{"summary":"Retrieve the revenue attributed to a campaign","description":"Lifetime ecommerce revenue attributed to the campaign, one total per currency, and whether revenue is tracked for it. Amounts are whole numbers in the minor unit of the currency (cents for USD); the caller formats them. Takes no date window and is not paginated. Answers 403 when the account has no campaigns entitlement or the user may not see the campaign.","operationId":"retrieve-campaign-attributed-revenue","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The attributed revenue","content":{"application/json":{"schema":{"properties":{"revenueTracked":{"description":"Whether revenue is tracked for the campaign.","type":"boolean","example":true},"revenues":{"description":"The attributed revenue, one item per currency; empty when none is attributed.","type":"array","items":{"properties":{"currency":{"description":"Currency code, uppercased.","type":"string","example":"USD"},"totalRevenue":{"description":"Attributed revenue in the minor unit of the currency (cents for USD).","type":"integer","example":125000}},"type":"object"}}},"type":"object"},"example":{"revenueTracked":true,"revenues":[{"currency":"USD","totalRevenue":125000}]}}}},"403":{"description":"The account is not entitled to campaigns (detail \"This account is not entitled to campaigns.\") or the user may not see the campaign (detail \"Forbidden\"). Body: errors, a list with one item carrying status \"403\" and detail."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reportTotals":{"get":{"summary":"Retrieve the report totals of a campaign","description":"The headline counters of a campaign report: sends, opens, clicks, unsubscribes, forwards, bounces and attributed revenue. The v3 counterpart of the v1 campaign_report_totals action and its per-metric variants. Totals are lifetime unless both startDate and endDate are sent, which restricts the time-based counters to that window. Every field is always present; a field the chosen branch does not compute is null (the lifetime totals carry updates, totalBounces, socialShares, uniqueReplies and revenue; a date window carries replies, bounces and shares instead). Answers 403 when the account has no campaigns entitlement or the user may not see the campaign, 404 when no totals exist for it, 400 when messageId does not belong to the campaign, and 422 when a query parameter is invalid.","operationId":"retrieve-campaign-report-totals","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"messageId","in":"query","description":"Restrict the totals to one message of a split campaign. 0, the default, reports the whole campaign.","required":false,"schema":{"type":"integer","default":0,"minimum":0},"example":0},{"name":"startDate","in":"query","description":"Start of the date window, as Y-m-d, Y-m-d H:i:s or Y-m-d\\TH:i:s; a date alone starts at midnight. Send together with endDate.","required":false,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"End of the date window, in the same formats as startDate; may not be earlier than startDate. Send together with startDate.","required":false,"schema":{"type":"string"},"example":"2026-09-30 23:59:59"},{"name":"includeBots","in":"query","description":"true, the default, counts clicks identified as bot clicks; false leaves them out of the click counters. Only true or false is accepted.","required":false,"schema":{"type":"string","default":"true","enum":["true","false"]},"example":"false"}],"responses":{"200":{"description":"The totals","content":{"application/json":{"schema":{"properties":{"ldate":{"description":"When the campaign was last sent, as stored (Y-m-d H:i:s).","type":["string","null"],"example":"2026-09-28 09:00:00"},"status":{"description":"Status code of the campaign, as on the campaign record (5 is completed).","type":["integer","null"],"example":5},"type":{"description":"Type of the campaign, as on the campaign record (single, split, ...); null in a date window on a single message.","type":["string","null"],"example":"single"},"messageId":{"description":"The message reported on: the messageId sent, or, for the whole campaign, the IDs of all its messages joined with commas.","type":["string","null"],"example":"7"},"totalAmt":{"description":"Number of sends delivered.","type":["integer","null"],"example":1000},"sendAmt":{"description":"Number of sends attempted.","type":["integer","null"],"example":1000},"uniqueOpens":{"description":"Number of contacts who opened at least once.","type":["integer","null"],"example":400},"verifiedUniqueOpens":{"description":"Unique opens confirmed as human.","type":["integer","null"],"example":350},"uniqueLinkClicks":{"description":"Number of distinct links clicked; in a date window, the number of contacts who clicked.","type":["integer","null"],"example":4},"subscriberClicks":{"description":"Number of contacts who clicked at least one link.","type":["integer","null"],"example":120},"unsubscribes":{"description":"Number of contacts who unsubscribed through the campaign.","type":["integer","null"],"example":3},"forwards":{"description":"Total forwards.","type":["integer","null"],"example":5},"uniqueForwards":{"description":"Number of contacts who forwarded at least once.","type":["integer","null"],"example":4},"uniqueReplies":{"description":"Number of contacts who replied at least once. Lifetime totals only.","type":["integer","null"],"example":2},"updates":{"description":"Number of contacts who updated their profile. Lifetime totals only.","type":["integer","null"],"example":1},"totalBounces":{"description":"Hard and soft bounces added together. Lifetime totals only.","type":["integer","null"],"example":6},"socialShares":{"description":"Number of social shares. Lifetime totals only.","type":["integer","null"],"example":0},"replies":{"description":"Reply records counted in the window. Date window only.","type":["integer","null"],"example":1},"bounces":{"description":"Number of contacts who bounced in the window. Date window only.","type":["integer","null"],"example":6},"shares":{"description":"Number of shares in the window. Date window only.","type":["integer","null"],"example":0},"revenue":{"description":"Revenue attributed to the campaign, one item per currency; the whole campaign's revenue even when messageId is sent. Lifetime totals only; null in a date window.","type":["array","null"],"items":{"properties":{"revenue_generator_id":{"description":"ID of the campaign the revenue is attributed to.","type":"string","example":"12"},"currency":{"description":"Currency code, uppercased.","type":"string","example":"USD"},"total_revenue":{"description":"Attributed revenue in the minor unit of the currency (cents for USD).","type":"string","example":"125000"},"revenue_generator_type":{"description":"Always Campaign.","type":"string","example":"Campaign"},"total_revenue_formatted":{"description":"total_revenue formatted for display in the currency.","type":"string","example":"$1,250.00"}},"type":"object"}}},"type":"object"}}}},"400":{"description":"The totals could not be computed for the request, for example a messageId that does not belong to the campaign. Body: errors, a list with one item carrying status \"400\" and detail, the localized reason."},"403":{"description":"The account is not entitled to campaigns (detail \"This account is not entitled to campaigns.\") or the user may not see the campaign (detail \"Forbidden\"). Body: errors, a list with one item carrying status \"403\" and detail."},"404":{"description":"No totals found for the campaign. Body: errors, a list with one item carrying status \"404\" and detail \"No report totals found for campaign {campaignId}.\"."},"422":{"description":"A query parameter is invalid: empty or not a single value, messageId not a whole number of 0 or more, includeBots not true or false, a date in another format, only one of startDate and endDate, or endDate before startDate. Body: errors, a list with one item carrying status \"422\" and detail naming the problem."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/bounces":{"get":{"summary":"List the contacts whose campaign email bounced","description":"One row per contact whose email from this campaign bounced, with the bounce type, code, description and date, plus the total number of bounced contacts in meta.total. The v3 counterpart of the v1 campaign_report_bounce_list action. Rows come in no guaranteed order. Answers 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-bounces","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of rows to return, from 1 to 100. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of rows to skip before the first one returned. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageId","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the whole campaign.","schema":{"type":"string","default":"0"},"example":"0"}],"responses":{"200":{"description":"One page of bounces and the total","content":{"application/json":{"schema":{"properties":{"campaignBounces":{"description":"The bounced contacts, one row per contact.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact whose email bounced, as a string.","type":"string","example":"42"},"email":{"description":"The email address that bounced.","type":"string","example":"jane@example.com"},"list":{"description":"ID of the list the bounced email was sent through, as a string; \"0\" when none is recorded.","type":"string","example":"3"},"message":{"description":"ID of the campaign message that bounced, as a string.","type":"string","example":"7"},"type":{"description":"Whether the bounce was hard or soft.","type":"string","enum":["hard","soft"],"example":"hard"},"code":{"description":"The bounce code recorded for the bounce, such as 5.1.1; an empty string when none was recorded.","type":"string","example":"5.1.1"},"description":{"description":"What the bounce code means, for example \"Bad destination mailbox address\" for 5.1.1. \"Address does not exist.\" when the code is unknown or has no description.","type":"string","example":"Bad destination mailbox address"},"source":{"description":"The reason text stored with the bounce; null when none was stored.","type":["string","null"]},"bounceDate":{"description":"The calendar date of the bounce at midnight US Central time, as an ISO 8601 date and time; null when no date is recorded.","type":["string","null"],"example":"2026-09-28T00:00:00-05:00"}},"type":"object"}},"meta":{"description":"Paging information.","properties":{"total":{"description":"How many distinct contacts bounced for the campaign, or for the message when messageId is sent.","type":"integer","example":12}},"type":"object"}},"type":"object"},"example":{"campaignBounces":[{"contact":"42","email":"jane@example.com","list":"3","message":"7","type":"hard","code":"5.1.1","description":"Bad destination mailbox address","source":null,"bounceDate":"2026-09-28T00:00:00-05:00"}],"meta":{"total":1}}}}},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 100, offset or messageId not a whole number of 0 or more. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/clicks":{"get":{"summary":"List the links of a campaign and who clicked them","description":"One row per link in the campaign, with its unique and total click counts and the contacts who clicked it. The v3 counterpart of the v1 campaign_report_link_list action, built from the same rows. The contacts under a link are read without the message and bot-click restrictions applied to the link counts, so they can cover more clicks than the counts do. The response carries no total: page with limit and offset until a page comes back shorter than limit. Answers 403 when the account has no campaigns entitlement, 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-link-clicks","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of links to return, from 1 to 1000. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of links to skip before the first one returned. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageid","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the whole campaign.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"includeBotClicks","in":"query","description":"Whether clicks identified as bot clicks count towards uniqueClicks and totalClicks: true or 1, the default, counts them; false or 0 leaves them out.","schema":{"type":"string","default":"true","enum":["true","false","1","0"]},"example":"false"}],"responses":{"200":{"description":"One page of links","content":{"application/json":{"schema":{"properties":{"campaignLinks":{"description":"The links of the campaign, one row per link.","type":"array","items":{"properties":{"id":{"description":"ID of the link, as a string.","type":"string","example":"15"},"url":{"description":"The URL the link points to.","type":"string","example":"https://www.example.com/sale"},"name":{"description":"The name of the link; an empty string when it has none.","type":"string","example":"Shop the sale"},"tracked":{"description":"1 when clicks on the link are tracked, 0 when they are not.","type":"integer","example":1},"uniqueClicks":{"description":"How many contacts clicked the link.","type":"integer","example":8},"totalClicks":{"description":"How many times the link was clicked, repeat clicks included.","type":"integer","example":11},"contacts":{"description":"The click records of the link, one row per stored record, so a contact can appear more than once.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact who clicked, as a string.","type":"string","example":"42"},"email":{"description":"Email address of the contact.","type":"string","example":"jane@example.com"},"clicks":{"description":"The click count stored on the record.","type":"integer","example":2},"lastClickDate":{"description":"The time stored on the click record, as an ISO 8601 date and time; null when none is recorded.","type":["string","null"],"example":"2026-09-28T17:45:11-05:00"}},"type":"object"}}},"type":"object"}}},"type":"object"},"example":{"campaignLinks":[{"id":"15","url":"https://www.example.com/sale","name":"Shop the sale","tracked":1,"uniqueClicks":8,"totalClicks":11,"contacts":[{"contact":"42","email":"jane@example.com","clicks":2,"lastClickDate":"2026-09-28T17:45:11-05:00"}]}]}}}},"403":{"description":"The account is not entitled to campaigns. Body: errors, a list with one item carrying status \"403\" and detail \"This account is not entitled to campaigns.\"."},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 1000, offset or messageid not a whole number of 0 or more, or includeBotClicks not one of true, false, 1 or 0. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/forwards":{"get":{"summary":"List the forwards of a campaign","description":"One row per contact and campaign message the contact forwarded: how many times they forwarded it, with the sender, recipient and note of one of those forwards. The v3 counterpart of the v1 campaign_report_forward_list action, built from the same query. The response carries no total: page with limit and offset until a page comes back shorter than limit. Answers 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-forwards","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of rows to return, from 1 to 100. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of rows to skip before the first one returned. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageid","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the whole campaign.","schema":{"type":"string","default":"0"},"example":"0"}],"responses":{"200":{"description":"One page of forwards","content":{"application/json":{"schema":{"properties":{"campaignForwards":{"description":"The forwards of the campaign, one row per contact and message.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact who forwarded the campaign, as a string.","type":"string","example":"42"},"message":{"description":"ID of the campaign message that was forwarded, as a string.","type":"string","example":"7"},"fromEmail":{"description":"Email address the forward was sent from, taken from one of the grouped forwards.","type":"string","example":"jane@example.com"},"fromName":{"description":"Name the forward was sent from, taken from one of the grouped forwards.","type":"string","example":"Jane Doe"},"toEmail":{"description":"Email address the message was forwarded to, taken from one of the grouped forwards: a contact who forwarded to several people is reported once.","type":"string","example":"sam@example.com"},"briefMessage":{"description":"The note the sender added, taken from one of the grouped forwards; an empty string when there is none.","type":"string","example":"Thought you would like this."},"forwards":{"description":"How many times the contact forwarded this message.","type":"integer","example":1},"lastForwardDate":{"description":"The time of one of the grouped forwards, as an ISO 8601 date and time: the query groups the forwards and does not select the latest one. Null when no time is recorded.","type":["string","null"],"example":"2026-09-28T17:45:11-05:00"}},"type":"object"}}},"type":"object"},"example":{"campaignForwards":[{"contact":"42","message":"7","fromEmail":"jane@example.com","fromName":"Jane Doe","toEmail":"sam@example.com","briefMessage":"Thought you would like this.","forwards":1,"lastForwardDate":"2026-09-28T17:45:11-05:00"}]}}}},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 100, offset not a whole number of 0 or more, or messageid not digits-only. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/opens":{"get":{"summary":"List the contacts who opened a campaign","description":"One row per contact who opened the campaign, with how many times they opened it and when they last did, newest open first unless orders[tstamp]=ASC is sent. The v3 counterpart of the v1 campaign_report_open_list action, built from the same rows. The response carries no total: page with limit and offset until a page comes back shorter than limit. Answers 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-opens","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of rows to return, from 1 to 1000. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of rows to skip before the first one returned. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageid","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the campaign's own message the way the v1 report does, not every message of a split campaign.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"orders[]","in":"query","description":"Sort direction by open time, sent as orders[tstamp]=ASC or orders[tstamp]=DESC (case-insensitive); tstamp is the only field accepted. Defaults to DESC, newest open first.","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"One page of openers","content":{"application/json":{"schema":{"properties":{"campaignOpens":{"description":"The contacts who opened the campaign, one row per contact.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact who opened, as a string.","type":"string","example":"42"},"email":{"description":"Email address of the contact.","type":"string","example":"jane@example.com"},"opens":{"description":"How many times the contact opened the campaign.","type":"integer","example":3},"lastOpenDate":{"description":"When the contact last opened the campaign, as an ISO 8601 date and time; null when no open time is recorded.","type":["string","null"],"example":"2026-09-28T17:45:11-05:00"}},"type":"object"}}},"type":"object"},"example":{"campaignOpens":[{"contact":"42","email":"jane@example.com","opens":3,"lastOpenDate":"2026-09-28T17:45:11-05:00"}]}}}},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 1000, offset or messageid not a whole number of 0 or more, or orders naming a field other than tstamp or a direction other than ASC or DESC. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/unopens":{"get":{"summary":"List the contacts who did not open a campaign","description":"One row per contact the campaign was sent to who has no recorded open of it. The v3 counterpart of the v1 campaign_report_unopen_list action, built from the same rows: opens is always 0 and sendDate is the campaign send date rather than a per-contact time, so the rows stay comparable with v1. The response carries no total: page with limit and offset until a page comes back shorter than limit; limit plus offset may not exceed 1000. Answers 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-unopens","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of rows to return, from 1 to 1000; limit plus offset may not exceed 1000. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of rows to skip before the first one returned, from 0 to 1000. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageid","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the campaign's own message the way the v1 report does.","schema":{"type":"string","default":"0"},"example":"0"}],"responses":{"200":{"description":"One page of contacts who did not open","content":{"application/json":{"schema":{"properties":{"campaignUnopens":{"description":"The contacts who did not open the campaign, one row per contact.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact, as a string.","type":"string","example":"42"},"email":{"description":"Email address of the contact.","type":"string","example":"jane@example.com"},"phone":{"description":"Phone number of the contact; an empty string when there is none.","type":"string","example":"+1 312 555 0100"},"account":{"description":"Name of the account (organization) recorded on the contact; an empty string when there is none.","type":"string","example":"Example Inc"},"opens":{"description":"Always 0.","type":"integer","example":0},"sendDate":{"description":"When the campaign was sent, as an ISO 8601 date and time. The same value on every row; null when no send date is recorded.","type":["string","null"],"example":"2026-09-28T09:00:00-05:00"}},"type":"object"}}},"type":"object"},"example":{"campaignUnopens":[{"contact":"42","email":"jane@example.com","phone":"","account":"","opens":0,"sendDate":"2026-09-28T09:00:00-05:00"}]}}}},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 1000, offset not a whole number from 0 to 1000, limit plus offset above 1000, or messageid not a whole number of 0 or more. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and, for a single parameter, source.pointer naming it (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/reports/unsubscribes":{"get":{"summary":"List the contacts who unsubscribed through a campaign","description":"One row per contact who unsubscribed through the campaign, with the reason they gave and when. The v3 counterpart of the v1 campaign_report_unsubscription_list action, built from the same rows. The response carries no total: page with limit and offset until a page comes back shorter than limit. Answers 404 when the campaign does not exist or the user may not see it, and 422 when a query parameter is invalid.","operationId":"list-campaign-report-unsubscribes","parameters":[{"name":"campaignId","in":"path","description":"ID of the campaign to report on","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"limit","in":"query","description":"Number of rows to return, from 1 to 100. Defaults to 20.","schema":{"type":"string","default":"20"},"example":"20"},{"name":"offset","in":"query","description":"Number of rows to skip before the first one returned. Defaults to 0.","schema":{"type":"string","default":"0"},"example":"0"},{"name":"messageid","in":"query","description":"ID of the campaign message to report on. 0, the default, reports the unsubscribes made through any message of the campaign; unsubscribes recorded without a message (for example by an automation) are left out.","schema":{"type":"string","default":"0"},"example":"0"}],"responses":{"200":{"description":"One page of unsubscribes","content":{"application/json":{"schema":{"properties":{"campaignUnsubscribes":{"description":"The contacts who unsubscribed through the campaign.","type":"array","items":{"properties":{"contact":{"description":"ID of the contact, as a string.","type":"string","example":"42"},"email":{"description":"Email address of the contact.","type":"string","example":"jane@example.com"},"firstName":{"description":"First name on the contact list subscription; an empty string when there is none.","type":"string","example":"Jane"},"lastName":{"description":"Last name on the contact list subscription; an empty string when there is none.","type":"string","example":"Doe"},"phone":{"description":"Phone number of the contact; an empty string when there is none.","type":"string","example":""},"accountName":{"description":"Name of the account (organization) recorded on the contact; an empty string when there is none.","type":"string","example":""},"reason":{"description":"The reason the contact gave for unsubscribing, as they entered it; null when they gave none.","type":["string","null"]},"unsubscribeDate":{"description":"When the contact unsubscribed, as an ISO 8601 date and time; null when no date is recorded.","type":["string","null"],"example":"2026-09-28T17:45:11-05:00"}},"type":"object"}}},"type":"object"},"example":{"campaignUnsubscribes":[{"contact":"42","email":"jane@example.com","firstName":"Jane","lastName":"Doe","phone":"","accountName":"","reason":null,"unsubscribeDate":"2026-09-28T17:45:11-05:00"}]}}}},"404":{"description":"No campaign with this id, or the user may not see it: a campaign the user cannot see is reported as missing. Body: errors, a list with one item carrying status \"404\" and detail \"Campaign not found.\"."},"422":{"description":"A query parameter is invalid: limit not a whole number from 1 to 100, offset or messageid not a whole number of 0 or more. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail naming the rule and source.pointer naming the parameter (for example /data/attributes/limit)."}},"x-canonical-resource":"campaign","x-internal":true}},"/campaigns/{campaignId}/resume":{"put":{"summary":"Resume a paused campaign","description":"Resume a paused campaign, setting its status back to `sending` (2) and re-driving the sending pipeline from the stage the campaign stopped at.\n\nOnly a campaign whose status is `paused` (3) can be resumed. The response reports the status change, not the outcome of the pipeline recovery that follows it.\n\nThis endpoint reports business-rule failures in the response body rather than with an\nerror status: an unknown campaign, an automation (\"series\") campaign, a completed campaign and a\ntransition that is not allowed from the campaign's current status all return `200` with `succeeded`\nset to `0`. The `message` text is localized to the account language, so match on `succeeded` rather\nthan on the message.","operationId":"resume-a-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"campaignId","in":"path","description":"id of the campaign whose status is being changed","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Status updated":{"value":"{\n\t\"succeeded\":1,\n\t\"message\":\"<localized success message>\"\n}"},"Campaign is not paused":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"<localized error message>\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","example":1},"message":{"type":"string","example":"<localized success message>"}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Bad request. Campaign id must be non-zero."}}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"An error occurred while updating the campaign status."}}}}}},"deprecated":false}},"/campaigns/{campaignId}/splitSeriesSave":{"post":{"summary":"Save the variations of an automation split campaign","description":"Saves the message variations (tabs) of a split campaign sent by an automation, as the automation split editor submits them, in one transaction: the messages listed in deletedTabs are removed, a tab without a messageId gets a new message copied from the first tab's message, every tab's sender, subject and preheader are written to its message, editor markup is saved when a tab carries both markupHtml and markupCss, and each message's split percentage is updated. At most 5 tabs; the first tab must name an existing message and cannot be deleted. Failures answer 200 with meta.success false and roll everything back; a body that does not match the shape answers 422.","operationId":"save-automation-split-campaign-variations","parameters":[{"name":"campaignId","in":"path","description":"ID of the automation split campaign","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitSeriesCampaignSaveRequest"},"example":{"tabs":[{"messageId":7,"subject":"Spring sale","replyToEmail":"help@example.com","fromName":"Example Store","fromEmail":"news@example.com","preHeader":"Up to 30% off","percentage":50},{"subject":"Spring sale: last chance","replyToEmail":"help@example.com","fromName":"Example Store","fromEmail":"news@example.com","preHeader":"Ends tonight","percentage":50}],"deletedTabs":[9]}}}},"responses":{"200":{"description":"Saved, or meta.success false with the reason","content":{"application/json":{"schema":{"properties":{"meta":{"description":"Outcome.","properties":{"success":{"description":"True when every change was saved.","type":"boolean","example":true},"message":{"description":"Present only when success is false, for example \"More than 5 tabs are not allowed\", \"At least one tab must have an already created message\", \"Campaign is not a series split campaign\", \"The first tab cannot be deleted\" or \"One of the messages was not able to be saved\".","type":"string"}},"type":"object"}},"type":"object"},"example":{"meta":{"success":true}}}}},"400":{"description":"The body is not valid JSON. Body: errors, a list with one item carrying status \"400\" and detail."},"422":{"description":"tabs or deletedTabs is missing or not a list. Body: errors, one item per failed rule, each carrying status 422, title \"Invalid attribute\", detail and source.pointer naming the field."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/campaigns/{campaignId}/splitSeriesTransform":{"post":{"summary":"Turn an automation campaign into a split campaign","description":"Copies a single campaign sent by an automation into a new draft split campaign in the same automation, so its sends can be A/B tested in the automation builder. The original is left as it is; the response names the new campaign and its first message. Takes no body. Failures answer 200 with meta.success false.","operationId":"transform-automation-campaign-to-split","parameters":[{"name":"campaignId","in":"path","description":"ID of the automation campaign to copy","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The split campaign was created, or meta.success false with the reason","content":{"application/json":{"schema":{"properties":{"campaignId":{"description":"ID of the new split campaign. Absent when meta.success is false.","type":"integer","example":46},"messageId":{"description":"ID of the first message of the new campaign. Absent when meta.success is false.","type":"integer","example":91},"meta":{"description":"Outcome.","properties":{"success":{"description":"False when the campaign is not an automation campaign, does not exist, or no message was created.","type":"boolean","example":true},"message":{"description":"Present only when success is false: \"Only series campaigns can be transformed to split series campaigns\", \"No messages were created for the new campaign\", \"No Result found for Campaign with id {campaignId}\" or a database error.","type":"string"}},"type":"object"}},"type":"object"},"example":{"campaignId":46,"messageId":91,"meta":{"success":true}}}}}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{campaignId}/stop":{"put":{"summary":"Stop a campaign","description":"Stop a campaign permanently, setting its status to `stopped` (4).\n\nOnly a campaign whose status is `sending` (2) or `paused` (3) can be stopped. Stopping is not reversible through this endpoint: a stopped campaign cannot be resumed or re-enabled. It also finalizes the campaign's sending state - the outstanding process row is removed and the campaign's sent totals are written from the counts recorded so far.\n\nThis endpoint reports business-rule failures in the response body rather than with an\nerror status: an unknown campaign, an automation (\"series\") campaign, a completed campaign and a\ntransition that is not allowed from the campaign's current status all return `200` with `succeeded`\nset to `0`. The `message` text is localized to the account language, so match on `succeeded` rather\nthan on the message.","operationId":"stop-a-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"campaignId","in":"path","description":"id of the campaign whose status is being changed","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Status updated":{"value":"{\n\t\"succeeded\":1,\n\t\"message\":\"Campaign updated.\"\n}"},"Campaign is neither sending nor paused":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"<localized error message>\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","example":1},"message":{"type":"string","example":"Campaign updated."}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Bad request. Campaign id must be non-zero."}}}}},"500":{"description":"500","content":{"text/plain":{"examples":{"Result":{"value":"An error occurred while updating the campaign status."}}}}}},"deprecated":false}},"/campaigns/{id}":{"get":{"summary":"Retrieve a campaign","description":"","operationId":"retrieve-a-campaign","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"path","description":"ID of campaign to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"campaign\": {\n        \"type\": \"single\",\n        \"userid\": \"1\",\n        \"segmentid\": \"0\",\n        \"bounceid\": \"-1\",\n        \"realcid\": \"0\",\n        \"sendid\": \"0\",\n        \"threadid\": \"0\",\n        \"seriesid\": \"0\",\n        \"formid\": \"0\",\n        \"basetemplateid\": \"13b1432dc41b75dda9ff86d84a8593d2b2b9419f\",\n        \"basemessageid\": \"0\",\n        \"addressid\": \"0\",\n        \"source\": \"web\",\n        \"name\": \"Matt Litmus test\",\n        \"cdate\": \"2018-10-10T11:59:43-05:00\",\n        \"mdate\": \"2018-10-10T12:00:23-05:00\",\n        \"sdate\": null,\n        \"ldate\": null,\n        \"send_amt\": \"0\",\n        \"total_amt\": \"0\",\n        \"opens\": \"0\",\n        \"uniqueopens\": \"0\",\n        \"linkclicks\": \"0\",\n        \"uniquelinkclicks\": \"0\",\n        \"subscriberclicks\": \"0\",\n        \"forwards\": \"0\",\n        \"uniqueforwards\": \"0\",\n        \"hardbounces\": \"0\",\n        \"softbounces\": \"0\",\n        \"unsubscribes\": \"0\",\n        \"unsubreasons\": \"0\",\n        \"updates\": \"0\",\n        \"socialshares\": \"0\",\n        \"replies\": \"0\",\n        \"uniquereplies\": \"0\",\n        \"status\": \"0\",\n        \"public\": \"1\",\n        \"mail_transfer\": \"0\",\n        \"mail_send\": \"0\",\n        \"mail_cleanup\": \"0\",\n        \"mailer_log_file\": \"0\",\n        \"tracklinks\": \"all\",\n        \"tracklinksanalytics\": \"0\",\n        \"trackreads\": \"1\",\n        \"trackreadsanalytics\": \"1\",\n        \"analytics_campaign_name\": \"\",\n        \"tweet\": \"0\",\n        \"facebook\": \"0\",\n        \"survey\": \"\",\n        \"embed_images\": \"0\",\n        \"htmlunsub\": \"0\",\n        \"textunsub\": \"0\",\n        \"htmlunsubdata\": null,\n        \"textunsubdata\": null,\n        \"recurring\": \"day1\",\n        \"willrecur\": \"0\",\n        \"split_type\": \"even\",\n        \"split_content\": \"0\",\n        \"split_offset\": \"2\",\n        \"split_offset_type\": \"day\",\n        \"split_winner_messageid\": \"0\",\n        \"split_winner_awaiting\": \"0\",\n        \"responder_offset\": \"0\",\n        \"responder_type\": \"subscribe\",\n        \"responder_existing\": \"0\",\n        \"reminder_field\": \"sdate\",\n        \"reminder_format\": null,\n        \"reminder_type\": \"month_day\",\n        \"reminder_offset\": \"0\",\n        \"reminder_offset_type\": \"day\",\n        \"reminder_offset_sign\": \"+\",\n        \"reminder_last_cron_run\": null,\n        \"activerss_interval\": \"day1\",\n        \"activerss_url\": null,\n        \"activerss_items\": \"10\",\n        \"ip4\": \"643992596\",\n        \"laststep\": \"designer\",\n        \"managetext\": \"0\",\n        \"schedule\": \"0\",\n        \"scheduleddate\": null,\n        \"waitpreview\": \"0\",\n        \"deletestamp\": null,\n        \"replysys\": \"0\",\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/:version/campaigns/1/user\",\n            \"automation\": \"https://:account.api-us1.com/api/:version/campaigns/1/automation\",\n            \"campaignMessage\": \"https://:account.api-us1.com/api/:version/campaigns/1/campaignMessage\",\n            \"links\": \"https://:account.api-us1.com/api/:version/campaigns/1/links\",\n            \"aggregateRevenues\": \"https://:account.api-us1.com/api/:version/campaigns/1/aggregateRevenues\"\n        },\n        \"id\": \"1\",\n        \"user\": \"1\",\n        \"automation\": null\n    }\n}"}},"schema":{"type":"object","properties":{"campaign":{"type":"object","properties":{"type":{"type":"string","example":"single"},"userid":{"type":"string","example":"1"},"segmentid":{"type":"string","example":"0"},"bounceid":{"type":"string","example":"-1"},"realcid":{"type":"string","example":"0"},"sendid":{"type":"string","example":"0"},"threadid":{"type":"string","example":"0"},"seriesid":{"type":"string","example":"0"},"formid":{"type":"string","example":"0"},"basetemplateid":{"type":"string","example":"13b1432dc41b75dda9ff86d84a8593d2b2b9419f"},"basemessageid":{"type":"string","example":"0"},"addressid":{"type":"string","example":"0"},"source":{"type":"string","example":"web"},"name":{"type":"string","example":"Matt Litmus test"},"cdate":{"type":"string","example":"2018-10-10T11:59:43-05:00"},"mdate":{"type":"string","example":"2018-10-10T12:00:23-05:00"},"sdate":{},"ldate":{},"send_amt":{"type":"string","example":"0"},"total_amt":{"type":"string","example":"0"},"opens":{"type":"string","example":"0"},"uniqueopens":{"type":"string","example":"0"},"linkclicks":{"type":"string","example":"0"},"uniquelinkclicks":{"type":"string","example":"0"},"subscriberclicks":{"type":"string","example":"0"},"forwards":{"type":"string","example":"0"},"uniqueforwards":{"type":"string","example":"0"},"hardbounces":{"type":"string","example":"0","description":"Hard bounces recorded for this campaign, cumulative for the campaign, as a string."},"softbounces":{"type":"string","example":"0","description":"Soft bounces recorded for this campaign, cumulative for the campaign, as a string."},"unsubscribes":{"type":"string","example":"0","description":"Contacts who unsubscribed from this campaign's emails, cumulative for the campaign, as a string."},"unsubreasons":{"type":"string","example":"0"},"updates":{"type":"string","example":"0"},"socialshares":{"type":"string","example":"0"},"replies":{"type":"string","example":"0"},"uniquereplies":{"type":"string","example":"0"},"status":{"type":"string","example":"0"},"public":{"type":"string","example":"1"},"mail_transfer":{"type":"string","example":"0"},"mail_send":{"type":"string","example":"0"},"mail_cleanup":{"type":"string","example":"0"},"mailer_log_file":{"type":"string","example":"0"},"tracklinks":{"type":"string","example":"all"},"tracklinksanalytics":{"type":"string","example":"0"},"trackreads":{"type":"string","example":"1"},"trackreadsanalytics":{"type":"string","example":"1"},"analytics_campaign_name":{"type":"string","example":""},"tweet":{"type":"string","example":"0"},"facebook":{"type":"string","example":"0"},"survey":{"type":"string","example":""},"embed_images":{"type":"string","example":"0"},"htmlunsub":{"type":"string","example":"0"},"textunsub":{"type":"string","example":"0"},"htmlunsubdata":{},"textunsubdata":{},"recurring":{"type":"string","example":"day1"},"willrecur":{"type":"string","example":"0"},"split_type":{"type":"string","example":"even"},"split_content":{"type":"string","example":"0"},"split_offset":{"type":"string","example":"2"},"split_offset_type":{"type":"string","example":"day"},"split_winner_messageid":{"type":"string","example":"0"},"split_winner_awaiting":{"type":"string","example":"0"},"responder_offset":{"type":"string","example":"0"},"responder_type":{"type":"string","example":"subscribe"},"responder_existing":{"type":"string","example":"0"},"reminder_field":{"type":"string","example":"sdate"},"reminder_format":{},"reminder_type":{"type":"string","example":"month_day"},"reminder_offset":{"type":"string","example":"0"},"reminder_offset_type":{"type":"string","example":"day"},"reminder_offset_sign":{"type":"string","example":"+"},"reminder_last_cron_run":{},"activerss_interval":{"type":"string","example":"day1"},"activerss_url":{},"activerss_items":{"type":"string","example":"10"},"ip4":{"type":"string","example":"643992596"},"laststep":{"type":"string","example":"designer"},"managetext":{"type":"string","example":"0"},"schedule":{"type":"string","example":"0"},"scheduleddate":{},"waitpreview":{"type":"string","example":"0"},"deletestamp":{},"replysys":{"type":"string","example":"0"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/:version/campaigns/1/user"},"automation":{"type":"string","example":"https://:account.api-us1.com/api/:version/campaigns/1/automation"},"campaignMessage":{"type":"string","example":"https://:account.api-us1.com/api/:version/campaigns/1/campaignMessage"},"links":{"type":"string","example":"https://:account.api-us1.com/api/:version/campaigns/1/links"},"aggregateRevenues":{"type":"string","example":"https://:account.api-us1.com/api/:version/campaigns/1/aggregateRevenues"}}},"id":{"type":"string","example":"1"},"user":{"type":"string","example":"1"},"automation":{}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a campaign","description":"Deletes a campaign through the campaigns resource. Runs the same delete as DELETE /campaigns/{id}/delete: the campaign row is archived, and its folder associations, any pending approval request and any queued automation sends are removed as well; campaigns that reference it as their source are deleted too. Only the success body differs: an empty object here. Requires the Campaigns module and permission to delete campaigns. A campaign the user may not delete answers 404, the same as one that does not exist.","operationId":"delete-a-campaign-record","parameters":[{"name":"id","in":"path","description":"ID of the campaign to delete","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The account does not have the Campaigns module, or the user may not delete campaigns. Body: errors, a list with one item carrying status 403, title and detail, the localized reason."},"404":{"description":"No campaign with this ID, or the delete was refused for this user. Body: errors, a list with one item carrying status 404, title and detail, the localized campaign-not-found message."},"422":{"description":"The ID is not a positive integer. Body: errors, a list with one item carrying status 422, title \"Invalid attribute\", detail \"Campaign id must be a positive integer.\" and source.pointer /data/attributes/id."}},"x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/campaigns/{id}/campaignMessages":{"get":{"summary":"Retrieve campaign messages associated to campaign","description":"Retrieve the per-message reporting totals for a campaign. Each element of `campaignMessages` corresponds to one message the campaign sent: a single element for a regular campaign, and one element per variation for a split (A/B) campaign, which is the only way to break a split campaign's results down by variation.\n\nThe counters are lifetime totals for the message and cannot be constrained to a date range.\n\nThis collection is not paginated: every message of the campaign is returned, and `limit`, `offset` and `meta.total` do not apply. The endpoint is read only; `POST`, `PUT` and `DELETE` return `403`.","operationId":"retrieve-campaign-messages-associated-campaign","x-canonical-resource":"campaign_message","parameters":[{"name":"id","in":"path","description":"ID of campaign to retrieve campaign messages for","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Split campaign with two messages":{"value":"{\n    \"campaignMessages\": [\n        {\n            \"messageid\": \"3\",\n            \"campaignid\": \"1\",\n            \"percentage\": \"50\",\n            \"sourcesize\": \"0\",\n            \"send_amt\": \"500\",\n            \"total_amt\": \"500\",\n            \"opens\": \"241\",\n            \"uniqueopens\": \"180\",\n            \"linkclicks\": \"64\",\n            \"uniquelinkclicks\": \"51\",\n            \"subscriberclicks\": \"48\",\n            \"forwards\": \"2\",\n            \"uniqueforwards\": \"2\",\n            \"hardbounces\": \"1\",\n            \"softbounces\": \"3\",\n            \"unsubscribes\": \"2\",\n            \"unsubreasons\": \"1\",\n            \"updates\": \"0\",\n            \"socialshares\": \"0\",\n            \"replies\": \"5\",\n            \"uniquereplies\": \"4\",\n            \"spamcheck_score\": \"-1\",\n            \"spamcheck_max\": \"0\",\n            \"initial_split_percentage\": \"50\",\n            \"verified_opens\": \"160\",\n            \"verified_unique_opens\": \"150\",\n            \"repair_timestamp\": null,\n            \"screenshot\": \"//:account.img-us3.com/_screenshot_/915e875e-c68f-4683-9ee9-5e18f947a5fd.jpeg\",\n            \"subject\": \"Your journey starts here\",\n            \"links\": {\n                \"campaign\": \"https://:account.api-us1.com/api/3/campaignMessages/1/campaign\",\n                \"message\": \"https://:account.api-us1.com/api/3/campaignMessages/1/message\"\n            },\n            \"id\": \"1\",\n            \"campaign\": \"1\",\n            \"message\": \"3\"\n        },\n        {\n            \"messageid\": \"4\",\n            \"campaignid\": \"1\",\n            \"percentage\": \"50\",\n            \"sourcesize\": \"0\",\n            \"send_amt\": \"500\",\n            \"total_amt\": \"500\",\n            \"opens\": \"198\",\n            \"uniqueopens\": \"165\",\n            \"linkclicks\": \"71\",\n            \"uniquelinkclicks\": \"60\",\n            \"subscriberclicks\": \"57\",\n            \"forwards\": \"1\",\n            \"uniqueforwards\": \"1\",\n            \"hardbounces\": \"0\",\n            \"softbounces\": \"2\",\n            \"unsubscribes\": \"4\",\n            \"unsubreasons\": \"2\",\n            \"updates\": \"0\",\n            \"socialshares\": \"0\",\n            \"replies\": \"3\",\n            \"uniquereplies\": \"3\",\n            \"spamcheck_score\": \"-1\",\n            \"spamcheck_max\": \"0\",\n            \"initial_split_percentage\": \"50\",\n            \"verified_opens\": \"150\",\n            \"verified_unique_opens\": \"141\",\n            \"repair_timestamp\": null,\n            \"screenshot\": \"//:account.img-us3.com/_screenshot_/2c1f0b7a-3c62-4c11-8b0e-0d2d5c1a77b1.jpeg\",\n            \"subject\": \"Start your journey today\",\n            \"links\": {\n                \"campaign\": \"https://:account.api-us1.com/api/3/campaignMessages/2/campaign\",\n                \"message\": \"https://:account.api-us1.com/api/3/campaignMessages/2/message\"\n            },\n            \"id\": \"2\",\n            \"campaign\": \"1\",\n            \"message\": \"4\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"campaignMessages":{"type":"array","items":{"type":"object","properties":{"messageid":{"type":"string","description":"id of the message this row reports on","example":"3"},"campaignid":{"type":"string","description":"id of the campaign","example":"1"},"percentage":{"type":"string","description":"share of the campaign's recipients this message was sent to","example":"50"},"sourcesize":{"type":"string","description":"size of the source list at send time","example":"0"},"send_amt":{"type":"string","description":"number of sends attempted for this message","example":"500"},"total_amt":{"type":"string","description":"number of sends delivered for this message","example":"500"},"opens":{"type":"string","description":"total opens, including repeat opens","example":"241"},"uniqueopens":{"type":"string","description":"number of contacts who opened at least once","example":"180"},"linkclicks":{"type":"string","description":"total link clicks, including repeat clicks","example":"64"},"uniquelinkclicks":{"type":"string","description":"number of distinct links clicked","example":"51"},"subscriberclicks":{"type":"string","description":"number of contacts who clicked at least one link","example":"48"},"forwards":{"type":"string","description":"total forwards","example":"2"},"uniqueforwards":{"type":"string","description":"number of contacts who forwarded at least once","example":"2"},"hardbounces":{"type":"string","description":"number of hard bounces","example":"1"},"softbounces":{"type":"string","description":"number of soft bounces","example":"3"},"unsubscribes":{"type":"string","description":"number of unsubscribes","example":"2"},"unsubreasons":{"type":"string","description":"number of unsubscribes that included a reason","example":"1"},"updates":{"type":"string","description":"number of contacts who updated their profile","example":"0"},"socialshares":{"type":"string","description":"number of social shares","example":"0"},"replies":{"type":"string","description":"total replies","example":"5"},"uniquereplies":{"type":"string","description":"number of contacts who replied at least once","example":"4"},"spamcheck_score":{"type":"string","description":"spam check score, `-1` when the message has not been checked","example":"-1"},"spamcheck_max":{"type":"string","description":"maximum possible spam check score","example":"0"},"initial_split_percentage":{"type":"string","description":"split percentage this message started with","example":"50"},"verified_opens":{"type":"string","description":"opens confirmed as human","example":"241"},"verified_unique_opens":{"type":"string","description":"unique opens confirmed as human","example":"180"},"screenshot":{"type":"string","description":"URL of the rendered preview image of the message","example":"//:account.img-us3.com/_screenshot_/915e875e-c68f-4683-9ee9-5e18f947a5fd.jpeg"},"subject":{"type":"string","description":"subject line of the message","example":"Your journey starts here"},"repair_timestamp":{"type":["string","null"],"description":"timestamp of the last statistics repair, `null` when the row has never been repaired","example":null},"links":{"type":"object","properties":{"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/campaign"},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/campaignMessages/1/message"}}},"id":{"type":"string","description":"id of the campaign message row","example":"1"},"campaign":{"type":"string","description":"id of the related campaign","example":"1"},"message":{"type":"string","description":"id of the related message","example":"3"}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Campaign with id 2\"\n}"}}}}}},"deprecated":false}},"/campaigns/{id}/copy":{"post":{"summary":"Duplicate Campaign","description":"","operationId":"duplicate-campaign","parameters":[{"name":"id","in":"path","description":"id of the source campaign","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always 1 when the copy was made.","type":"integer","default":0,"example":1},"message":{"description":"Says the draft was copied.","type":"string","example":"Campaign draft copied."},"newCampaignId":{"description":"ID of the new campaign created as the copy.","type":"integer","default":0,"example":217}},"type":"object"},"examples":{"Result":{"summary":"The copy was made","value":"{\n\t\"succeeded\":1,\n  \"message\":\"Campaign draft copied.\",\n  \"newCampaignId\":217\n}"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"summary":"The campaign cannot be copied","value":"'Bad request. You are not allowed to copy this campaign.'"}}}}}},"deprecated":false,"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false}},"/campaigns/{id}/delete":{"delete":{"summary":"Delete a campaign","description":"Delete an existing campaign. The campaign row is archived, and its folder associations, any pending approval request and any queued automation sends are removed as well. Campaigns that reference this campaign as their source are deleted too.\n\nThis endpoint reports failures in the response body rather than with an error status: a campaign that does not exist, or a user without permission to delete campaigns, both return `200` with `succeeded` set to `0`.","operationId":"delete-a-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"id of the campaign to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Campaign deleted":{"value":"{\n\t\"succeeded\":1,\n\t\"message\":\"Campaign deleted.\"\n}"},"Campaign not found":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"Campaign not found.\"\n}"},"No permission to delete campaigns":{"value":"{\n\t\"succeeded\":0,\n\t\"message\":\"You do not have a permission to delete campaigns.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","example":1,"default":0},"message":{"type":"string","example":"Campaign deleted."}}}}}},"400":{"description":"400","content":{"text/plain":{"examples":{"Result":{"value":"Bad request. Campaign id must be non-zero."}}}}},"405":{"description":"405","content":{"text/plain":{"examples":{"Result":{"value":"Method not supported. Only DELETE supported."}}}}}},"deprecated":false}},"/campaigns/{id}/duplication-entitlements":{"get":{"summary":"List the entitlements a campaign uses that the account lacks","description":"Checks the campaign's messages for features the account is not entitled to, so the app can warn before the campaign is duplicated: predictive content (a message uses predictive content and the account lacks it), conditional content (a message contains a %/if% block and the account lacks it) and ecommerce product blocks (a message contains a %/product-block% and the account has neither the product catalog nor ecommerce). Served by the campaigns/duplication-entitlements file for the /campaigns/{id}/duplication-entitlements address. When nothing is missing the body is an empty JSON array, [], not an object. Only GET is accepted.","operationId":"list-campaign-missing-duplication-entitlements","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The missing entitlements, keyed by entitlement, or [] when none are missing","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"One key per missing entitlement; each value is the localized warning to show.","properties":{"predictive-content":{"type":"string","description":"Present when a message uses predictive content and the account is not entitled to it."},"conditional-content":{"type":"string","description":"Present when a message contains conditional content and the account is not entitled to it."},"ecommerce":{"type":"string","description":"Present when a message contains a product block and the account has neither the product catalog nor ecommerce."}}},{"type":"array","description":"Empty: nothing is missing.","maxItems":0,"items":{}}]}}}},"400":{"description":"The campaign ID is not a positive number. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Bad request. Campaign id must be non-zero."}}}},"405":{"description":"The method is not GET. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only GET supported."}}}}},"deprecated":false,"x-internal":true}},"/campaigns/{id}/edit":{"put":{"summary":"Edit campaign","description":"","operationId":"edit-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Campaign name"},"type":{"type":"string","description":"Campaign type"},"segmentId":{"type":"string","description":"Id of selected segment. Both integer segment id's and string based segment id's are supported."},"addressId":{"type":"integer","description":"Id of selected address","format":"int32"},"listIds":{"type":"array","description":"Array of selected lists ids","items":{"type":"integer","format":"int32"}},"replyTrackingEnabled":{"type":"boolean","description":"Turn on/off reply tracking"},"linkTrackingEnabled":{"type":"boolean","description":"Turn on/off link tracking"},"googleAnalyticsLinkTrackingEnabled":{"type":"boolean","description":"Turn on/off google analytics link tracking"},"googleAnalyticsCampaignName":{"type":"string","description":"Name of campaign in google analytics"},"readTrackingEnabled":{"type":"boolean","description":"Turn on/off read tracking"},"sendToExistingSubscribers":{"type":"boolean","description":"Should send only to existing customers"},"canSplitContent":{"type":"boolean","description":"Campaign can contains split content"},"recurring":{"type":"boolean","description":"Is campaign recurring"},"responderDaysOffset":{"type":"integer","description":"Determine value of responder offset in days","format":"int32"},"responderHoursOffset":{"type":"integer","description":"Determine value of responder offset in hours","format":"int32"},"scheduledDate":{"type":"string","description":"Date of sending"},"reminderField":{"type":"string","description":"Field basic on witch reminder will be triggered"},"reminderOffset":{"type":"integer","description":"Value of reminder offset","format":"int32"},"reminderOffsetType":{"type":"string","description":"Type of reminder offset"},"reminderType":{"type":"string","description":"Format of reminder date"},"rssInterval":{"type":"integer","description":"Interval for RSS","format":"int32"},"splitType":{"type":"string","description":"Type of split campaign"},"splitWinnerWaitPeriod":{"type":"integer","description":"Period wait time","format":"int32"},"splitWinnerWaitPeriodType":{"type":"string","description":"Determine period type"},"publicCampaignArchive":{"type":"boolean","description":"Is campaign public"}},"additionalProperties":false}}}},"deprecated":false}},"/campaigns/{id}/links":{"get":{"summary":"Retrieve links associated to campaign","description":"","operationId":"retrieve-links-associated-campaign","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"path","description":"ID of campaign to retrieve Links for","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"links\": [\n        {\n            \"campaignid\": \"1\",\n            \"messageid\": \"3\",\n            \"link\": \"open\",\n            \"name\": \"Read Tracker\",\n            \"ref\": \"\",\n            \"tracked\": \"1\",\n            \"links\": {\n                \"campaign\": \"https://:account.api-us1.com/api/3/links/1/campaign\",\n                \"message\": \"https://:account.api-us1.com/api/3/links/1/message\"\n            },\n            \"id\": \"1\",\n            \"campaign\": \"1\",\n            \"message\": \"3\"\n        },\n        {\n            \"campaignid\": \"1\",\n            \"messageid\": \"0\",\n            \"link\": \"open\",\n            \"name\": \"Read Tracker\",\n            \"ref\": \"\",\n            \"tracked\": \"1\",\n            \"links\": {\n                \"campaign\": \"https://:account.api-us1.com/api/3/links/2/campaign\",\n                \"message\": \"https://:account.api-us1.com/api/3/links/2/message\"\n            },\n            \"id\": \"2\",\n            \"campaign\": \"1\",\n            \"message\": null\n        }\n    ]\n}"},"No links":{"value":"{\n    \"links\": []\n}"}},"schema":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"campaignid":{"type":"string","example":"1"},"messageid":{"type":"string","example":"3"},"link":{"type":"string","example":"open"},"name":{"type":"string","example":"Read Tracker"},"ref":{"type":"string","example":""},"tracked":{"type":"string","example":"1"},"links":{"type":"object","properties":{"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/links/1/campaign"},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/links/1/message"}}},"id":{"type":"string","example":"1"},"campaign":{"type":"string","example":"1"},"message":{"type":"string","example":"3"}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Campaign with id 2\"\n}"}}}}}},"deprecated":false}},"/campaigns/{id}/resend":{"get":{"summary":"Count the contacts a campaign resend would reach","description":"How many contacts a resend of the campaign would go to, without creating anything. unread resends to the contacts of the original audience who did not open the original campaign; newsub resends to the contacts of the original audience who subscribed after the original send date. A split campaign cannot be resent. Served by the campaigns/resend file for the /campaigns/{id}/resend address, which answers GET and POST only.","operationId":"retrieve-campaign-resend-audience-size","x-canonical-resource":"campaign","parameters":[{"name":"id","in":"path","description":"ID of the original campaign","required":true,"schema":{"type":"integer"}},{"name":"resendType","in":"query","description":"unread or newsub. Required: leaving it out fails the request with a server error rather than a 400.","required":true,"schema":{"type":"string","enum":["unread","newsub"]}}],"responses":{"200":{"description":"The audience size","content":{"application/json":{"schema":{"type":"object","properties":{"resend":{"type":"object","description":"The resend that was sized.","properties":{"sendAmount":{"type":"integer","description":"Number of contacts the resend would go to; 0 when there are none.","example":120},"resendType":{"type":"string","description":"The resendType sent.","example":"unread"}}}}},"example":{"resend":{"sendAmount":120,"resendType":"unread"}}}}},"400":{"description":"The request was refused. The body is plain text, one of: \"The parameter resendType ('unread' or 'newsub') is required\", \"Invalid resendType. Please retry using either 'unread' or 'newsub'\", \"Invalid campaign ID provided\", \"Resend is not available for split campaigns\".","content":{"text/plain":{"schema":{"type":"string"}}}},"405":{"description":"The method is not GET or POST. Body: errors, a list with one item carrying status 405, title and detail."}},"deprecated":false,"x-internal":true},"post":{"summary":"Resend a campaign to the contacts it missed","description":"Creates a copy of the campaign addressed to a narrower audience and schedules it to send right away. unread resends to the contacts of the original audience who did not open the original campaign; newsub resends to the contacts of the original audience who subscribed after the original send date. The copy is owned by the authenticated user, may take a new name and a new subject for all its messages, is set to send now and is queued for initialization with status scheduled (1). A failure to create the copy is a server error. A split campaign cannot be resent, and a resend with nobody to send to is refused.","operationId":"resend-a-campaign","x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the original campaign","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["resendType"],"properties":{"resendType":{"type":"string","enum":["unread","newsub"],"description":"Who the resend goes to: unread or newsub."},"name":{"type":"string","description":"Name of the new campaign. Optional; the copy keeps the original campaign's name when left out."},"subject":{"type":"string","description":"Subject for every message of the new campaign. Optional; the original subjects are kept when left out."}}},"example":{"resendType":"unread","name":"Spring sale (resend)","subject":"In case you missed it"}}}},"responses":{"201":{"description":"The resend campaign was created and scheduled","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"object","description":"The new campaign record, serialized the way the campaigns resource serializes a campaign."}}}}}},"400":{"description":"The request was refused. The body is plain text, one of: \"The parameter resendType ('unread' or 'newsub') is required\", \"Invalid resendType. Please retry using either 'unread' or 'newsub'\", \"Invalid campaign ID provided\", \"Resend is not available for split campaigns\", or \"No contacts to send to\".","content":{"text/plain":{"schema":{"type":"string"}}}},"405":{"description":"The method is not GET or POST. Body: errors, a list with one item carrying status 405, title and detail."}},"deprecated":false,"x-internal":true}},"/campaigns/{id}/send":{"put":{"summary":"Send a scheduled campaign now","description":"Sends a scheduled campaign immediately instead of at its scheduled time: sets its send date to now and queues it for initialization. Only a regular campaign (single, split, recurring, RSS or text, not sent by an automation) whose status is scheduled (1) qualifies, and its from address must be verified. Business-rule failures are not error statuses: they answer 200 with succeeded 0 and a localized message. Only PUT is accepted.","operationId":"send-a-scheduled-campaign-now","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the campaign","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Sent, or refused with a reason","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the campaign.","example":12},"succeeded":{"type":"integer","enum":[0,1],"description":"1 when the campaign was queued to send, 0 when it was refused.","example":1},"message":{"type":"string","description":"What happened, localized to the account language: initiated for sending, or why not (not found, not scheduled, not a regular campaign, from domain not verified, send date could not be updated)."}}},"example":{"id":12,"succeeded":1,"message":"<localized success message>"}}}},"400":{"description":"The campaign ID is not a positive number. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Bad request. Campaign id must be non-zero."}}}},"405":{"description":"The method is not PUT. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only PUT supported."}}}},"500":{"description":"Sending failed unexpectedly. Body: errors, a list with one item carrying status \"500\" and detail \"Failed to send campaign\"."}},"deprecated":false,"x-internal":true}},"/campaigns/{id}/template":{"post":{"summary":"Save a campaign as a template","description":"Creates an email template from each message of the campaign, owned by the user named in the User-Id request header. The caller must be allowed to assign ownership to that user: the main admin group, the user themselves, or a user in a shared group. A one-message campaign yields one template; a multi-message (for example split) campaign yields one per message, all listed in ids. Only POST is accepted.","operationId":"save-a-campaign-as-a-template","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the campaign to copy","required":true,"schema":{"type":"integer"}},{"name":"User-Id","in":"header","description":"ID of the user who will own the new templates.","required":true,"schema":{"type":"integer"},"example":1}],"responses":{"200":{"description":"The templates were created","content":{"application/json":{"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"Always 1.","example":1},"message":{"type":"string","description":"Always \"Template(s) created successfully.\".","example":"Template(s) created successfully."},"id":{"type":"integer","nullable":true,"description":"ID of the first template created.","example":88},"ids":{"type":"array","description":"IDs of every template created, one per message.","items":{"type":"integer"},"example":[88]}}},"example":{"succeeded":1,"message":"Template(s) created successfully.","id":88,"ids":[88]}}}},"400":{"description":"The request was refused. The body is plain text: the User-Id header is missing, the caller may not assign templates to that user, the campaign ID is not a positive number, or no campaign has that ID.","content":{"text/plain":{"schema":{"type":"string","example":"Bad request. You cannot assign this template to that user."}}}},"405":{"description":"The method is not POST. The body is plain text.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only POST supported."}}}}},"deprecated":false,"x-internal":true}},"/canduConfig":{"get":{"summary":"Retrieve the Candu configuration","description":"The identity, client token, traits and variables the app passes to Candu, the in-app onboarding content service, for the signed-in user: account plan and onboarding answers, counts of automations, contacts, custom fields, pipelines, tags, campaigns and forms, connected integrations, and the user's name and trial days left. The result is cached in the session for an hour; `clear_candu` rebuilds it. When the request's `Referer` is the Getting Started page (`/app/overview/setup`), the four checklist traits are recomputed and added on every call. Internal: backs the in-app onboarding content.","operationId":"retrieve-candu-config","x-canonical-resource":"activecampaign_account","parameters":[{"name":"clear_candu","in":"query","description":"When present and not `0` or empty, rebuild the configuration instead of reading the copy cached in the session, and cache the new one.","required":false,"schema":{"type":"string"},"example":"1"},{"name":"clear_candu","in":"cookie","description":"Same as the `clear_candu` query parameter; when both are sent, the cookie wins.","required":false,"schema":{"type":"string"}},{"name":"Referer","in":"header","description":"When it contains `/app/overview/setup`, the response also carries the checklist traits (`checklistActiveContacts`, `checklistConnectedIntegrations`, `checklistCampaigns`, `checklistAutomations`), computed fresh.","required":false,"schema":{"type":"string"},"example":"https://example.activehosted.com/app/overview/setup"}],"responses":{"200":{"description":"The Candu configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanduConfig"}}}},"405":{"description":"The method is not GET. The `Allow` header lists GET.","headers":{"Allow":{"description":"`GET`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"`405`.","example":405},"title":{"type":"string","description":"Translated title of the HTTP status."}}}}}}}}},"500":{"description":"Building the configuration failed. The failure is logged and the generic API error body is returned.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Generic error text.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/channel/whatsapp/channels/whatsapp/template":{"get":{"operationId":"list-whatsapp-templates","x-canonical-resource":"whatsapp_template","description":"Lists WhatsApp Templates. You can search with the `name` and `status` fields using the `?search=my-template-name` query parameter.","summary":"List WhatsApp Templates","parameters":[{"in":"query","name":"category","schema":{"type":"string","enum":["ACCOUNT_UPDATE","ALERT_UPDATE","APPOINTMENT_UPDATE","AUTHENTICATION","AUTO_REPLY","ISSUE_RESOLUTION","MARKETING","OTP","PAYMENT_UPDATE","PERSONAL_FINANCE_UPDATE","RESERVATION_UPDATE","SHIPPING_UPDATE","TICKET_UPDATE","TRANSACTIONAL","TRANSPORTATION_UPDATE","UTILITY"]},"description":"* `ACCOUNT_UPDATE` - Account Update\n* `PAYMENT_UPDATE` - Payment Update\n* `PERSONAL_FINANCE_UPDATE` - Personal Finance Update\n* `SHIPPING_UPDATE` - Shipping Update\n* `RESERVATION_UPDATE` - Reservation Update\n* `ISSUE_RESOLUTION` - Issue Resolution\n* `APPOINTMENT_UPDATE` - Appointment Update\n* `TRANSPORTATION_UPDATE` - Transportation Update\n* `TICKET_UPDATE` - Ticket Update\n* `ALERT_UPDATE` - Alert Update\n* `AUTO_REPLY` - Auto Reply\n* `TRANSACTIONAL` - Transactional\n* `MARKETING` - Marketing\n* `OTP` - Otp\n* `AUTHENTICATION` - Authentication\n* `UTILITY` - Utility"},{"in":"query","name":"category__in","schema":{"type":"array","items":{"type":"string"}},"description":"Multiple values may be separated by commas.","explode":false,"style":"form"},{"in":"query","name":"channel","schema":{"type":"integer"}},{"in":"query","name":"channel__in","schema":{"type":"array","items":{"type":"integer"}},"description":"Multiple values may be separated by commas.","explode":false,"style":"form"},{"name":"ordering","required":false,"in":"query","description":"Which field to use when ordering the results.","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"A page number within the paginated result set.","schema":{"type":"integer"}},{"name":"page_size","required":false,"in":"query","description":"Number of results to return per page.","schema":{"type":"integer"}},{"name":"search","required":false,"in":"query","description":"A search term.","schema":{"type":"string"}},{"in":"query","name":"status","schema":{"type":"string","enum":["approved","deleted","disabled","draft","in_appeal","pending","pending_deletion","rejected","submitted"]},"description":"* `draft` - Draft\n* `approved` - Approved\n* `in_appeal` - In Appeal\n* `pending` - Pending\n* `rejected` - Rejected\n* `pending_deletion` - Pending Deletion\n* `deleted` - Deleted\n* `disabled` - Disabled\n* `submitted` - Submitted"},{"in":"query","name":"status__in","schema":{"type":"array","items":{"type":"string"}},"description":"Multiple values may be separated by commas.","explode":false,"style":"form"}],"tags":["Templates"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedWhatsAppTemplateSimpleReadList"}}},"description":""}}}},"/channel/whatsapp/channels/whatsapp/template/{id}":{"put":{"operationId":"channels_whatsapp_template_update","x-canonical-resource":"whatsapp_template","x-destructive":true,"x-bulk-operation":false,"description":"Update a WhatsApp Template by Id.","summary":"Update WhatsApp Template","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Templates"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateRead"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateRead"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateRead"}}},"required":true},"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateRead"}}},"description":""}}},"delete":{"operationId":"delete-whatsapp-template","x-canonical-resource":"whatsapp_template","x-destructive":true,"x-bulk-operation":false,"description":"Deletes a WhatsApp Template by Id.","summary":"Delete WhatsApp Template","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Templates"],"security":[{"tokenAuth":[]}],"responses":{"204":{"description":"No response body"}}},"get":{"operationId":"get-whatsapp-template","x-canonical-resource":"whatsapp_template","description":"Gets a WhatsApp Template by Id.","summary":"Get WhatsApp Template","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Templates"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateRead"}}},"description":""}}}},"/channel/whatsapp/channels/whatsapp/template/{id}/send":{"post":{"operationId":"send-a-whatsapp-template-message","x-canonical-resource":"whatsapp_message","x-destructive":false,"x-bulk-operation":false,"description":"Send a single WhatsApp message: select a template to use and call our endpoint with the recipient phone number and the variables the template needs. That's it!","summary":"Send a WhatsApp Template","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"Template Id","required":true,"examples":{"TheTemplateIdThatWeWantToSend":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"The Template Id that we want to send"}}}],"tags":["Templates"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateSend"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateSend"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateSend"}}},"required":true},"security":[{"tokenAuth":[]}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplateSendPublicResponse"},"examples":{"WhatsAppTemplateSendPublicResponse":{"value":{"id":"a513da3a-8b73-42aa-a938-0eb1e0141533","conversation":"ee49ab6c-dfd8-4cb6-a512-5880f4385622"},"description":"Returns the Message Id and its Conversation Id."}}}},"description":""}}}},"/channel/whatsapp/flow-execution":{"get":{"operationId":"list-flow-execution","x-canonical-resource":"whatsapp_flow","description":"Lists Flow Executions. ","summary":"List Flow Executions","parameters":[{"in":"query","name":"flow","schema":{"type":"string","format":"uuid"},"description":"A Flow Id to filter the Flow Executions and only get those from that Flow.","examples":{"OnlyReturnTheFlowExecutionsOfThisFlow":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Only return the Flow Executions of this Flow"}}},{"in":"query","name":"flow_version","schema":{"type":"string","format":"uuid"},"description":"A Flow Version Id to filter the Flow Executions and only get those from that Flow Version."},{"name":"page","required":false,"in":"query","description":"A page number within the paginated result set.","schema":{"type":"integer"}},{"in":"query","name":"search","schema":{"type":"string"},"description":"You can search with the `status`, `created_by__email` fields.","examples":{"CreatedByEmail":{"value":"jdoe@example.com","summary":"created by email"},"With`PROCESSING`Status":{"value":"Processing","summary":"with `PROCESSING` status"},"With`READY`Status":{"value":"Ready","summary":"with `READY` status"},"With`AWAITINGCONFIRMATION`Status":{"value":"Awaiting Confirmation","summary":"with `AWAITING_CONFIRMATION` status"},"With`CONFIRMED`Status":{"value":"Confirmed","summary":"with `CONFIRMED` status"},"With`STARTING`Status":{"value":"Starting","summary":"with `STARTING` status"},"With`RUNNING`Status":{"value":"Running","summary":"with `RUNNING` status"},"With`COMPLETED`Status":{"value":"Completed","summary":"with `COMPLETED` status"},"With`CANCELED`Status":{"value":"Canceled","summary":"with `CANCELED` status"}}}],"tags":["Flows"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedFlowExecutionListList"}}},"description":""}}}},"/channel/whatsapp/flow-execution-contact":{"get":{"operationId":"list-flow-execution-contact","x-canonical-resource":"whatsapp_flow","description":"Lists Flow Execution Contacts.","summary":"List Flow Execution Contacts","parameters":[{"in":"query","name":"contact","schema":{"type":"string","format":"uuid"},"description":"A Contact Id to filter the Flow Execution Contacts and only get those from that Contact.","examples":{"OnlyReturnTheFlowExecutionsContactOfThisContact":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Only return the Flow Executions Contact of this Contact"}}},{"in":"query","name":"execution_steps__step_id","schema":{"type":"string","format":"uuid"},"description":"An Execution Step Id to filter the Flow Execution Contacts and only get those from that Execution Step."},{"in":"query","name":"flow","schema":{"type":"string","format":"uuid"},"description":"A Flow Id to filter the Flow Execution Contacts and only get those from that Flow.","examples":{"OnlyReturnTheFlowExecutionsContactOfThisFlow":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Only return the Flow Executions Contact of this flow"}}},{"in":"query","name":"flow_execution","schema":{"type":"string","format":"uuid"},"description":"A Flow Execution Id to filter the Flow Execution Contacts and only get those from that Flow Execution.","examples":{"OnlyReturnTheFlowExecutionsContactOfThisFlowExecution":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Only return the Flow Executions Contact of this Flow Execution"}}},{"in":"query","name":"flow_version","schema":{"type":"string","format":"uuid"},"description":"A Flow Version Id to filter the Flow Execution Contacts and only get those from that Flow Version."},{"in":"query","name":"id","schema":{"type":"string","format":"uuid"},"description":"A Flow Execution Contact Id to filter and only get that specific Flow Execution Contact."},{"in":"query","name":"is_active","schema":{"type":"boolean"},"description":"A boolean param to filter between active/in progress Flow Execution Contacs.\n\n If the parameter is omitted it will respond with Flow Execution Contacts with any `status`.","examples":{"OnlyReturnTheFlowExecutionsContactThatAreWithStatus`READY`Or`RUNNING`.":{"value":["true","any-truthy-value",1],"summary":"Only return the Flow Executions Contact that are with status `READY` or `RUNNING`."},"OnlyReturnTheFlowExecutionsContactThatAreWithStatus`CANCELED`Or`COMPLETED`.":{"value":["false",0],"summary":"Only return the Flow Executions Contact that are with status `CANCELED` or `COMPLETED`."}}},{"name":"page","required":false,"in":"query","description":"A page number within the paginated result set.","schema":{"type":"integer"}},{"name":"page_size","required":false,"in":"query","description":"Number of results to return per page.","schema":{"type":"integer"}},{"in":"query","name":"search","schema":{"type":"string"},"description":"You can search with the `contact__phone`, `contact__first_name`, `contact__last_name`, `contact__email` fields.","examples":{"ByContactEmail":{"value":"jdoe@example.com","summary":"by contact email"},"ByContactPhone":{"value":"+525512345678","summary":"by contact phone"},"ByContactLastName":{"value":"Smith","summary":"by contact last_name"},"ByContactFirstName":{"value":"Jonh","summary":"by contact first_name"}}}],"tags":["Flows"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedFlowExecutionContactListSimpleList"}}},"description":""}}}},"/channel/whatsapp/flow-execution-contact/{id}":{"get":{"operationId":"get-flow-execution-contact","x-canonical-resource":"whatsapp_flow","description":"Get Flow Execution Contact by Id.","summary":"Get Flow Execution Contact by Id","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"A Flow Execution Contact Id to Retrieve.","required":true,"examples":{"QueryById":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Query by Id"}}}],"tags":["Flows"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowExecutionContactReadDetail"}}},"description":""}}}},"/channel/whatsapp/flow-execution/{id}":{"get":{"operationId":"get-flow-execution","x-canonical-resource":"whatsapp_flow","description":"Get Flow Execution by Id.","summary":"Get Flow Execution","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"A Flow Execution Id to retrieve.","required":true,"examples":{"QueryById":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Query by Id"}}}],"tags":["Flows"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowExecutionReadDetail"}}},"description":""}}}},"/channel/whatsapp/flow/{id}/run":{"post":{"operationId":"create-a-flow-execution","x-canonical-resource":"whatsapp_flow","x-destructive":true,"x-bulk-operation":false,"description":"Create a Flow Execution of a Flow.","summary":"Create a Flow Execution","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"A Flow Id to create a Flow Execution.","required":true,"examples":{"CreateByFlowId":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Create by Flow Id"}}}],"tags":["Flows"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowExecutionCreateRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/FlowExecutionCreateRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/FlowExecutionCreateRequest"}}},"required":true},"security":[{"tokenAuth":[]}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowExecutionEdit"}}},"description":""}}}},"/channel/whatsapp/inbox/conversation":{"get":{"operationId":"list-conversations","x-canonical-resource":"whatsapp_conversation","description":"Lists Conversations. ","summary":"List Conversations","parameters":[{"in":"query","name":"contact","schema":{"type":"string","format":"uuid"},"description":"A Contact Id to filter the Conversations and only get those from that Contact.","examples":{"OnlyReturnTheConversationsOfThisContact":{"value":"a3ff7ee5-0c11-49e2-a0d6-7e316626f7b1","summary":"Only return the Conversations of this Contact"}}},{"name":"page","required":false,"in":"query","description":"A page number within the paginated result set.","schema":{"type":"integer"}},{"name":"page_size","required":false,"in":"query","description":"Number of results to return per page.","schema":{"type":"integer"}},{"name":"search","required":false,"in":"query","description":"A search term.","schema":{"type":"string"}}],"tags":["Conversations"],"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedConversationReadSimpleList"}}},"description":""}}}},"/channel/whatsapp/inbox/conversation/{id}/update":{"patch":{"operationId":"partially-update-a-conversation","x-canonical-resource":"whatsapp_conversation","x-destructive":true,"x-bulk-operation":false,"description":"Partially update a Conversation","summary":"Partially Update a Conversation","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Conversations"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchedConversationEdit"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/PatchedConversationEdit"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/PatchedConversationEdit"}}}},"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationEdit"}}},"description":""}}},"put":{"operationId":"update-a-conversation","x-canonical-resource":"whatsapp_conversation","x-destructive":true,"x-bulk-operation":false,"description":"Update a Conversation","summary":"Update a conversation","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Conversations"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationEdit"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ConversationEdit"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ConversationEdit"}}},"required":true},"security":[{"tokenAuth":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationEdit"}}},"description":""}}}},"/configs/{id}":{"put":{"summary":"Update settings","description":"","operationId":"set-config","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the config to edit","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"config\": {\n        \"keyname\": \"pagination.users_index\",\n        \"section\": \"\",\n        \"item\": \"\",\n        \"userid\": \"1\",\n        \"val\": \"20\",\n        \"cdate\": \"2018-08-08T13:38:38-05:00\",\n        \"udate\": \"2018-09-20T14:07:07-05:00\",\n        \"links\": {\n            \"owner\": \"https://:account.api-us1.com/api/3/configs/6/owner\"\n        },\n        \"id\": \"6\",\n        \"owner\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"config":{"type":"object","properties":{"keyname":{"type":"string","example":"pagination.users_index"},"section":{"type":"string","example":""},"item":{"type":"string","example":""},"userid":{"type":"string","example":"1"},"val":{"type":"string","example":"20"},"cdate":{"type":"string","example":"2018-08-08T13:38:38-05:00"},"udate":{"type":"string","example":"2018-09-20T14:07:07-05:00"},"links":{"type":"object","properties":{"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/configs/6/owner"}}},"id":{"type":"string","example":"6"},"owner":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for ConfigResult with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for ConfigResult with id 100"}}}}}}},"deprecated":false}},"/connection/chooseAccountAuth":{"post":{"summary":"Request authorization for a chosen ad account","description":"Internal: the second step of connecting a service that authorizes per ad account, such as Facebook Custom Audiences. After the user picks one of their ad accounts, asks Deep Data to complete the connection for it on behalf of the current user and answers with Deep Data's response, which carries the URL the app sends the main window to. Parameters are read from the query string or from a form-encoded body (application/x-www-form-urlencoded), which is what the app sends; a JSON body is not read. Legacy endpoint with no method guard: any HTTP method is answered the same way; POST is the documented verb and the one the app uses. Refused with 403 when the account has no Deep Data.","operationId":"create-connection-chosen-account-request","x-canonical-resource":"connections","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["service"],"properties":{"service":{"type":"string","description":"The external service","example":"facebook_audience"},"accountid":{"type":"string","description":"ID of the ad account the user chose, in the external service","example":"act_1234567890"},"externalid":{"type":"string","description":"ID of the user in the external service","example":"10223344556677"}}}}}},"responses":{"200":{"description":"Deep Data's answer, passed through. The app reads data.url.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"Where to send the main window once the ad account is authorized","example":"https://acme.activehosted.com/app/integrations?isConnected=true&service=facebook_audience"}}}}},"example":{"data":{"url":"https://acme.activehosted.com/app/integrations?isConnected=true&service=facebook_audience"}}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"403"},"detail":{"type":"string","description":"Always \"Upgrade your account to enable Deep Data\"","example":"Upgrade your account to enable Deep Data"}}}}}},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"422":{"description":"The service parameter is missing. Deep Data is not called.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"title":{"type":"string","description":"Always \"Unable to process your request.\"","example":"Unable to process your request."}}}}}},"example":{"errors":[{"title":"Unable to process your request."}]}}}},"500":{"description":"Deep Data could not be reached or refused the call. The body is {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always the same generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/connection/errorLog":{"get":{"summary":"List the sync errors of a connection","description":"Internal: the errors Deep Data recorded while syncing one connection, for the integration's error log in the app. When Deep Data has no error registration for the connection, which is normal for a custom API integration, the answer is an empty list rather than an error. Refused with 403 when the account has no Deep Data.","operationId":"list-connection-error-logs","x-canonical-resource":"connections","parameters":[{"name":"connection","in":"query","description":"Hosted ID of the connection. Missing is a 404.","required":true,"schema":{"type":"integer"}},{"name":"limit","in":"query","description":"Maximum number of error records to return; Deep Data's default when left out","required":false,"schema":{"type":"integer"}},{"name":"cursor","in":"query","description":"Passed to Deep Data as given","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"The connection's error records, as Deep Data returns them","content":{"application/json":{"schema":{"type":"object","properties":{"errorRecords":{"type":"array","description":"One entry per recorded error. Left out when Deep Data has none to report, and an empty array when it has no registration for the connection.","items":{"type":"object","description":"A Deep Data error record"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Number of error records for the connection","example":2},"per_page":{"type":"integer","description":"The page size used","example":25},"next_page":{"type":"string","description":"Only when a cursor was sent"},"previous_page":{"type":"string","description":"Only when a cursor was sent"}}}}},"example":{"errorRecords":[],"meta":{"total":0,"per_page":25}}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"403"},"detail":{"type":"string","description":"Always \"Upgrade your account to enable Deep Data\"","example":"Upgrade your account to enable Deep Data"}}}}}},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"404":{"description":"The connection parameter is missing ({\"error\": \"No connection ID provided\"}), or no connection has this ID ({\"message\": \"No Result found for Connection with id 9\"}).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"When the connection parameter is missing","example":"No connection ID provided"},"message":{"type":"string","description":"When no connection has this ID","example":"No Result found for Connection with id 9"}}},"example":{"error":"No connection ID provided"}}}},"405":{"description":"The method is not GET. The Allow header says GET.","headers":{"Allow":{"description":"Always GET","schema":{"type":"string","example":"GET"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always \"Method not allowed\"","example":"Method not allowed"}}}}}},"500":{"description":"Deep Data could not be reached or refused the call. The body is {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always the same generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/connection/events":{"get":{"summary":"List the sync events of a connection","description":"Internal: the webhook and sync events Deep Data recorded for one connection, newest first, 100 per page, for the Deep Data events support tool. Restricted to ActiveCampaign staff: outside local development the request must come from an allowed internal IP address with an active staff (MPMA) session, otherwise the answer is 403 with a plain-text body. Every query parameter is forwarded to Deep Data.","operationId":"list-connection-events","x-canonical-resource":"connections","parameters":[{"name":"connection","in":"query","description":"Hosted ID of the connection. Missing is a 404.","required":true,"schema":{"type":"integer"}},{"name":"page","in":"query","description":"Page number, from 1","required":false,"schema":{"type":"integer"}},{"name":"before","in":"query","description":"Only events recorded before this time","required":false,"schema":{"type":"string"}},{"name":"after","in":"query","description":"Only events recorded after this time","required":false,"schema":{"type":"string"}},{"name":"eventName","in":"query","description":"Only events with this name","required":false,"schema":{"type":"string"}},{"name":"action","in":"query","description":"Only events with this action","required":false,"schema":{"type":"string"}},{"name":"requestId","in":"query","description":"Only events of this request","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"One page of events, in Deep Data's paginated form","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"The events on this page","items":{"type":"object","description":"A Deep Data event record"}},"current_page":{"type":"integer","description":"This page's number","example":1},"per_page":{"type":"integer","description":"Always 100","example":100},"total":{"type":"integer","description":"Number of matching events","example":240},"last_page":{"type":"integer","description":"Number of the last page","example":3},"from":{"type":"integer","description":"Position of the first event on this page"},"to":{"type":"integer","description":"Position of the last event on this page"},"path":{"type":"string","description":"This endpoint's URL on the account, without page"},"first_page_url":{"type":"string","description":"URL of the first page"},"last_page_url":{"type":"string","description":"URL of the last page"},"next_page_url":{"type":"string","description":"URL of the next page; null on the last page"},"prev_page_url":{"type":"string","description":"URL of the previous page; null on the first page"}}}}}},"403":{"description":"The caller is not on the staff allowlist.","content":{"text/plain":{"schema":{"type":"string","example":"ACCESS NOT ENABLED."}}}},"404":{"description":"The connection parameter is missing ({\"error\": \"No connection ID provided\"}), or no connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"When the connection parameter is missing","example":"No connection ID provided"},"message":{"type":"string","description":"When no connection has this ID"}}}}}},"405":{"description":"The method is not GET. The Allow header says GET.","headers":{"Allow":{"description":"Always GET","schema":{"type":"string","example":"GET"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always \"Method not allowed\"","example":"Method not allowed"}}}}}},"500":{"description":"Deep Data could not be reached or refused the call. The body is {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always the same generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/connection/oauth":{"post":{"summary":"Request an OAuth URL for a new connection","description":"Internal: the first step of connecting an ecommerce or marketing service from the integrations page. Asks Deep Data to open a connection request for the service on behalf of the current user (with write permission for services Hosted can write to) and answers with Deep Data's response, which carries the provider's consent URL the app opens in a popup. Parameters are read from the query string or from a form-encoded body (application/x-www-form-urlencoded), which is what the app sends; a JSON body is not read. Legacy endpoint with no method guard: any HTTP method is answered the same way; POST is the documented verb and the one the app uses. Refused with 403 when the account has no Deep Data.","operationId":"create-connection-oauth-request","x-canonical-resource":"connections","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["service"],"properties":{"service":{"type":"string","description":"The external service","example":"shopify"},"externalid":{"type":"string","description":"ID of the store in the external service, such as a Shopify shop domain, when the info modal collected one","example":"toystore123.myshopify.com"}}}}}},"responses":{"200":{"description":"Deep Data's connection request, passed through. The app reads data.attributes.oauth_url.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","description":"Always \"connection-request\"","example":"connection-request"},"id":{"type":"string","description":"ID of the connection request in Deep Data"},"attributes":{"type":"object","properties":{"account":{"type":"string","description":"The account hostname","example":"acme.activehosted.com"},"service":{"type":"string","description":"The external service","example":"shopify"},"external_id":{"type":"string","description":"The externalid sent","example":"toystore123.myshopify.com"},"oauth_url":{"type":"string","description":"The provider's consent URL"}}}}}}}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"403"},"detail":{"type":"string","description":"Always \"Upgrade your account to enable Deep Data\"","example":"Upgrade your account to enable Deep Data"}}}}}},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"422":{"description":"The service parameter is missing. Deep Data is not called.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"title":{"type":"string","description":"Always \"Unable to process your request.\"","example":"Unable to process your request."}}}}}},"example":{"errors":[{"title":"Unable to process your request."}]}}}},"500":{"description":"Deep Data refused or could not be reached.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always \"Internal server error.\"","example":"Internal server error."}}},"example":{"error":"Internal server error."}}}}},"x-internal":true}},"/connection/old":{"get":{"summary":"Check for integrations from before Deep Data","description":"Internal: tells the integrations page whether the account still has an integration from before Deep Data for each service, so the connect modal can warn that connecting again replaces it. Only shopify and bigcommerce can have one; any other service named is always false. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses. Refused with 403 when the account has no Deep Data.","operationId":"retrieve-old-integrations","x-canonical-resource":"connections","parameters":[{"name":"service","in":"query","description":"Comma-separated services to check. Left out, shopify and bigcommerce are checked.","required":false,"schema":{"type":"string"},"example":"shopify,bigcommerce"}],"responses":{"200":{"description":"One key per service checked: true when the account has an integration of that service from before Deep Data","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"}},"example":{"shopify":true,"bigcommerce":false}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"403"},"detail":{"type":"string","description":"Always \"Upgrade your account to enable Deep Data\"","example":"Upgrade your account to enable Deep Data"}}}}}},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}}},"x-internal":true}},"/connection/{id}/accountUpdate":{"put":{"summary":"Point a connection at a renamed account","description":"Internal: used when an account's hostname changes. Tells Deep Data the new hostname for the Deep Data connection deepdataConnectionId, then answers with the Hosted connection {id} showing the new account; this call does not save the Hosted connection row itself. account must have exactly two dots (name.activehosted.com), be hosted.localdev, or contain \"staging\". Only PUT is accepted: any other method is a 405 with a plain-text body. Refused with 403 when the account has no Deep Data, before the method is checked.","operationId":"update-connection-account","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Hosted ID of the connection","required":true,"schema":{"type":"string","pattern":"^\\d+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["account","deepdataConnectionId"],"properties":{"account":{"type":"string","description":"The account's new hostname","example":"newname.activehosted.com"},"deepdataConnectionId":{"type":"string","description":"ID of the connection in Deep Data, which is not the Hosted connection ID","example":"4411"}}},"example":{"account":"newname.activehosted.com","deepdataConnectionId":"4411"}}}},"responses":{"200":{"description":"Deep Data accepted the new hostname","content":{"application/json":{"schema":{"type":"object","properties":{"connection":{"type":"object","description":"The connection, with account replaced by the new hostname. IDs come back as strings.","properties":{"id":{"type":"string","description":"ID of the connection","example":"9"},"service":{"type":"string","description":"The external service","example":"shopify"},"externalid":{"type":"string","description":"ID of the store in the external service","example":"toystore123.myshopify.com"},"name":{"type":"string","description":"Display name of the connection","example":"Toystore, Inc."},"account":{"type":"string","description":"The account hostname the connection now points at","example":"newname.activehosted.com"},"links":{"type":"object","description":"API paths of related resources","example":{"customers":"/api/3/connections/9/customers"}}}}}}}}},"400":{"description":"The body is not JSON (plain text \"Body not valid JSON.\"), or account or deepdataConnectionId is missing, or account is not in the expected format (JSON error).","content":{"text/plain":{"schema":{"type":"string","example":"Body not valid JSON."}},"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"One of \"Required field missing: [account]\", \"Required field missing: [deepdataConnectionId]\" or \"Bad format on account. Should be in the format: [reallycoolaccount.activehosted.com]\"","example":"Required field missing: [account]"}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Required field missing: [account]"}]}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"403"},"detail":{"type":"string","description":"Always \"Upgrade your account to enable Deep Data\"","example":"Upgrade your account to enable Deep Data"}}}}}},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the model and the ID","example":"No Result found for Connection with id 9"}}},"example":{"message":"No Result found for Connection with id 9"}}}},"405":{"description":"The method is not PUT.","content":{"text/plain":{"schema":{"type":"string","example":"Method not supported. Only PUT supported."}}}},"500":{"description":"Deep Data could not be reached or refused the call. The body is {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always the same generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/connection/{id}/test":{"get":{"summary":"Check a connection's credentials","description":"Internal: asks Deep Data whether the stored access token of connection {id} still works. Not a pure read: when Deep Data says the token is no longer valid, the connection is deleted, with its delete events, before the answer is sent. The integrations page calls this for every Square connection when it loads and ignores the answer.","operationId":"retrieve-connection-health","x-canonical-resource":"connections","parameters":[{"name":"id","in":"path","description":"Hosted ID of the connection","required":true,"schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Deep Data's verdict, passed through","content":{"application/json":{"schema":{"type":"object","properties":{"account":{"type":"object","description":"Deep Data's record of the account the connection belongs to"},"tokenValid":{"type":"boolean","description":"False when the token has been revoked; the connection has then been deleted","example":true}}}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"404"},"detail":{"type":"string","description":"Always \"Invalid connection ID\"","example":"Invalid connection ID"}}}}}},"example":{"errors":[{"status":"404","detail":"Invalid connection ID"}]}}}},"405":{"description":"The method is not GET. The Allow header says GET.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string","example":"405"},"detail":{"type":"string","description":"Empty","example":""}}}}}},"example":{"errors":[{"status":"405","detail":""}]}}},"headers":{"Allow":{"description":"Always GET","schema":{"type":"string","example":"GET"}}}},"500":{"description":"Deep Data could not be reached or refused the call. The body is {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always the same generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/connections":{"post":{"summary":"Create a connection","description":"Create a new connection resource.","operationId":"create-connection","x-canonical-resource":"connections","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"connection":{"properties":{"service":{"type":"string","description":"The name of the service."},"externalid":{"type":"string","description":"The id of the account in the external service."},"name":{"type":"string","description":"The name associated with the account in the external service. Often this will be a company name (e.g., 'My Toystore, Inc.')."},"logoUrl":{"type":"string","description":"The URL to a logo image for the external service."},"linkUrl":{"type":"string","description":"The URL to a page where the integration with the external service can be managed in the third-party's website."},"listId":{"type":"string","description":"The ID of list where new contacts from connection will be synced"},"connectionType":{"type":"string"},"disconnectDate":{"type":"string","format":"date-time","description":"Date and time of disconnect."},"lastSync":{"type":"string","format":"date-time","description":"Time the last sync finished."},"planTier":{"type":"string"},"status":{"type":"integer","enum":[0,1],"description":"1 connected, 0 error."},"syncStatus":{"type":"integer","enum":[0,1],"description":"1 running, 0 stopped."},"sync_start_time":{"type":"string","format":"date-time"}},"required":["service","externalid","name","logoUrl","linkUrl"],"type":"object"}}},"examples":{"JSON":{"value":{"connection":{"service":"fooCommerce","externalid":"toystore123","name":"Toystore, Inc.","logoUrl":"http://example.com/i/foo.png","linkUrl":"http://example.com/foo/","listId":"1"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"connection\": {\n    \"isInternal\": 0,\n    \"service\": \"fooCommerce\",\n    \"externalid\": \"toystore123\",\n    \"name\": \"Toystore, Inc.\",\n    \"logoUrl\": \"http://example.com/i/foo.png\",\n    \"linkUrl\": \"http://example.com/foo/\",\n\t\t\"listId\": \"1\",\n    \"cdate\": \"2017-02-02T14:56:05-06:00\",\n    \"udate\": \"2017-02-02T14:56:05-06:00\",\n    \"links\": {\n      \"customers\": \"https://:account.api-us1.com/api/3/connections/1/customers\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"connection":{"type":"object","properties":{"isInternal":{"type":"integer","example":0,"default":0},"service":{"type":"string","example":"fooCommerce"},"externalid":{"type":"string","example":"toystore123"},"name":{"type":"string","example":"Toystore, Inc."},"logoUrl":{"type":"string","example":"http://example.com/i/foo.png"},"linkUrl":{"type":"string","example":"http://example.com/foo/"},"listId":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-02-02T14:56:05-06:00"},"udate":{"type":"string","example":"2017-02-02T14:56:05-06:00"},"links":{"type":"object","properties":{"customers":{"type":"string","example":"https://:account.api-us1.com/api/3/connections/1/customers"}}},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"get":{"summary":"List all connections","description":"List all existing connection resources.","operationId":"list-all-connections","x-canonical-resource":"connections","parameters":[{"name":"filters[service]","in":"query","description":"Filter by the external service name.","schema":{"type":"string"}},{"name":"filters[externalid]","in":"query","description":"Filter by the external id associated with a connection.","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"connections\": [\n    {\n      \"service\": \"shopify\",\n      \"externalid\": \"foo.myshopify.com\",\n      \"name\": \"Foo, Inc.\",\n      \"isInternal\": \"1\",\n      \"status\": \"1\",\n      \"syncStatus\": \"0\",\n      \"lastSync\": \"2017-02-02T13:09:07-06:00\",\n      \"logoUrl\": \"\",\n      \"linkUrl\": \"\",\n      \"listId\": \"0\",\n      \"cdate\": \"2017-02-02T13:09:07-06:00\",\n      \"udate\": \"2017-02-02T13:09:12-06:00\",\n      \"links\": {\n        \"customers\": \"https://:account.api-us1.com/api/3/connections/1/customers\"\n      },\n      \"id\": \"1\"\n    },\n    {\n      \"service\": \"fooCommerce\",\n      \"externalid\": \"johndoe@example.com\",\n      \"name\": \"Acme, Inc.\",\n      \"isInternal\": \"0\",\n      \"status\": \"1\",\n      \"syncStatus\": \"0\",\n      \"lastSync\": null,\n      \"logoUrl\": \"http://example.com/i/foo.png\",\n      \"linkUrl\": \"http://example.com/foo/\",\n      \"listId\": \"1\",\n      \"cdate\": \"2017-02-02T14:56:05-06:00\",\n      \"udate\": \"2017-02-03T15:54:51-06:00\",\n      \"links\": {\n        \"customers\": \"https://:account.api-us1.com/api/3/connections/2/customers\"\n      },\n      \"id\": \"2\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"connections":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string","example":"shopify"},"externalid":{"type":"string","example":"foo.myshopify.com"},"name":{"type":"string","example":"Foo, Inc."},"isInternal":{"type":"string","example":"1"},"status":{"type":"string","example":"1"},"syncStatus":{"type":"string","example":"0"},"lastSync":{"type":"string","example":"2017-02-02T13:09:07-06:00"},"logoUrl":{"type":"string","example":""},"linkUrl":{"type":"string","example":""},"listId":{"type":"string","example":"0"},"cdate":{"type":"string","example":"2017-02-02T13:09:07-06:00"},"udate":{"type":"string","example":"2017-02-02T13:09:12-06:00"},"links":{"type":"object","properties":{"customers":{"type":"string","example":"https://:account.api-us1.com/api/3/connections/1/customers"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/connections/{id}":{"get":{"summary":"Retrieve a connection","description":"Retrieve an existing connection resource.","operationId":"get-connection","x-canonical-resource":"connections","parameters":[{"name":"id","in":"path","description":"The id of the connection to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"connection\": {\n    \"isInternal\": 0,\n    \"service\": \"fooCommerce\",\n    \"externalid\": \"toystore123\",\n    \"name\": \"Toystore, Inc.\",\n    \"logoUrl\": \"http://example.com/i/foo.png\",\n    \"linkUrl\": \"http://example.com/foo/\",\n    \"listId\": \"1\",  \n    \"cdate\": \"2017-02-02T14:56:05-06:00\",\n    \"udate\": \"2017-02-02T14:56:05-06:00\",\n    \"links\": {\n      \"customers\": \"https://:account.api-us1.com/api/3/connections/1/customers\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"connection":{"type":"object","properties":{"isInternal":{"type":"integer","example":0,"default":0},"service":{"type":"string","example":"fooCommerce"},"externalid":{"type":"string","example":"toystore123"},"name":{"type":"string","example":"Toystore, Inc."},"logoUrl":{"type":"string","example":"http://example.com/i/foo.png"},"linkUrl":{"type":"string","example":"http://example.com/foo/"},"listId":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-02-02T14:56:05-06:00"},"udate":{"type":"string","example":"2017-02-02T14:56:05-06:00"},"links":{"type":"object","properties":{"customers":{"type":"string","example":"https://:account.api-us1.com/api/3/connections/1/customers"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a connection","description":"Update an existing connection resource.","operationId":"update-connection","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The id of the connection to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"connection":{"properties":{"service":{"type":"string","description":"The name of the service."},"externalid":{"type":"string","description":"The id of the account in the external service."},"name":{"type":"string","description":"The name associated with the account in the external service."},"logoUrl":{"type":"string","description":"The URL to a logo image for the third-party service."},"linkUrl":{"type":"string","description":"The link to the third-party integrator's site."},"status":{"type":"integer","description":"The status of the connection (0 = error; 1 = connected)","format":"int32"},"syncStatus":{"type":"integer","description":"The status of a sync triggered on the connection (0 = sync stopped; 1 = sync running).","format":"int32"},"connectionType":{"type":"string"},"disconnectDate":{"type":"string","format":"date-time","description":"Date and time of disconnect."},"lastSync":{"type":"string","format":"date-time","description":"Time the last sync finished."},"listId":{"type":"string"},"planTier":{"type":"string"},"sync_start_time":{"type":"string","format":"date-time"}},"required":[],"type":"object"}}},"examples":{"JSON":{"value":{"connection":{"externalid":"johndoe@example.com","name":"Acme, Inc."}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"connection\": {\n    \"service\": \"fooCommerce\",\n    \"externalid\": \"johndoe@example.com\",\n    \"name\": \"Acme, Inc.\",\n    \"isInternal\": \"0\",\n    \"status\": \"1\",\n    \"syncStatus\": \"0\",\n    \"logoUrl\": \"http://foocorp.net/i/path3523.png\",\n    \"linkUrl\": \"http://example.com/\",\n    \"listId\": \"1\",\n    \"cdate\": \"2017-02-02T14:56:05-06:00\",\n    \"udate\": \"2017-02-03T15:54:51-06:00\",\n    \"links\": {\n      \"customers\": \"https://:account.api-us1.com/api/3/connections/2/customers\"\n    },\n    \"id\": \"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"connection":{"type":"object","properties":{"service":{"type":"string","example":"fooCommerce"},"externalid":{"type":"string","example":"johndoe@example.com"},"name":{"type":"string","example":"Acme, Inc."},"isInternal":{"type":"string","example":"0"},"status":{"type":"string","example":"1"},"syncStatus":{"type":"string","example":"0"},"logoUrl":{"type":"string","example":"http://foocorp.net/i/path3523.png"},"linkUrl":{"type":"string","example":"http://example.com/"},"listId":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-02-02T14:56:05-06:00"},"udate":{"type":"string","example":"2017-02-03T15:54:51-06:00"},"links":{"type":"object","properties":{"customers":{"type":"string","example":"https://:account.api-us1.com/api/3/connections/2/customers"}}},"id":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a connection","description":"Delete an existing connection resource.","operationId":"delete-connection","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The id of the connection to delete.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/contact/bulkSync":{"post":{"summary":"Bulk sync contacts","description":"Upserts up to 250 contacts in one request, matching each one on its email address: an existing contact with that email is updated, otherwise a contact is created. This is the v3 equivalent of looping over `POST /api/3/contact/sync`, and it is the endpoint to reach for when a v1 integration synced contacts one request at a time.\n\nThe work is done in the background. The response is a `202` carrying the id of the process that was created, and the contacts are written after the response is sent, so a contact read back immediately afterwards may not reflect the request yet.\n\nA request holding more than 250 contacts is rejected as a whole and no process is created. Rows are otherwise handled independently: a row that cannot be written (no `email`, a validation failure, a contact the caller cannot access) is logged and skipped without failing the rest of the batch, and the outcome of an individual row is **not** reported back anywhere in the API. Use `POST /api/3/contact/sync` per contact when a request needs to know whether each contact was written.\n\nRequires the `pg_subscriber_add` permission. Prefer POST /import/bulk_import for creating or updating many contacts: it reports each row's outcome through GET /import/info and can set list subscriptions and tags per contact.","operationId":"bulk-sync-contacts","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contacts"],"properties":{"contacts":{"type":"array","description":"The contacts to upsert, at most 250 per request.","items":{"type":"object","required":["email"],"properties":{"email":{"type":"string","description":"Email address the contact is matched on. A row without an email is skipped.","example":"johndoe@example.com"},"first_name":{"type":"string","example":"John","description":"The contact's first name."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name."},"phone":{"type":"string","example":"7223224241","description":"The contact's phone number."},"fields":{"type":"array","description":"Custom field values for the contact, given as field id and value pairs.","items":{"type":"object","properties":{"field":{"type":"string","example":"1","description":"Id of the custom field."},"value":{"type":"string","example":"Albany","description":"The value to store."}},"additionalProperties":false}},"orgid":{"type":"integer","description":"ID of the account to associate the contact with."},"orgname":{"type":"string","description":"Name of an account to find or create; the contact is added to it."},"whatsapp_id":{"type":"string","maxLength":250},"whatsapp_username":{"type":"string","maxLength":250},"open_tracking_optout":{"type":["integer","string"],"enum":[0,1,"0","1"],"description":"0 or 1: the contact's open-tracking opt-out. Only written while the contact pixel tracking opt-out feature is on for the account; ignored otherwise."}}}},"urlParams":{"type":"object","description":"Query-string parameters are merged into this object by the handler.","properties":{"service":{"type":"string","description":"salesforce records each newly created contact as sourced from Salesforce; any other value has no effect."}}}}},"examples":{"Request":{"value":{"contacts":[{"email":"johndoe@example.com","first_name":"John","last_name":"Doe","phone":"7223224241","fields":[{"field":"1","value":"Albany"}]},{"email":"janedoe@example.com","first_name":"Jane","last_name":"Doe"}]}}}}}},"responses":{"202":{"description":"Accepted. The contacts are written by the background process identified by `process_id`.","content":{"application/json":{"examples":{"Result":{"value":{"contactBulkSync":{"process_id":"1234"}}}},"schema":{"type":"object","properties":{"contactBulkSync":{"type":"object","description":"The background process created for the request.","properties":{"process_id":{"type":"string","description":"Id of the background process that writes the contacts, as a numeric string. The API has no read for it. An identical request from the same user can return the id of an earlier unfinished process instead of creating a new one.","example":"1234"}}}}}}}},"403":{"description":"The caller lacks the `pg_subscriber_add` permission."},"422":{"description":"More than 250 contacts were sent. No process is created and no contact is written. The body is {\"errors\": \"Bulk operation failed. Request must contain no more than 250 resources.\"}, with errors as a single string."}}}},"/contact/bulk_update":{"post":{"summary":"Bulk edit contacts","description":"Starts a background job that applies one set of changes to many contacts: add or remove tags, lists and automations, add contacts to automation blocks, set field values, or queue contact enrichment. It serves the bulk edit screen in the app.\n\nThe body names the changes and which contacts they apply to. The contacts are either the ones in `contactIds`, or every contact that matches the filters (`listid`, `tagid`, `status`, `search`, `segmentid` and the others), which mean the same as the GET /contacts filters of the same name. The request body description says which filters apply together.\n\nThe request is checked first, the same way as POST /contact/bulk_update/validation. If the checks pass and at least one contact would change, a job is created and the call returns 200 straight away. `numChanged` is how many contacts the job covers. The changes are made later, in batches. The response carries no job id; the job appears in GET /contacts/bulkEdit with its status and progress. A running job can be stopped by ActiveCampaign; it then shows as cancelled in GET /contacts/bulkEdit, and changes it already made stay in place.\n\nRequests from the web app must say which contacts they mean in the `scope` query parameter. Requests made with an API key are not checked.\n\nSome options depend on account features: `enrichContacts` needs contact data enrichment, and the account in `fieldValueUpdates` is ignored when the Accounts feature is off.","operationId":"bulk-update-contacts","parameters":[{"name":"scope","in":"query","description":"Which contacts a web app request means: `ids` (the contacts in `contactIds` or `ids`), `filter` (the contacts matching the filters, which must include at least one usable filter) or `all` (every contact; no `contactIds`, no `ids` and no filters allowed). While enforcement is on, a web app request without a matching scope is refused with 400 and nothing is changed. API key requests may leave it out.","required":false,"schema":{"type":"string","enum":["ids","filter","all"]}}],"requestBody":{"description":"The changes to make and the contacts to make them on. At least one change is required. An id named in both an add and a remove list (a tag in `toTagIds` and `fromTagIds`, for example) is dropped from both.\n\nWhich contacts: with `segmentid`, the contacts are the members of the segment, and the other filters are not applied. Without `segmentid`, the selection (whether from `contactIds` or from the filters) is limited to contacts on at least one list the user may access, plus contacts on no list. With `contactIds`, `formid`, `seriesid`, `finishedAutomation`, `waitid` and `customer_account` still narrow the selection. With no filter at all it covers all of those contacts.","required":true,"content":{"application/json":{"schema":{"properties":{"toTagIds":{"description":"Ids of contact tags to add. Unknown ids are skipped with a warning.","type":"array","items":{"type":"integer"}},"fromTagIds":{"description":"Ids of contact tags to remove. Unknown ids are skipped with a warning.","type":"array","items":{"type":"integer"}},"toTags":{"description":"Names of tags to add. A tag that does not exist yet is created, which needs permission to manage tags. It is created while the request is checked, so it exists even if a later check then fails the request.","type":"array","items":{"type":"string"}},"fromTags":{"description":"Names of tags to remove. Names that match no tag are ignored.","type":"array","items":{"type":"string"}},"toListIds":{"description":"Ids of lists to subscribe the contacts to. Unknown ids are skipped with a warning. A list the user may not access is reported as a warning too, but the contacts are still subscribed to it.","type":"array","items":{"type":"integer"}},"fromListIds":{"description":"Ids of lists to unsubscribe the contacts from. Unknown ids are skipped with a warning. A list the user may not access is reported as a warning too, but the contacts are still unsubscribed from it.","type":"array","items":{"type":"integer"}},"toAutomationIds":{"description":"Ids of active automations to add the contacts to. Unknown or inactive automations are skipped with a warning.","type":"array","items":{"type":"integer"}},"fromAutomationIds":{"description":"Ids of automations to remove the contacts from. Only contacts currently in the automation are affected.","type":"array","items":{"type":"integer"}},"toAutomationBlockIds":{"description":"Ids of automation blocks to add the contacts to, starting the automation at that block.","type":"array","items":{"type":"integer"}},"replayAction":{"description":"Enter the contacts at the blocks in `toAutomationBlockIds` as a replay of that step. Needs at least one block id, blocks that support replay, and automations that are active and not holding new entries.","type":"boolean"},"fieldValueUpdates":{"description":"Values to set, keyed by custom field id. Also accepts `phone` and `userid` (the contact owner), and `customer_acct_name` (or `orgname`) with an object `{\"id\": 12, \"name\": \"Example Inc\"}` to set the account. The name decides: a name other than the contact's current account name is matched to an account by name, and created if none exists, whatever the id, so it must match the account's name exactly. Id 0 with an empty name, or with the contact's current account name, removes the contact's account. The account is ignored when the Accounts feature is off. Unknown field ids are skipped with a warning.","type":"object","additionalProperties":true},"enrichContacts":{"description":"Queue contact data enrichment for every contact covered. Needs contact data enrichment on the account and permission to edit contacts.","type":"boolean"},"contactIds":{"description":"Ids of the contacts to edit. When set, `listid`, `tagid`, `status`, `search`, `segmentid` and `segment_run_id` are ignored, but a request that sends both `q` and `search` is still refused.","type":"array","items":{"oneOf":[{"type":"integer"},{"type":"string"}]}},"ids":{"description":"Another name for `contactIds`, with the same values and meaning. Send the ids in one or the other, not both. An empty list counts as not sent.","type":"array","items":{"oneOf":[{"type":"integer"},{"type":"string"}]}},"listid":{"description":"Only contacts on this list. -1 means contacts on any list and -2 contacts on no list; 0, the default, does not filter.","type":"integer"},"tagid":{"description":"Only contacts with this tag, or with any of a list of tags. -1 means contacts with any tag and -2 contacts with no tags; 0, the default, does not filter.","oneOf":[{"type":"integer"},{"type":"array","items":{"type":"integer"}}]},"status":{"description":"Only contacts with this list status, as in GET /contacts. -1, the default, means any status.","type":"integer"},"formid":{"description":"Only contacts that came in through this form.","type":"integer"},"seriesid":{"description":"Only contacts in this automation.","type":"integer"},"finishedAutomation":{"description":"With `seriesid`: 1 for contacts that finished the automation, 0 for contacts still in it.","type":"integer"},"waitid":{"description":"Only contacts waiting in this automation block.","type":["integer","null"]},"customer_account":{"description":"Only contacts that belong to this account, by account id.","type":["integer","null"]},"search":{"description":"Only contacts matching this search, as in GET /contacts. Not allowed together with `segmentid`.","type":"string"},"q":{"description":"Older name for `search`. Send one or the other, not both.","type":"string"},"segmentid":{"description":"Only contacts in this segment. The segment is run when the request is checked.","oneOf":[{"type":"integer"},{"type":"string"}]},"segment_run_id":{"description":"A segment run to reuse, as returned in `runId` by POST /contact/bulk_update/validation. Needs `segmentid`.","type":"string"}},"type":"object"},"example":{"contactIds":[1,2,3],"toTags":["VIP"],"fromListIds":[4]}}}},"responses":{"200":{"description":"The job was created. The edits run in the background.","content":{"application/json":{"schema":{"properties":{"numChanged":{"description":"Number of contacts the job covers. It often arrives as a numeric string, such as \"3\".","type":["integer","string"]},"meta":{"description":"The outcome of the request.","properties":{"success":{"description":"Always true here.","type":"boolean"},"warnings":{"description":"Messages about parts of the request that were skipped, such as unknown ids. Present only when there are any.","type":"array","items":{"type":"string"}}},"type":"object"}},"type":"object"},"example":{"numChanged":"3","meta":{"success":true}}}}},"400":{"description":"No job was created and no contact was changed. Either the request failed a check, and `meta.errors` says which, or there was nothing to change (no contact matched, or every contact is already in the requested state), and `meta.errors` is absent. Checks that fail include: a missing or unmatched `scope` from the web app; no change requested; `q` and `search` both set; contact ids in both `contactIds` and `ids`, or not as a list; `search` with `segmentid`; `segment_run_id` without `segmentid`; a v2 segment id the segment service does not know, or a segment that could not be run; new tag names without permission to create tags; `enrichContacts` without the feature or the permission; an invalid `replayAction`; and, when nothing else would change, tags or automations to remove that no covered contact has. A numeric `segmentid` that matches no segment is not refused with 400: it currently fails with a server error. Tags named in `toTags` are created before some of these checks run, so a refused request can still leave new tags behind. Contact ids that are not a list, or that are sent under both names, are refused before any tag is created.","content":{"application/json":{"schema":{"properties":{"numChanged":{"description":"Number of contacts that matched, often as a numeric string. 0 when the request was refused before counting.","type":["integer","string"]},"meta":{"description":"The outcome of the request. `errors` is absent when there was nothing to change.","properties":{"success":{"description":"Always false here.","type":"boolean"},"errors":{"description":"Why the request was refused.","type":"array","items":{"type":"string"}},"warnings":{"description":"Messages about parts of the request that would have been skipped.","type":"array","items":{"type":"string"}}},"type":"object"}},"type":"object"},"example":{"numChanged":"3","meta":{"success":false,"errors":["You must provide at least one setting to update for the contacts."]}}}}},"422":{"description":"The request passed its checks, but the job could not be created. No contact was changed, though new tags named in `toTags` may have been created. The call can be retried.","content":{"application/json":{"schema":{"properties":{"numChanged":{"description":"Number of contacts that matched, often as a numeric string.","type":["integer","string"]},"meta":{"description":"The outcome of the request.","properties":{"success":{"description":"Always false here.","type":"boolean"},"errors":{"description":"The failure message.","type":"array","items":{"type":"string"}},"warnings":{"description":"Messages about parts of the request that would have been skipped.","type":"array","items":{"type":"string"}}},"type":"object"}},"type":"object"},"example":{"numChanged":"3","meta":{"success":false,"errors":["Bulk update for contacts failed to run because an error occurred. Please try again."]}}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/contact/bulk_update/validation":{"post":{"summary":"Check a contact bulk edit before running it","description":"Checks a bulk edit the same way POST /contact/bulk_update does, and reports how many contacts it would touch. It does not start the edit. The app calls it before a bulk edit, to show the count and any problems.\n\nIt is not read-only: tags named in `toTags` that do not exist yet are created during the check (see `toTags`).\n\nA request from a web app session must say which contacts it means in the `scope` query parameter, when the account enforces it. Requests authenticated with an API key or a service token are not checked.\n\nThe answer is 200 when there are no errors and 422 when there is at least one. Warnings alone do not fail the request. Ids that do not exist are dropped and reported as warnings, not errors.","operationId":"validate-contact-bulk-edit","parameters":[{"name":"scope","in":"query","description":"Which contacts a web app request means: `ids` (the contacts in `contactIds` or `ids`, which must not be empty), `filter` (the contacts matching the filters, at least one of which must actually narrow the selection), or `all` (every contact; the body must then carry no ids and no filters). A missing or mismatched scope fails with `errors.scope` when the account enforces it. Ignored for API key and service requests.","schema":{"type":"string","enum":["ids","filter","all"]}}],"requestBody":{"description":"The changes to make and the contacts to make them on. At least one change is required. An id named in both an add and a remove list (a tag in `toTagIds` and `fromTagIds`, for example) is dropped from both.\n\nWhich contacts: with `segmentid`, the contacts are the members of the segment, and the other filters are not applied. Without `segmentid`, the selection (whether from `contactIds` or from the filters) is limited to contacts on at least one list the user may access, plus contacts on no list. With `contactIds`, `formid`, `seriesid`, `finishedAutomation`, `waitid` and `customer_account` still narrow the selection. With no filter at all it covers all of those contacts.","required":true,"content":{"application/json":{"schema":{"properties":{"toTagIds":{"description":"Ids of contact tags to add. Unknown ids are skipped with a warning.","type":"array","items":{"type":"integer"}},"fromTagIds":{"description":"Ids of contact tags to remove. Unknown ids are skipped with a warning.","type":"array","items":{"type":"integer"}},"toTags":{"description":"Names of tags to add. A tag that does not exist yet is created, which needs permission to manage tags. It is created while the request is checked, so it exists even if a later check then fails the request.","type":"array","items":{"type":"string"}},"fromTags":{"description":"Names of tags to remove. Names that match no tag are ignored.","type":"array","items":{"type":"string"}},"toListIds":{"description":"Ids of lists to subscribe the contacts to. Unknown ids, and lists the user may not access, are reported as warnings.","type":"array","items":{"type":"integer"}},"fromListIds":{"description":"Ids of lists to unsubscribe the contacts from. Unknown ids, and lists the user may not access, are reported as warnings.","type":"array","items":{"type":"integer"}},"toAutomationIds":{"description":"Ids of active automations to add the contacts to. Unknown or inactive automations are skipped with a warning.","type":"array","items":{"type":"integer"}},"fromAutomationIds":{"description":"Ids of automations to remove the contacts from. Only contacts currently in the automation are affected.","type":"array","items":{"type":"integer"}},"toAutomationBlockIds":{"description":"Ids of automation blocks to add the contacts to, starting the automation at that block.","type":"array","items":{"type":"integer"}},"replayAction":{"description":"Enter the contacts at the blocks in `toAutomationBlockIds` as a replay of that step. Needs at least one block id, blocks that support replay, and automations that are active and not holding new entries.","type":"boolean"},"fieldValueUpdates":{"description":"Values to set, keyed by custom field id. Also accepts `phone` and `userid` (the contact owner), and `customer_acct_name` (or `orgname`) with an object `{\"id\": 12, \"name\": \"Example Inc\"}` to set the account, only when the account uses Accounts. The name decides which account is linked, so it must match the account's name: a name different from the contact's current one is matched to an account by name, whatever the id, and a new account is created if none matches. Sending id 0 with an empty name, or with the contact's current account name, removes the contact's account. Unknown field ids are skipped with a warning.","type":"object","additionalProperties":true},"enrichContacts":{"description":"Queue contact data enrichment for every contact covered. Needs contact data enrichment on the account and permission to edit contacts.","type":"boolean"},"contactIds":{"description":"Ids of the contacts to edit. When set, the list, tag, status, search and segment filters are ignored.","type":"array","items":{"oneOf":[{"type":"integer"},{"type":"string"}]}},"ids":{"description":"Another name for `contactIds`, with the same values and meaning. Send the ids in one or the other, not both. An empty list counts as not sent.","type":"array","items":{"oneOf":[{"type":"integer"},{"type":"string"}]}},"listid":{"description":"Only contacts on this list. -1 means contacts on any list and -2 contacts on no list; 0, the default, does not filter.","type":"integer"},"tagid":{"description":"Only contacts with this tag, or with any of a list of tags. -1 means contacts with any tag and -2 contacts with no tags; 0, the default, does not filter.","oneOf":[{"type":"integer"},{"type":"array","items":{"type":"integer"}}]},"status":{"description":"Only contacts with this list status, as in GET /contacts. -1, the default, means any status.","type":"integer"},"formid":{"description":"Only contacts that came in through this form.","type":"integer"},"seriesid":{"description":"Only contacts in this automation.","type":"integer"},"finishedAutomation":{"description":"With `seriesid`: 1 for contacts that finished the automation, 0 for contacts still in it.","type":"integer"},"waitid":{"description":"Only contacts waiting in this automation block.","type":["integer","null"]},"customer_account":{"description":"Only contacts that belong to this account, by account id.","type":["integer","null"]},"search":{"description":"Only contacts matching this search, as in GET /contacts. Not allowed together with `segmentid`.","type":"string"},"q":{"description":"Older name for `search`. Send one or the other, not both.","type":"string"},"segmentid":{"description":"Only contacts in this segment. The segment is run when the request is checked.","oneOf":[{"type":"integer"},{"type":"string"}]},"segment_run_id":{"description":"A segment run to reuse, as returned in `runId` by POST /contact/bulk_update/validation. Needs `segmentid`.","type":"string"}},"type":"object"},"example":{"contactIds":[1,2,3],"toTags":["VIP"],"fromListIds":[4]}}}},"responses":{"200":{"description":"The edit passed every check. `errors` is an empty array.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always empty on 200.","type":"array","items":{"type":"string"},"maxItems":0},"warnings":{"description":"Messages about ids that were dropped, keyed by the body field they came from (`toTagIds`, `toListIds`, `fieldValueUpdates`, ...). An empty array when there are none.","oneOf":[{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"array","items":{"type":"string"},"maxItems":0}]},"numChanged":{"description":"Number of contacts the edit selects. For a segment it is the segment size. A filter-based count may come back as a numeric string.","type":["integer","string"]},"runId":{"description":"Only with `segmentid`: the segment run the count came from. Send it back as `segment_run_id` to edit the same contacts.","type":"string"},"isReady":{"description":"Only with `segmentid`: false while the segment run is still being built, in which case `numChanged` may still grow.","type":"boolean"}},"type":"object"},"example":{"errors":[],"warnings":{"toListIds":["The following list(s) you tried to add contacts to do not exist: 99"]},"numChanged":"3"}}}},"422":{"description":"The edit failed at least one check. The body has the same fields as the 200 response, with `errors` filled in.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Error messages keyed by what failed:\n\n- `scope`: the `scope` query parameter is missing or does not match the body. Nothing else is checked and `numChanged` is 0.\n- `general`: no edit was given; a search term was sent in both `q` and `search`; contact ids were sent in both `contactIds` and `ids`, or as something other than a list; `segmentid` was combined with a search term; `segment_run_id` was sent without `segmentid`; or `segmentid` is a newer string segment id the segment service does not know, or the segment could not be run. An unknown numeric `segmentid` is not answered with 422: it currently fails with a server error.\n- `toTags`: a tag would have to be created and the user may not create tags.\n- `enrichContacts`: enrichment is off for the account, or the user may not edit contacts.\n- `replayAction`: replay was asked for without `toAutomationBlockIds`, for a step that does not exist or cannot be replayed, or in a paused automation.\n- `fromTagIds` / `fromAutomationIds`: the edit would change nothing, because no selected contact has the tag or is in the automation.\n\nA scope refusal, a search sent in both `q` and `search`, contact ids that are not a list or are sent under both names, and a segment combined with a search are refused before any tag is created.","type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"warnings":{"description":"As on 200.","oneOf":[{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"array","items":{"type":"string"},"maxItems":0}]},"numChanged":{"description":"As on 200. It is 0 when the request was refused before the contacts were counted.","type":["integer","string"]},"runId":{"description":"As on 200: present for a segment edit that got as far as running the segment.","type":"string"},"isReady":{"description":"As on 200: present for a segment edit that got as far as running the segment.","type":"boolean"}},"type":"object"},"example":{"errors":{"scope":["Scope \"ids\" requires a non-empty contactIds list."]},"warnings":[],"numChanged":0}}}}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/contact/clearCacheCounts":{"get":{"summary":"Clear the cached contact counts","description":"Deletes the account's two cached contact counts from the caches of the server that answers. One of them is the count used for the contact limit, and the next read of it counts the contacts again from the database.\n\nHosted cron servers and web servers use different memcached servers, so a count cleared on a cron server stays stale on the web servers. When a cron job changes contacts (the archive contact automation action and the list cleanup process, for example), it calls this operation on the account's web URL with the account's API key, so the app shows fresh counts.\n\nThe script does not check the method, so every method does the same thing. The cron jobs use GET. It reads no parameters and no body.\n\nInternal: called by Hosted cron jobs, not by the app.","operationId":"clear-the-cached-contact-counts","x-canonical-resource":"contact","x-side-effects":true,"x-internal":true,"responses":{"200":{"description":"The counts were cleared. The body is empty."}},"deprecated":false}},"/contact/deals_secondary_contact_status":{"get":{"summary":"Check whether a contact's deals have secondary contacts","description":"Looks at the deals where the contact is the primary contact. Returns allDealsHaveSecondaryContact: true when at least one of those deals has at least one secondary contact. Despite the name, one such deal is enough: the other deals are not checked. Returns false when the contact is the primary contact on no deal, or when none of its deals has a secondary contact. A contact id that does not exist returns false.\n\nOnly GET is answered; any other method gets 405 with an empty body and an Allow: GET header.\n\nInternal: the app calls it before it deletes a contact that has deals.","operationId":"check-whether-a-contacts-deals-have-secondary-contacts","x-canonical-resource":"contact","x-internal":true,"parameters":[{"name":"contactId","in":"query","required":true,"description":"ID of the contact. The name is in camel case, with a capital I.","schema":{"type":"integer"},"example":110}],"responses":{"200":{"description":"Whether any deal of the contact has a secondary contact.","content":{"application/json":{"schema":{"type":"object","properties":{"allDealsHaveSecondaryContact":{"type":"boolean","description":"true when at least one deal where the contact is the primary contact has at least one secondary contact."}}},"examples":{"Result":{"value":{"allDealsHaveSecondaryContact":false}}}}}},"405":{"description":"The request used a method other than GET. The body is empty and the Allow header names GET."},"422":{"description":"`contactId` is missing, empty or 0. Body: errors, a list with one item carrying status (a string) and detail. detail is \"Missing Contact Id\", translated into the user's language.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string","description":"What is wrong."}}}}}},"examples":{"Missing contact id":{"value":{"errors":[{"status":"422","detail":"Missing Contact Id"}]}}}}}}},"deprecated":false}},"/contact/enrichment/usage":{"get":{"summary":"Retrieve the account's AI allowance for contact enrichment","description":"Shows the account's monthly AI allowance and how much of it is used, so a caller can tell before enriching whether POST /contact/{id}/enrich will be declined. Contact enrichment shares this allowance with the other AI features. `limit` and `usage` are in the allowance's own units, AI credits or activities, not in enrichments. On the current consumption path one enrichment costs 1 AI credit, or 30 activities; on the older path it counts as one unit.","operationId":"retrieve-contact-enrichment-usage","responses":{"200":{"description":"The allowance and its use","content":{"application/json":{"schema":{"properties":{"limit":{"description":"The monthly allowance. On the current consumption path, 0 when the account has no AI usage entitlement.","type":"integer"},"usage":{"description":"How much of the allowance is used this month. It may come back with two decimals, such as 42.00 or 3.50. 0 when the use could not be read.","type":"number"},"over_limit":{"description":"True when POST /contact/{id}/enrich would be declined for the allowance. Use this rather than comparing `usage` with `limit`, as the two can disagree: on most accounts an allowance of 0 is not enforced and reads false, and an account with no AI usage entitlement reads true.","type":"boolean"},"remaining_enrichments":{"description":"How many more contacts can be enriched this month before POST /contact/{id}/enrich is declined: the allowance that is left divided by the cost of one enrichment, rounded down. 0 once the allowance is used up. Null when the allowance is not enforced, so there is no cap to compare a batch against.","type":["integer","null"]},"refresh_date":{"description":"When the allowance next resets, in UTC. Null when it is not known.","type":["string","null"],"format":"date-time"}},"type":"object"},"example":{"limit":1000,"usage":42.25,"over_limit":false,"remaining_enrichments":957,"refresh_date":"2026-11-01T00:00:00Z"}}}},"403":{"description":"Contact data enrichment is not turned on for the account (`declined_flag`), or the user may not edit contacts (`permission_denied`).","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrichmentError"}}},"type":"object"},"example":{"errors":[{"title":"You do not have permission to edit contacts.","code":"permission_denied"}]}}}}},"x-canonical-resource":"agent_consumption","x-internal":true}},"/contact/export":{"post":{"summary":"Start a contact export","description":"Queues a background job that writes the matching contacts to a CSV file. The response comes back as soon as the job is queued, before the file exists.\n\nThe body holds one object, `export`, with the filters and column options. All of them are optional, and an empty body exports every contact. The body can be JSON or form encoded (`export[listid]=5`).\n\nThe job creates an export record named after `exportName`, or, when that is absent or null, after the time it starts (for example 20261020_141500). The exports page lists it through GET /exports, and it expires after one week. The job fills the file in batches and updates its progress as it goes. When it finishes, it sets the user's export.new_since_last_visit setting to 1, so the app shows a dot next to Exports.\n\nOnly POST is answered; any other method gets 405 with an empty body and an Allow: POST header.\n\nInternal: the contacts page in the app calls it when the user exports contacts.","operationId":"start-a-contact-export","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactExportRequest"},"example":{"export":{"listid":5,"status":1,"includeScores":false,"exportName":"Active on list 5"}}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ContactExportRequest"}}}},"responses":{"200":{"description":"The export job was queued. The body is always the same.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}}},"example":{"success":true}}}},"403":{"description":"The user cannot export contacts, or `listid` names a list the user cannot see. Body: errors, a list with one item carrying status (a number), title and detail. detail is \"You do not have permission to export contacts.\" or \"You do not have permissions to edit this list\", translated into the user's language.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptHttpErrors"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to export contacts."}]}}}},"405":{"description":"The request used a method other than POST. The body is empty and the Allow header names POST."},"422":{"description":"A value in `export` is not valid: an id that is not a whole number (for `listid`, only for a user in the admin group; for others it gets the 403), a segment id that is neither a whole number nor a UUID, a list status outside -1 to 3, or an export name with HTML tags. Body: errors, a list with one item, in the same shape as the 403. detail names the value, for example \"List id aaa is not a valid integer\" or \"Invalid export name\".","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptHttpErrors"},"example":{"errors":[{"status":422,"title":"Invalid Input Parameter","detail":"List id aaa is not a valid integer"}]}}}}},"deprecated":false}},"/contact/hard_delete":{"delete":{"summary":"Delete a contact and transfer or delete its deals","description":"Deletes one contact, the same way the app deletes contacts elsewhere. The contact is marked deleted and its email is replaced with an anonymous address in related records. Its list memberships, tags, tasks, scores, automation queue entries and account links are removed, and the contact row moves to the contact archive. Open app pages are told the contact is gone. Once the contact is found, and before the delete is tried, a contact deleted event goes to the account's activity log when activity logs are on, so it is also recorded when the call then fails.\n\nWhen the contact is the primary contact on any deal, the body must say what happens to those deals. `newDealPrimaryContactId` makes another contact the primary contact on them. `deleteDeals` deletes them. When both are sent, the deals are transferred. This covers the deals the caller can see, up to 100; other deals get the normal handling for a deleted contact. When the account does not use deals, or the user cannot see deals, this step is skipped: the contact is deleted and its deals get that normal handling. The deals are changed before the delete limit is checked.\n\nFor a user who sees only some lists, only the contact's memberships on those lists are removed, along with its scores, tasks, automation queue entries and account links. The contact itself is deleted only when no list membership is left. The response is the same either way.\n\nThe body is JSON. Only DELETE is answered; any other method gets 405 with an empty body and an Allow: DELETE header.\n\nInternal: a delete-contact dialog in the shared deals components calls it.","operationId":"delete-a-contact-and-its-deals","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contactId"],"properties":{"contactId":{"type":"integer","description":"ID of the contact to delete."},"newDealPrimaryContactId":{"type":"integer","description":"ID of the contact that becomes the primary contact on the deleted contact's deals. 0, the default, transfers nothing."},"deleteDeals":{"type":"boolean","description":"Delete the contact's deals. Any value PHP treats as true counts, including the string \"false\". Defaults to false."}}},"example":{"contactId":110,"newDealPrimaryContactId":0,"deleteDeals":true}}}},"responses":{"200":{"description":"The contact was deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"integer","const":1},"message":{"type":"string","description":"\"Contact(s) successfully deleted.\", translated into the user's language."}}},"example":{"success":1,"message":"Contact(s) successfully deleted."}}}},"403":{"description":"The user cannot delete contacts, or the contact has deals, `deleteDeals` is sent without `newDealPrimaryContactId`, and the user cannot delete deals. Body: errors, a list with one item carrying status (a string) and detail, translated into the user's language.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptKernelErrors"},"example":{"errors":[{"status":"403","detail":"Forbidden. You don't have permission to delete contacts"}]}}}},"404":{"description":"No contact has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptNotFound"},"example":{"message":"No Result found for Contact with id 110. Please change your selection and try again."}}}},"405":{"description":"The request used a method other than DELETE. The body is empty and the Allow header names DELETE."},"422":{"description":"The contact was not deleted. When `contactId` is missing or 0, the body is JSON: errors, a list with one item carrying status (a string) and detail \"Missing Contact Id\". Otherwise the body is a plain message: the contact has deals and the body says neither to transfer nor to delete them, the deals could not be transferred or deleted, or the account has reached its contact delete limit for the billing period. The limit is checked after the deals are changed, so a limit 422 can come after deals were already transferred or deleted. Messages are translated into the user's language, except the limit message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptKernelErrors"},"example":{"errors":[{"status":"422","detail":"Missing Contact Id"}]}},"text/html":{"schema":{"type":"string"},"example":"Contact could not be deleted, you must either transfer or delete their deals prior to deleting."}}}},"deprecated":false}},"/contact/has_deals":{"get":{"summary":"Check whether a contact is the primary contact on a deal","description":"Returns hasDeals: true when the contact is the primary contact on at least one deal, and false when it is not. Deals where the contact is only a secondary contact do not count. A contact id that does not exist returns false.\n\nOnly GET is answered; any other method gets 200 with an empty body and an Allow: GET header.\n\nInternal: the app calls it before it deletes a contact, to decide whether to offer to delete the contact's deals too.","operationId":"check-whether-a-contact-has-deals","x-canonical-resource":"contact","x-internal":true,"parameters":[{"name":"contactid","in":"query","required":true,"description":"ID of the contact. The name is all lower case.","schema":{"type":"integer"},"example":110}],"responses":{"200":{"description":"Whether the contact is the primary contact on any deal.","content":{"application/json":{"schema":{"type":"object","properties":{"hasDeals":{"type":"boolean","description":"true when the contact is the primary contact on at least one deal."}}},"examples":{"Result":{"value":{"hasDeals":true}}}}}},"422":{"description":"`contactid` is missing, empty or 0. Body: errors, a list with one item carrying status (a string) and detail. detail is \"Missing Contact Id\", translated into the user's language.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string","description":"What is wrong."}}}}}},"examples":{"Missing contact id":{"value":{"errors":[{"status":"422","detail":"Missing Contact Id"}]}}}}}}},"deprecated":false}},"/contact/merge":{"post":{"summary":"Merge two contacts","description":"Merges one contact into another and deletes the contact that was merged. The destination contact survives and keeps its id; the source contact's lists, tags, automations, deals, notes and activity are moved onto the destination, and the source is then removed.\n\nThe merge runs synchronously, so the response means the contacts have already been merged. It cannot be undone.\n\nWhere the two contacts hold conflicting information, `resolutionFieldId` and `resolutionAutomationId` name which of the two contacts wins: field values are taken from the contact named by `resolutionFieldId`, and automation membership from the contact named by `resolutionAutomationId`.\n\nRequires the `pg_subscriber_merge` permission.","operationId":"merge-contacts","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source","destination"],"properties":{"source":{"type":"integer","format":"int32","description":"Id of the contact to merge in. This contact is deleted once the merge completes.","example":123},"destination":{"type":"integer","format":"int32","description":"Id of the contact that survives the merge.","example":456},"resolutionFieldId":{"type":"integer","format":"int32","description":"Id of the contact whose field values win where both contacts hold a value. Must be the `source` or the `destination`.","example":456},"resolutionAutomationId":{"type":"integer","format":"int32","description":"Id of the contact whose automation membership wins where both contacts are in the same automation. Must be the `source` or the `destination`.","example":456}},"additionalProperties":false},"examples":{"Request":{"value":{"source":123,"destination":456,"resolutionFieldId":456,"resolutionAutomationId":456}}}}}},"responses":{"200":{"description":"The contacts were merged.","content":{"application/json":{"examples":{"Result":{"value":{"meta":{"success":true}}}},"schema":{"type":"object","properties":{"meta":{"type":"object","description":"The outcome of the merge.","properties":{"success":{"type":"boolean","description":"Always true. A failed merge returns an error status instead.","example":true}}}}}}}},"403":{"description":"The caller lacks the `pg_subscriber_merge` permission."},"404":{"description":"No contact has the source or destination id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found.","example":"No Result found for Subscriber with id 123"}}}}}},"422":{"description":"`source` is missing, or `source` and `destination` are the same contact."}}}},"/contact/sync":{"post":{"summary":"Create or update a contact by email (upsert)","description":"Create or update a single contact by email address (upsert). When a contact with the given email already exists it is updated and the response is 200; otherwise a new contact is created and the response is 201, so the status code tells you which happened. Use this whenever the request supplies email addresses that may already be in the account, including pasted or imported lists, or to update a contact without knowing its id. Unlike POST /contacts, it never fails with a duplicate-email error. How the contact is found: with the lookupByAcId query parameter and contact.id, by id first. With contact.whatsapp_id, by WhatsApp id and then by email. Otherwise by email. Without an email, which needs allowNullEmail, by phone. If no contact is found, one is created; if another request creates a contact with the same email at the same moment, this request updates that contact instead. Updating needs the edit contacts permission and creating needs the add contacts permission. Only the fields included in the request are changed; omitted fields keep their current values. The contact also takes the other fields of POST /contacts and PUT /contacts/{id}, such as tags, lists, form, ip4 and account, with the same meaning there. To create or update many contacts at once, use POST /import/bulk_import (up to 250 per request): it also creates or updates by email, can set list subscriptions and tags per contact, and reports each row's outcome through GET /import/info. Use POST /contacts only when the contact must be brand-new and an existing email should be reported as an error.","operationId":"sync-a-contacts-data","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"properties":{"email":{"type":["string","null"],"description":"The contact's email address, used to find the contact. Required unless allowNullEmail applies or whatsapp_id is sent; without it the request fails with 400. Sending whatsapp_id instead needs a WhatsApp inbox and phone-only contacts on the account. Line breaks are removed, and so are spaces at either end."},"firstName":{"type":"string","description":"The contact's first name."},"lastName":{"type":"string","description":"The contact's last name."},"phone":{"type":"string","description":"The contact's phone number. Must be a string; a number fails with 422. Used to find the contact when no email and no whatsapp_id are sent; if several contacts have this phone, the request fails with 400."},"fieldValues":{"type":"array","description":"Custom field values to save with the contact. Each item sets one field. Fields you leave out are not changed.","items":{"type":"object","properties":{"field":{"type":["integer","string"],"description":"Id of the custom field.","example":"1"},"value":{"type":["string","number","boolean","array","null"],"items":{"type":"string"},"description":"The new value. Lists are only supported for checkbox and listbox fields. For those fields, a string with the options separated by || also works.","example":"The Value for First Field"}},"additionalProperties":false}},"orgid":{"type":["integer","string"],"description":"Deprecated: use account. Id of the account to link the contact to."},"id":{"type":["integer","string"],"description":"Id of the contact to update. Used only with the lookupByAcId query parameter.","example":10},"allowNullEmail":{"type":"boolean","description":"Set to true to sync a contact without an email address. Works only when the account has phone-only contacts turned on; then either email or phone must be sent, or the request fails with 400, and without an email the contact is found by phone. When phone-only contacts are off, an email is still required."},"whatsapp_id":{"type":"string","description":"The contact's WhatsApp user id from Meta. When sent, the contact is found by this id first and then by email, and the email is optional. Needs a WhatsApp inbox on the account, or the request fails with 400, and phone-only contacts turned on, or it fails with 422.","example":"15551234567"},"account":{"type":"object","description":"Account to link the contact to, named by exactly one of id or name.","properties":{"id":{"type":["integer","string"],"description":"ID of an existing account; a missing account is refused."},"name":{"type":"string","description":"Exact name of the account."},"createIfMissing":{"type":"boolean","description":"Only with name: create the account when no account has that name. Refused with id."}},"additionalProperties":false},"account_name":{"type":"string","description":"Name of an account to find or create and link the contact to, when neither account nor organization is sent and the Accounts feature is on."},"organization":{"type":["integer","string"],"description":"Legacy alternative to account: ID of the account to link; ignored when account is sent."},"channelIdentities":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string","enum":["instagram","messenger"]},"channelAccountId":{"type":"string","minLength":1,"maxLength":64},"externalId":{"type":"string","minLength":1,"maxLength":255}},"additionalProperties":false},"description":"Channel identities that identify the contact and are attached to it. Only used when the account has channel identity contacts enabled."},"disableAccountMatch":{"type":"boolean","description":"true turns off automatic account matching when the sync creates a new contact; no effect when it updates one."},"fields":{"type":"array","items":{"type":"object","properties":{"field":{"type":["integer","string"],"description":"Id of the custom field."},"value":{"type":["string","number","boolean","array","null"],"items":{"type":"string"},"description":"The new value."}},"additionalProperties":false},"description":"Alternative to fieldValues; ignored when fieldValues is sent."},"form":{"type":["integer","string"],"description":"ID of a form; the contact is also subscribed to the form's lists."},"ip4":{"type":"string","format":"ipv4","description":"IPv4 address recorded as the contact's opt-in IP."},"lists":{"type":"array","items":{"type":"object","properties":{"list":{"type":["integer","string"],"description":"ID of the list; must exist."},"sdate":{"type":"string","description":"Subscribe date, as 'Y-m-d H:i:s' or 'Y-m-d' (start of that day). Defaults to now."},"sendInstantAutoresponder":{"type":"boolean","description":"Send the list's instant autoresponders even for a membership that already existed or was unsubscribed. Cannot be true with suppressInstantAutoresponder."},"suppressInstantAutoresponder":{"type":"boolean","description":"Do not send the list's instant autoresponders for this membership."},"sendLastCampaign":{"type":"boolean","description":"Send the list's last campaign even when the list does not do so on subscribe."}},"additionalProperties":false},"description":"List memberships to write for the contact."},"open_tracking_optout":{"type":["integer","string"],"enum":[0,1,"0","1"],"description":"0 or 1: the contact's open-tracking opt-out. Only accepted while the contact pixel tracking opt-out feature is on for the account; ignored otherwise."},"tags":{"type":"array","items":{"type":["string","integer","number"]},"description":"Tag names to add to the contact; missing tags are created."},"whatsapp_username":{"type":"string","maxLength":250}},"type":"object","description":"The contact to create or update."},"source":{"type":"string","description":"Recorded as the source of the request for the webhooks the change fires."},"useDefaults":{"type":"boolean","description":"Read but has no effect."}},"required":["contact"]},"examples":{"Request Example":{"value":{"contact":{"email":"jondoe@example.com","firstName":"John","lastName":"Doe","phone":"7223224241","fieldValues":[{"field":"1","value":"The Value for First Field"},{"field":"6","value":"2008-01-20"}]}}}}}}},"responses":{"200":{"description":"A contact was found and updated.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"10\",\n            \"field\": \"2\",\n            \"value\": \"Albany\",\n            \"cdate\": \"2022-04-14T10:03:23-05:00\",\n            \"udate\": \"2022-04-14T10:03:23-05:00\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/14/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/14/field\"\n            },\n            \"id\": \"14\",\n            \"owner\": \"10\"\n        },\n        {\n            \"contact\": \"10\",\n            \"field\": \"3\",\n            \"value\": \"Georgia\",\n            \"cdate\": \"2022-04-14T10:03:23-05:00\",\n            \"udate\": \"2022-04-14T10:03:23-05:00\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/15/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/15/field\"\n            },\n            \"id\": \"15\",\n            \"owner\": \"10\"\n        }\n    ],\n    \"fields\": [\n        {\n            \"title\": \"City\",\n            \"type\": \"text\",\n            \"perstag\": \"CITY\",\n            \"id\": \"2\"\n        },\n        {\n            \"title\": \"State\",\n            \"type\": \"text\",\n            \"perstag\": \"STATE\",\n            \"id\": \"3\"\n        }\n    ],\n    \"contact\": {\n        \"email\": \"johndoe@example.com\",\n        \"phone\": \"7223224241\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"cdate\": \"2022-04-14T10:03:23-05:00\",\n        \"udate\": \"2022-04-14T10:03:23-05:00\",\n        \"orgid\": \"0\",\n        \"orgname\": \"\",\n        \"links\": {\n            \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/10/bounceLogs\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/10/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC\",\n            \"contactData\": \"https://:account.api-us1.com/api/3/contacts/10/contactData\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/10/contactGoals\",\n            \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/10/contactLists\",\n            \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/10/contactLogs\",\n            \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/10/contactTags\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/10/contactDeals\",\n            \"deals\": \"https://:account.api-us1.com/api/3/contacts/10/deals\",\n            \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/10/fieldValues\",\n            \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/10/geoIps\",\n            \"notes\": \"https://:account.api-us1.com/api/3/contacts/10/notes\",\n            \"organization\": \"https://:account.api-us1.com/api/3/contacts/10/organization\",\n            \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/10/plusAppend\",\n            \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/10/trackingLogs\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/10/scoreValues\",\n            \"accountContacts\": \"https://:account.api-us1.com/api/3/contacts/10/accountContacts\",\n            \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/10/automationEntryCounts\"\n        },\n        \"hash\": \"75b8163f768dff1f0f7b5f69476b986a\",\n        \"fieldValues\": [\n            \"14\",\n            \"15\"\n        ],\n        \"id\": \"10\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"10","description":"Id of the contact."},"field":{"type":"string","example":"2","description":"Id of the custom field."},"value":{"type":"string","example":"Albany","description":"The stored value, as a string."},"cdate":{"type":"string","example":"2022-04-14T10:03:23-05:00","description":"When the value was first stored."},"udate":{"type":"string","example":"2022-04-14T10:03:23-05:00","description":"When the value was last changed."},"created_by":{"type":["string","null"],"description":"Id of the user who created the value, or null."},"updated_by":{"type":["string","null"],"description":"Id of the user who last changed the value, or null."},"links":{"type":"object","properties":{"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/fieldValues/14/owner","description":"URL of the contact the value belongs to."},"field":{"type":"string","example":"https://:account.api-us1.com/api/3/fieldValues/14/field","description":"URL of the custom field definition."}},"description":"URLs of the records related to this value."},"id":{"type":"string","example":"14","description":"Id of the field value record."},"owner":{"type":"string","example":"10","description":"Id of the contact the value belongs to, the same as contact."}}},"description":"The contact's custom field values. Present only when the request sent fieldValues."},"contact":{"type":"object","properties":{"email":{"type":["string","null"],"example":"johndoe@example.com","description":"The contact's email address."},"phone":{"type":"string","example":"7223224241","description":"The contact's phone number. Empty when not set."},"firstName":{"type":"string","example":"John","description":"The contact's first name. Empty when not set."},"lastName":{"type":"string","example":"Doe","description":"The contact's last name. Empty when not set."},"cdate":{"type":["string","null"],"example":"2022-04-14T10:03:23-05:00","description":"When the contact was created, in ISO 8601 with the account's UTC offset."},"udate":{"type":["string","null"],"example":"2022-04-14T10:03:23-05:00","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset."},"orgid":{"type":"string","example":"0","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none. The current account link is accountContacts."},"orgname":{"type":"string","example":"","description":"Name of the account named by orgid. Empty when there is none."},"links":{"type":"object","properties":{"bounceLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/bounceLogs","description":"URL of the read that lists the contact's bounce logs."},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC","description":"URL of the read that lists the automations the contact has entered. The URL includes limit=2500 and orders[lastdate]=DESC."},"contactData":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactData","description":"URL of the read for the contact's engagement data."},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactGoals","description":"URL of the read that lists the automation goals the contact has met."},"contactLists":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactLists","description":"URL of the read that lists the contact's list memberships."},"contactLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactLogs","description":"URL of the read that lists the contact's logs."},"contactTags":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactTags","description":"URL of the read that lists the tags on the contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactDeals","description":"URL of the read that lists the links between the contact and deals."},"deals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/deals","description":"URL of the read that lists the contact's deals."},"fieldValues":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/fieldValues","description":"URL of the read that lists the contact's custom field values."},"geoIps":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/geoIps","description":"URL of the read that lists the IP addresses recorded for the contact."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/notes","description":"URL of the read that lists the contact's notes."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/organization","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts."},"plusAppend":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/plusAppend","description":"URL of the read for the contact's appended social profile data."},"trackingLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/trackingLogs","description":"URL of the read that lists the contact's tracking logs."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/scoreValues","description":"URL of the read that lists the contact's score values."},"accountContacts":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/accountContacts","description":"URL of the read that lists the contact's account links. Present only when the account has the Accounts feature."},"automationEntryCounts":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/automationEntryCounts","description":"URL of the read that counts the contact's entries into each automation."}},"description":"URLs of the reads for the contact's related records."},"hash":{"type":"string","example":"75b8163f768dff1f0f7b5f69476b986a","description":"A 32-character identifier for the contact, set by the database."},"fieldValues":{"type":"array","items":{"type":"string","example":"14"},"description":"Ids of the contact's custom field value records. The records are in the top-level fieldValues array. Present only when the request sent fieldValues."},"id":{"type":"string","example":"10","description":"Id of the contact."},"organization":{"type":["string","null"],"example":null,"description":"The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."}},"description":"The contact as stored after the update. It holds every field of the contact; the common ones are listed here. GET /contacts/{id} describes the rest."},"fields":{"type":"array","description":"The definitions of the custom fields in fieldValues. Present only when the request sent fieldValues.","items":{"type":"object","description":"One custom field definition. Other definition properties are as in GET /fields/{id}.","properties":{"id":{"type":"string","description":"ID of the custom field.","example":"2"},"title":{"type":"string","description":"Name of the custom field.","example":"City"},"descript":{"type":"string","description":"Description of the custom field.","example":""},"type":{"type":"string","description":"Field type, such as text, textarea, date, datetime, dropdown, listbox, radio, checkbox or hidden.","example":"text"},"perstag":{"type":"string","description":"Personalization tag for the field, used as %PERSTAG% in campaigns.","example":"CITY"},"defval":{"type":"string","description":"Default value of the field.","example":""},"isrequired":{"type":"string","description":"\"1\" when the field is required on forms, otherwise \"0\".","example":"0"},"visible":{"type":"string","description":"\"1\" when the field is shown, otherwise \"0\".","example":"1"},"ordernum":{"type":"string","description":"Position of the field in field lists.","example":"1"},"cdate":{"type":["string","null"],"description":"When the field was created.","example":"2022-04-14T10:03:23-05:00"},"udate":{"type":["string","null"],"description":"When the field was last changed.","example":"2022-04-14T10:03:23-05:00"}}}}}}}}},"201":{"description":"No contact was found, so a new contact was created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"10\",\n            \"field\": \"2\",\n            \"value\": \"Albany\",\n            \"cdate\": \"2022-04-14T10:03:23-05:00\",\n            \"udate\": \"2022-04-14T10:03:23-05:00\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/14/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/14/field\"\n            },\n            \"id\": \"14\",\n            \"owner\": \"10\"\n        },\n        {\n            \"contact\": \"10\",\n            \"field\": \"3\",\n            \"value\": \"Georgia\",\n            \"cdate\": \"2022-04-14T10:03:23-05:00\",\n            \"udate\": \"2022-04-14T10:03:23-05:00\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/15/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/15/field\"\n            },\n            \"id\": \"15\",\n            \"owner\": \"10\"\n        }\n    ],\n    \"contact\": {\n        \"email\": \"johndoe@example.com\",\n        \"phone\": \"7223224241\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"cdate\": \"2022-04-14T10:03:23-05:00\",\n        \"udate\": \"2022-04-14T10:03:23-05:00\",\n        \"orgid\": \"0\",\n        \"orgname\": \"\",\n        \"links\": {\n            \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/10/bounceLogs\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/10/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC\",\n            \"contactData\": \"https://:account.api-us1.com/api/3/contacts/10/contactData\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/10/contactGoals\",\n            \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/10/contactLists\",\n            \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/10/contactLogs\",\n            \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/10/contactTags\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/10/contactDeals\",\n            \"deals\": \"https://:account.api-us1.com/api/3/contacts/10/deals\",\n            \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/10/fieldValues\",\n            \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/10/geoIps\",\n            \"notes\": \"https://:account.api-us1.com/api/3/contacts/10/notes\",\n            \"organization\": \"https://:account.api-us1.com/api/3/contacts/10/organization\",\n            \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/10/plusAppend\",\n            \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/10/trackingLogs\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/10/scoreValues\",\n            \"accountContacts\": \"https://:account.api-us1.com/api/3/contacts/10/accountContacts\",\n            \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/10/automationEntryCounts\"\n        },\n        \"fieldValues\": [\n            \"14\",\n            \"15\"\n        ],\n        \"id\": \"10\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"10","description":"Id of the contact."},"field":{"type":"string","example":"2","description":"Id of the custom field."},"value":{"type":"string","example":"Albany","description":"The stored value, as a string."},"cdate":{"type":"string","example":"2022-04-14T10:03:23-05:00","description":"When the value was first stored."},"udate":{"type":"string","example":"2022-04-14T10:03:23-05:00","description":"When the value was last changed."},"created_by":{"type":["string","null"],"description":"Id of the user who created the value, or null."},"updated_by":{"type":["string","null"],"description":"Id of the user who last changed the value, or null."},"links":{"type":"object","properties":{"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/fieldValues/14/owner","description":"URL of the contact the value belongs to."},"field":{"type":"string","example":"https://:account.api-us1.com/api/3/fieldValues/14/field","description":"URL of the custom field definition."}},"description":"URLs of the records related to this value."},"id":{"type":"string","example":"14","description":"Id of the field value record."},"owner":{"type":"string","example":"10","description":"Id of the contact the value belongs to, the same as contact."}}},"description":"Custom field values saved by this request."},"contact":{"type":"object","properties":{"email":{"type":["string","null"],"example":"johndoe@example.com","description":"The contact's email address."},"phone":{"type":"string","example":"7223224241","description":"The contact's phone number. Empty when not set."},"firstName":{"type":"string","example":"John","description":"The contact's first name. Empty when not set."},"lastName":{"type":"string","example":"Doe","description":"The contact's last name. Empty when not set."},"cdate":{"type":["string","null"],"example":"2022-04-14T10:03:23-05:00","description":"When the contact was created, in ISO 8601 with the account's UTC offset."},"udate":{"type":["string","null"],"example":"2022-04-14T10:03:23-05:00","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset."},"orgid":{"type":"string","example":"0","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none. The current account link is accountContacts."},"orgname":{"type":"string","example":"","description":"Name of the account named by orgid. Empty when there is none."},"links":{"type":"object","properties":{"bounceLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/bounceLogs","description":"URL of the read that lists the contact's bounce logs."},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC","description":"URL of the read that lists the automations the contact has entered. The URL includes limit=2500 and orders[lastdate]=DESC."},"contactData":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactData","description":"URL of the read for the contact's engagement data."},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactGoals","description":"URL of the read that lists the automation goals the contact has met."},"contactLists":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactLists","description":"URL of the read that lists the contact's list memberships."},"contactLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactLogs","description":"URL of the read that lists the contact's logs."},"contactTags":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactTags","description":"URL of the read that lists the tags on the contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/contactDeals","description":"URL of the read that lists the links between the contact and deals."},"deals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/deals","description":"URL of the read that lists the contact's deals."},"fieldValues":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/fieldValues","description":"URL of the read that lists the contact's custom field values."},"geoIps":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/geoIps","description":"URL of the read that lists the IP addresses recorded for the contact."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/notes","description":"URL of the read that lists the contact's notes."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/organization","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts."},"plusAppend":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/plusAppend","description":"URL of the read for the contact's appended social profile data."},"trackingLogs":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/trackingLogs","description":"URL of the read that lists the contact's tracking logs."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/scoreValues","description":"URL of the read that lists the contact's score values."},"accountContacts":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/accountContacts","description":"URL of the read that lists the contact's account links. Present only when the account has the Accounts feature."},"automationEntryCounts":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/10/automationEntryCounts","description":"URL of the read that counts the contact's entries into each automation."}},"description":"URLs of the reads for the contact's related records."},"fieldValues":{"type":"array","items":{"type":"string","example":"14"},"description":"Ids of the contact's custom field value records. The records are in the top-level fieldValues array."},"id":{"type":"string","example":"10","description":"Id of the contact."},"organization":{"type":["string","null"],"example":null,"description":"The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."}},"description":"The new contact. Only the fields set on create are returned: the fields the request sent, plus id, cdate, udate, links and the account fields. Fields the database fills in, such as hash, are not returned; read GET /contacts/{id} for the full record."}}}}}},"400":{"description":"The contact was not found or saved. The detail says why: \"Contact email must be provided for sync\" when there is no email; \"Contact email or phone must be provided for sync\" when allowNullEmail is used without either; a whatsapp_id on an account without a WhatsApp inbox, where the detail may be the key contacts:sync:email-required rather than a sentence; \"Phone must be unique when there is no email\" when several contacts have the phone; or, as for POST /contacts, a list in contact.lists or contact.form that needs an email or phone the contact does not have.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status. A number for some errors and a string for others."},"title":{"type":"string","description":"What went wrong. Present for some errors."},"detail":{"type":"string","description":"Why the request was refused."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Contact email must be provided for sync"}]}}}},"403":{"description":"The user does not have the permission the sync needs. The 403s are as for POST /contacts when a contact is created and as for PUT /contacts/{id} when one is updated: for example the add contacts permission to create, the edit contacts permission to update or to subscribe to lists through contact.lists or contact.form, and \"Forbidden\" when the user may not access the contact being updated.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status. A number for some errors and a string for others."},"title":{"type":"string","description":"What went wrong. Present for some errors."},"detail":{"type":"string","description":"Why the request was refused."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"Rare: a create lost a race with another request for the same email, and the contact that request created could not be read back.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found."}}}}}},"409":{"description":"The contact was not saved: another contact already has this whatsapp_id.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status. A number for some errors and a string for others."},"title":{"type":"string","description":"What went wrong. Present for some errors."},"detail":{"type":"string","description":"Why the request was refused."}}}}}}}}},"422":{"description":"The request was refused before the contact was saved. The body is as for POST /contacts when a contact is created and as for PUT /contacts/{id} when one is updated, including PUT's plain-text refusal to resubscribe a contact who unsubscribed from a list. This happens when contact is missing, a field has the wrong type (for example a phone that is not a string), or the contact fails validation, for example an invalid email address, or a whatsapp_id when phone-only contacts are off (\"WhatsApp ID requires phone only contacts to be enabled for this account.\"). When contact is a list with more than one item, errors is a single string instead: \"Sync failed. Requests should contain no more than 1 resource. For syncing more than one resource, see bulkSync instead.\"","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":["array","string"],"description":"The problems found, or for the list case a single message.","items":{"type":"object"}}}}}}}},"deprecated":false,"parameters":[{"name":"lookupByAcId","in":"query","required":false,"description":"Set to true to find the contact by contact.id before any other lookup. If no contact has that id, the other lookups are used.","schema":{"type":"boolean"},"example":true}]}},"/contact/trackExportPageVisit":{"get":{"summary":"Record a visit to the contact exports page","description":"Records that the user has seen the contact exports page: it sets the user's export.new_since_last_visit setting to 0, and creates the setting first when the user has none. The user is the signed-in user, or the user the API key belongs to. While the setting is 1, the side menu of the app shows a dot next to Exports. A finished export sets it to 1.\n\nIt reads no parameters and no body. Only GET is answered; any other method gets 405 with an empty body and an Allow: GET header.\n\nInternal: the app calls it each time the exports page opens.","operationId":"record-a-visit-to-the-contact-exports-page","x-canonical-resource":"account_user","x-side-effects":true,"x-internal":true,"responses":{"200":{"description":"The visit was recorded. The body is always the same.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true.","const":true}}},"examples":{"Result":{"value":{"success":true}}}}}},"405":{"description":"The request used a method other than GET. The body is empty and the Allow header names GET."}},"deprecated":false}},"/contact/view":{"post":{"summary":"Mark a contact as viewed","description":"Sets the contact's rating to 1 when it is 0. When the rating is already above 0, nothing changes. The save sends no websocket update to open app pages.\n\nThe body is form encoded with one field, `contact`. The script reads it from the POST form data only, so a JSON body, a query string or another method gets 422.\n\nThe body of a success is the text Success, not JSON, although the Content-Type header is application/json.\n\nInternal: the contact page in the app calls it when it opens a contact.","operationId":"mark-a-contact-as-viewed","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["contact"],"properties":{"contact":{"type":"integer","description":"ID of the contact."}}},"example":{"contact":110}}}},"responses":{"200":{"description":"The contact is marked as viewed.","content":{"application/json":{"schema":{"type":"string","const":"Success"},"example":"Success"}}},"404":{"description":"No contact has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptNotFound"},"example":{"message":"No Result found for Subscriber with id 110"}}}},"422":{"description":"`contact` is missing, empty or 0. Body: errors, a list with one item carrying status (a string) and detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactScriptKernelErrors"},"example":{"errors":[{"status":"422","detail":"\"contact\" is a required parameter."}]}}}}},"deprecated":false}},"/contact/{id}/enrich":{"post":{"summary":"Enrich a contact with data from outside providers","description":"Looks the contact up with outside data providers (FullContact and People Data Labs) and fills in what the contact is missing. It only fills empty values. It never changes a value the contact already has, except that a link to an account that no longer exists is moved to the matched account. The request has no body.\n\nThe providers are asked by the contact's email address, or by its phone number when it has no email. People Data Labs is asked by phone only when the number starts with `+`. A provider that fails, times out or does not know the contact adds nothing, and the others are still asked.\n\nWhat can be filled: first name, last name and phone; the LinkedIn, Twitter and Facebook profile URLs and the photo URL; and the city, state, postal code and country, when the contact has no location yet and the country maps to a two-letter code. On the company side, the contact's account is used. A contact with no account is linked to an existing account with a matching company name, or to a new account created from the company name and website. Then the empty account fields are filled: website, description, address, city, state, postal code, country, employees, revenue, industry and phone. The contact's job title on that account is filled too.\n\nThe call adds an entry to the contact's activity feed: an enrichment entry when something was filled, and a \"no data found\" entry when the providers had nothing, or nothing they sent could be written. No entry is added when the contact has no email or phone.\n\nEach call that gets an answer from at least one provider uses one enrichment from the account's monthly AI allowance, even when nothing new could be written. On the current consumption path one enrichment costs 1 AI credit, or 30 on accounts metered in activities; on the older path it counts as one unit. Calls that find nothing, or that are answered without asking a provider, use nothing. GET /contact/enrichment/usage shows the allowance.","operationId":"enrich-contact","parameters":[{"name":"id","in":"path","description":"ID of the contact to enrich","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The request was handled. `success` is true when the providers were asked, whether or not they found anything, and also when the contact has no email or phone, so no provider was asked. The activity feed tells these apart. `success` is false, with `skipped` set to `already_complete`, when the contact and its account already have a value in every field enrichment fills. Then no provider is asked and nothing is used from the allowance.","content":{"application/json":{"schema":{"properties":{"success":{"description":"False only when the contact was skipped.","type":"boolean"},"skipped":{"description":"Only when `success` is false: why the contact was skipped.","type":"string","enum":["already_complete"]}},"type":"object"},"example":{"success":true}}}},"403":{"description":"Contact data enrichment is not turned on for the account (`declined_flag`), or the user may not edit contacts (`permission_denied`).","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrichmentError"}}},"type":"object"},"example":{"errors":[{"title":"Contact data enrichment is not enabled.","code":"declined_flag"}]}}}},"404":{"description":"No contact has this id.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrichmentError"}}},"type":"object"},"example":{"errors":[{"title":"Contact not found.","code":"contact_not_found"}]}}}},"429":{"description":"The account has used its monthly AI allowance. No provider was asked. This is also the answer when the account has no AI usage entitlement.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrichmentError"}}},"type":"object"},"example":{"errors":[{"title":"You have reached your monthly limit of contact enrichments.","code":"declined_quota"}]}}}}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/contactArchives":{"get":{"summary":"List archived contacts","description":"The archived contacts of the account: contacts that were deleted and are kept for 360 days before they are purged. GET /contacts never returns them, whatever its status value; they are read here, or one at a time with GET /contactArchives/{id}. Only contacts archived within the last 360 days are listed, and only to API users in the Admin group: any other user gets 404. Each row is the contact as it was when archived, with the contact's fields plus deleted_at, when it was archived, and is_restorable, true when the contact is old enough to restore (archived at least 30 days ago by default; support can change an account's threshold) and not yet past the 360-day window. To restore archived contacts, use POST /contactArchives/restoreRequest (by id) or POST /contactArchives/restoreAll (by date range or search). Search with search: a full email address matches exactly; any other single word is matched anywhere in email, first name, last name or phone; words separated by spaces are matched together against the full name, or as a whole against the phone. Known defect: when search is a single word that is not an email address, start, end and the 360-day limit are not applied to the rows it matches by email or name, so such a search can return contacts archived more than 360 days ago and ignores the date window; combine dates with filters[...] or an exact email instead. Narrow the archive date with start and end, both Unix timestamps in milliseconds (a value in seconds is read as a date far in the past and raised to the 360-day limit). Exact-match filters use the column spellings: filters[email], filters[first_name], filters[last_name], filters[cdate], filters[udate], filters[userid], filters[deleted_at]. The API spellings firstName and lastName, and the keys name, account_name and orgname, are not valid filter keys and return 500 (name is accepted only as orders[name]). Other unknown filter keys are ignored. Order with orders[email], orders[first_name], orders[last_name], orders[cdate], orders[udate], orders[userid], orders[deleted_at] or orders[name] (first then last name), each asc or desc; the default is email ascending. 20 rows per request by default and at most 100; page with offset. meta.total is the number of matching archived contacts, as a string; send meta=omit to leave the metadata out.","operationId":"list-archived-contacts","x-canonical-resource":"contact","parameters":[{"name":"search","in":"query","description":"Text to search for. A full email address matches the archived contact's email exactly. Any other single word is matched anywhere in email, first name, last name or phone. Several words are matched together against the full name, or as a whole against the phone. A single word that is not an email address is not combined with start, end or the 360-day limit (known defect); a two-word search or an exact email address is.","schema":{"type":"string"}},{"name":"start","in":"query","description":"Only contacts archived on or after this moment, as a Unix timestamp in milliseconds. Rounded down to the start of that day. A value earlier than 360 days ago is raised to 360 days ago, the oldest archive the API serves.","schema":{"type":"integer","format":"int64"}},{"name":"end","in":"query","description":"Only contacts archived on or before this moment, as a Unix timestamp in milliseconds. Rounded up to the end of that day; a value in the future is capped at now.","schema":{"type":"integer","format":"int64"}},{"name":"filters[email]","in":"query","description":"Exact email address.","schema":{"type":"string"}},{"name":"filters[first_name]","in":"query","description":"Exact first name. filters[firstName] returns 500.","schema":{"type":"string"}},{"name":"filters[last_name]","in":"query","description":"Exact last name. filters[lastName] returns 500.","schema":{"type":"string"}},{"name":"filters[cdate]","in":"query","description":"Exact creation date and time of the contact, YYYY-MM-DD HH:MM:SS.","schema":{"type":"string","format":"date-time"}},{"name":"filters[udate]","in":"query","description":"Exact last-modified date and time of the contact, YYYY-MM-DD HH:MM:SS.","schema":{"type":"string","format":"date-time"}},{"name":"filters[userid]","in":"query","description":"Id of the account user who owned the contact.","schema":{"type":"integer","format":"int32"}},{"name":"filters[deleted_at]","in":"query","description":"Exact archive date and time, YYYY-MM-DD HH:MM:SS. For a range use start and end.","schema":{"type":"string","format":"date-time"}},{"name":"orders[email]","in":"query","description":"Order by email address (the default, ascending).","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[first_name]","in":"query","description":"Order by first name.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[last_name]","in":"query","description":"Order by last name.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[name]","in":"query","description":"Order by first name then last name.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[cdate]","in":"query","description":"Order by when the contact was created.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[udate]","in":"query","description":"Order by when the contact record was last changed.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[deleted_at]","in":"query","description":"Order by when the contact was archived; desc lists the most recently archived first.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","description":"Number of archived contacts to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of archived contacts to skip before returning results. Use with limit to page.","schema":{"type":"integer","default":0}},{"name":"meta","in":"query","description":"Set to omit to leave the metadata (total) out of the response.","schema":{"type":"string","enum":["omit"]}}],"responses":{"200":{"description":"The matching archived contacts and their total.","content":{"application/json":{"schema":{"type":"object","properties":{"contactArchives":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","example":"5606","description":"The contact id the contact had before it was archived."},"email":{"type":["string","null"],"example":"sam@example.com","description":"The contact's email address when it was archived. Null when the contact had no email address."},"firstName":{"type":"string","example":"Sam","description":"The contact's first name when it was archived. An empty string when none was set."},"lastName":{"type":"string","example":"Example","description":"The contact's last name when it was archived. An empty string when none was set."},"phone":{"type":"string","example":"","description":"The contact's phone number when it was archived. An empty string when none was set."},"cdate":{"type":"string","example":"2025-01-10T09:12:44-06:00","description":"When the contact was created."},"udate":{"type":"string","example":"2026-08-01T14:02:10-05:00","description":"When the contact record was last changed before it was archived."},"deleted_at":{"type":"string","example":"2026-08-01 14:02:10","description":"When the contact was archived, as YYYY-MM-DD HH:MM:SS in the platform timezone, the one the response's other timestamps carry, not the ISO form the other dates use."},"is_restorable":{"type":"boolean","example":true,"description":"True when the contact sits inside the restore window: archived at least 30 days ago (the default threshold, which support can change per account) and at most 360 days ago."},"orgid":{"type":"string","example":"0","description":"Id of the account (organization) the contact belonged to."},"orgname":{"type":"string","example":"","description":"Name of the account (organization) the contact belonged to."},"owner":{"type":"string","example":"1","description":"Id of the account user who owned the contact."},"updated_by":{"type":"string","example":"1","description":"Id of the account user who archived the contact."},"updated_by_first_name":{"type":["string","null"],"example":"Sam","description":"The first name of the user in updated_by. Null when no user is recorded or that user no longer exists."},"updated_by_last_name":{"type":["string","null"],"example":"Example","description":"The last name of the user in updated_by. Null when no user is recorded or that user no longer exists."},"links":{"type":"array","description":"Always an empty list. An archived contact has no related reads."}}},"description":"The archived contacts on this page."},"meta":{"type":"object","properties":{"total":{"type":"string","example":"3","description":"Number of archived contacts that match, as a string."},"page_input":{"type":"object","description":"Echo of the paging and search input the app uses."}},"description":"Totals and paging information."}}}}}},"404":{"description":"The API user is not in the Admin group.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"description":"HTTP status code."},"title":{"type":"string","example":"Not Found","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}}}},"post":{"summary":"Create an archived contact (not supported)","description":"Archived contacts cannot be created through the API. A contact is archived when it is deleted, so this call never adds an archived contact and changes nothing. An API user in the Admin group gets 405, with an Allow header of GET; any other user gets 404. The request body is not used, but a body that is a non-empty JSON list or a single non-empty value instead of an object gets 400 before any other check. POST /contactArchives/ (with a trailing slash) does the same. To restore archived contacts, use POST /contactArchives/restoreRequest or POST /contactArchives/restoreAll.","operationId":"create-archived-contact","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"x-internal":true,"responses":{"400":{"description":"The body is a non-empty JSON list or a single non-empty value instead of an object. The detail says what was given.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"description":"HTTP status code."},"title":{"type":"string","example":"Bad Request","description":"Short name of the error."},"detail":{"type":"string","example":"Request body must be a JSON object, array given.","description":"What went wrong."}}},"description":"One entry per problem."}}}}}},"404":{"description":"The API user is not in the Admin group.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"description":"HTTP status code."},"title":{"type":"string","example":"Not Found","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}},"405":{"description":"The API user is in the Admin group. Archived contacts cannot be created. The Allow header is GET.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":405,"description":"HTTP status code."},"title":{"type":"string","example":"Method Not Allowed","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}}}}},"/contactArchives/deleteList":{"post":{"summary":"Permanently delete several archived contacts","description":"Removes up to 100 archived contacts for good in one request. They can no longer be restored or listed. Only API users in the Admin group may call this; any other user gets 404. The body is a JSON object with ids, a list of one to one hundred archived contact ids as integers. Ids that are already gone are skipped. Returns 200 with an empty object.","operationId":"delete-archived-contacts","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"integer","format":"int32"},"description":"The archived contact ids to delete, one to one hundred positive integers."}},"additionalProperties":false},"example":{"ids":[5606,5607]}}}},"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"404":{"description":"The API user is not in the Admin group. The body is validated first, so an invalid body from a non-Admin user gets the 422.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"description":"HTTP status code."},"title":{"type":"string","example":"Not Found","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}},"422":{"description":"ids is missing, empty, not a list, longer than 100, or holds a value that is not a positive integer. Each problem is one entry in errors with a source pointer.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":["string","integer"],"example":422,"description":"HTTP status code."},"title":{"type":"string","example":"Invalid attribute","description":"Short name of the error."},"detail":{"type":"string","example":"All ids must be integers.","description":"What went wrong."}}},"description":"One entry per problem."}}}}}}}}},"/contactArchives/restoreAll":{"post":{"summary":"Restore all matching archived contacts","description":"Queues a restore of every archived contact that matches the body, the same selection the app's Archived contacts view makes with \"Restore all\". Only API users in the Admin group may call this; any other user gets 404. The body is required: send {} to restore every archived contact inside the restore window; an empty body is refused with 400. start and end narrow the archive date; the restore rounds them out to whole days in UTC. search narrows the selection by email, name or phone. Known defect: when search has several words, start and end limit only the contacts it matches by phone, not the ones it matches by name; the 360-day limit still applies to both. Contacts archived more than 360 days ago are never restored. The contacts come back in the background, so the response only confirms the request; follow it with GET /contactArchives/restoreRequest/{id}. When several matching archived contacts have the same email address, only the one with the highest id (normally the most recently archived) is restored. Before queueing, the request is refused with 400 if a contact in the date range was archived too recently to restore. With search, only contacts whose email contains the search text are checked; contacts that match search only by name or phone are not checked, so they are restored even if they were archived too recently. Only one restore runs at a time: while one is running this returns 409. Only POST is accepted; any other method returns 405.","operationId":"restore-all-archived-contacts","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"start":{"type":"integer","format":"int64","description":"Only contacts archived on or after the start of this day (UTC), given as a Unix timestamp in milliseconds. The too-recent check runs from the exact moment instead. A value earlier than 360 days ago is raised to 360 days ago. Ignored when not a number."},"end":{"type":"integer","format":"int64","description":"Only contacts archived on or before the end of this day (UTC), given as a Unix timestamp in milliseconds. The too-recent check runs up to the exact moment instead. Defaults to now. Ignored when not a number."},"search":{"type":"string","description":"Text to search for. A full email address matches exactly; any other single word is matched anywhere in email, first name, last name or phone; several words are matched together against the full name, or as a whole against the phone. The too-recent check described above uses only the email part of this match. With several words, start and end do not limit name matches (known defect)."}},"additionalProperties":false},"examples":{"Everything in the window":{"value":{}},"Archived in a date range":{"value":{"start":1757376000000,"end":1759968000000}}}}},"required":true},"responses":{"201":{"description":"The restore was queued. The contacts are restored in the background; follow progress with GET /contactArchives/restoreRequest/{id} using restoreRequest.restoreRequestId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreQueued"}}}},"400":{"description":"Empty body: the request body is missing or is not valid JSON. With a JSON error body: a contact in the date range whose email contains search (or any contact in the range, without search) was archived too recently to restore (by default contacts must have been archived at least 30 days ago; support can change an account's threshold). The whole request is refused and nothing is queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreError"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Some contacts cannot be restored yet"}]}}}},"404":{"description":"The API user is not in the Admin group. The body is empty."},"405":{"description":"The method is not POST. The body is empty."},"409":{"description":"A restore request made in the last 30 days is still running. Only one restore can run at a time; wait for it to finish (its finished_at is set) and try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreError"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"There is already a restore request in progress."}]}}}},"500":{"description":"The restore service could not be reached or returned an error. Nothing is restored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreServerError"}}}}}}},"/contactArchives/restoreRequest":{"get":{"summary":"List running contact restores","description":"The account's contact restores that are still running: requests that have not finished, matched at least one contact, and were made in the last 30 days. A finished restore is not listed; read it with GET /contactArchives/restoreRequest/{id}. Only API users in the Admin group may call this; any other user gets 404. meta.total is the number of requests listed. While this list is not empty, POST /contactArchives/restoreRequest and POST /contactArchives/restoreAll return 409.","operationId":"list-contact-restore-requests","x-canonical-resource":"contact","responses":{"200":{"description":"The running restore requests.","content":{"application/json":{"schema":{"type":"object","properties":{"restoreRequests":{"type":"array","items":{"$ref":"#/components/schemas/ContactRestoreRequest"},"description":"The running restore requests."},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"description":"The number of running restore requests listed."}},"description":"Totals."}}}}}},"404":{"description":"The API user is not in the Admin group. The body is empty."},"500":{"description":"The restore service could not be reached or returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreServerError"}}}}}},"post":{"summary":"Restore archived contacts by id","description":"Queues a restore of the archived contacts with the given ids. The contacts come back in the background, so the response only confirms the request; follow it with GET /contactArchives/restoreRequest/{id}. Only API users in the Admin group may call this; any other user gets 404. Every id must be an archived contact inside the restore window (see is_restorable on GET /contactArchives), or the whole request is refused with 400. When two selected archived contacts have the same email address, only the one with the highest id (normally the most recently archived) is restored. An empty ids list is accepted: it returns 201 and creates a restore request that matches no contacts, finishes without restoring anything, and never appears in GET /contactArchives/restoreRequest. Only one restore runs at a time: while one is running this returns 409. To restore every archived contact that matches a date range or a search, use POST /contactArchives/restoreAll.","operationId":"restore-archived-contacts","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Ids of the archived contacts to restore, as listed by GET /contactArchives."}},"additionalProperties":false},"examples":{"Restore two contacts":{"value":{"ids":[5606,5607]}}}}}},"responses":{"201":{"description":"The restore was queued. The contacts are restored in the background; follow progress with GET /contactArchives/restoreRequest/{id} using restoreRequest.restoreRequestId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreQueued"}}}},"400":{"description":"Empty body: the request body is missing, is not valid JSON, or has no ids. With a JSON error body: the restore was refused and nothing was queued, because at least one selected contact cannot be restored: it was archived too recently (by default contacts must have been archived at least 30 days ago; support can change an account's threshold), it is past the 360-day restore window, or it is not an archived contact at all. The whole request is refused, not just those contacts. detail is \"Some contacts are past the restore window\" when any contact is past the window, otherwise \"Some contacts cannot be restored yet\".","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreError"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Some contacts cannot be restored yet"}]}}}},"404":{"description":"The API user is not in the Admin group. The body is empty."},"405":{"description":"The method is not GET or POST. The body is empty."},"409":{"description":"A restore request made in the last 30 days is still running. Only one restore can run at a time; wait for it to finish (its finished_at is set) and try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreError"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"There is already a restore request in progress."}]}}}},"500":{"description":"ids is not a list, or the restore service could not be reached or returned an error. Nothing is restored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreServerError"}}}}}}},"/contactArchives/restoreRequest/{id}":{"get":{"summary":"Retrieve a contact restore","description":"The progress of one contact restore, running or finished. The restore is finished when finished_at is set; contacts_restored, contacts_failed and contacts_to_be_skipped then add up to contacts_matching. Only API users in the Admin group may call this; any other user gets 404. An id that does not exist, or that belongs to another account, returns 500, not 404.","operationId":"get-contact-restore-request","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","required":true,"description":"The restore request id, from restoreRequestId in the response that created it or from GET /contactArchives/restoreRequest.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The restore request.","content":{"application/json":{"schema":{"type":"object","properties":{"restoreRequest":{"$ref":"#/components/schemas/ContactRestoreRequest"}}}}}},"404":{"description":"The API user is not in the Admin group. The body is empty."},"500":{"description":"No restore request with that id exists for this account, or the restore service could not be reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRestoreServerError"}}}}}}},"/contactArchives/{id}":{"get":{"summary":"Retrieve an archived contact","description":"One archived contact by the id it had before it was archived. The row is the contact as it was when archived, with deleted_at saying when. Unlike the list, this read is not limited to Admin users, has no 360-day limit, and carries no is_restorable flag. Returns 404 if no archived contact has that id, including when the contact is still active or has been permanently deleted.","operationId":"retrieve-archived-contact","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","required":true,"description":"The archived contact's id, as listed by GET /contactArchives.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The archived contact.","content":{"application/json":{"schema":{"type":"object","properties":{"contactArchive":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","example":"5606","description":"The contact id the contact had before it was archived."},"email":{"type":["string","null"],"example":"sam@example.com","description":"The contact's email address when it was archived. Null when the contact had no email address."},"firstName":{"type":"string","example":"Sam","description":"The contact's first name when it was archived. An empty string when none was set."},"lastName":{"type":"string","example":"Example","description":"The contact's last name when it was archived. An empty string when none was set."},"phone":{"type":"string","example":"","description":"The contact's phone number when it was archived. An empty string when none was set."},"cdate":{"type":"string","example":"2025-01-10T09:12:44-06:00","description":"When the contact was created."},"udate":{"type":"string","example":"2026-08-01T14:02:10-05:00","description":"When the contact record was last changed before it was archived."},"deleted_at":{"type":"string","example":"2026-08-01 14:02:10","description":"When the contact was archived, as YYYY-MM-DD HH:MM:SS in the platform timezone, the one the response's other timestamps carry, not the ISO form the other dates use."},"orgid":{"type":"string","example":"0","description":"Id of the account (organization) the contact belonged to."},"orgname":{"type":"string","example":"","description":"Name of the account (organization) the contact belonged to."},"owner":{"type":"string","example":"1","description":"Id of the account user who owned the contact."},"updated_by":{"type":"string","example":"1","description":"Id of the account user who archived the contact."},"links":{"type":"array","description":"Always an empty list. An archived contact has no related reads."}},"description":"The archived contact."}}}}}},"404":{"description":"No archived contact has this id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says no archived contact has this id."}}}}}}}},"put":{"summary":"Change when an archived contact was archived (staging environment only)","description":"A testing aid for the staging environment. It sets deleted_at, the date and time a contact was archived, so that a test can make an archived contact old enough to restore, or old enough to be purged, without waiting. It changes nothing else about the archived contact. A body that is a non-empty JSON list or a single non-empty value instead of an object gets 400 before any other check; an empty body, one that is not JSON, an empty list, or a value such as 0, false, an empty string or null is read as an empty object. Anywhere other than the staging environment, including production, it is turned off: an Admin user gets 405 and any other user gets 404. On the staging environment, only API users in the Admin group may call it; any other user gets 404. PATCH /contactArchives/{id} does the same thing. Returns 200 with an empty object. Sending the deleted_at the contact already has returns 500, because nothing was changed.","operationId":"update-archived-contact-deleted-at","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true,"parameters":[{"name":"id","in":"path","required":true,"description":"The archived contact's id, as listed by GET /contactArchives.","schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contactArchive"],"properties":{"contactArchive":{"type":"object","required":["deleted_at"],"properties":{"deleted_at":{"type":"string","example":"2025-12-20 10:30:00","description":"The new archive date and time, for example YYYY-MM-DD HH:MM:SS. Any date-and-time text PHP can read is accepted, but it must include a time: a date on its own is refused with 400, and so are null and an empty string. The value is stored in the server's time zone, so a time zone offset in the value is converted to it."}},"description":"The fields to change. Only deleted_at is used.","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"contactArchive":{"deleted_at":"2025-12-20 10:30:00"}}}}}}},"responses":{"200":{"description":"deleted_at was changed.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"400":{"description":"The body is not usable. A body that is a non-empty JSON list or a single non-empty value gets detail Request body must be a JSON object, followed by what was given; this is checked first and has an integer status and a title. Otherwise the detail says which problem it is: contactArchive or deleted_at is missing (deleted_at field is required), deleted_at is null or empty (deleted_at must be a valid datetime string and cannot be null), deleted_at is not a string (deleted_at must be a string), or it is not a date and time (Invalid deleted_at datetime format).","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":["string","integer"],"example":"400","description":"HTTP status code: the number 400 when the body is a non-empty list or a single value instead of an object, otherwise the string \"400\"."},"title":{"type":"string","example":"Bad Request","description":"Present only when the body is not a JSON object."},"detail":{"type":"string","example":"deleted_at field is required","description":"What went wrong."}}},"description":"One entry per problem."}}}}}},"404":{"description":"The API user is not in the Admin group (no detail), or no archived contact has this id (detail Archived contact not found).","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"description":"HTTP status code."},"title":{"type":"string","example":"Not Found","description":"Short name of the error."},"detail":{"type":"string","example":"Archived contact not found","description":"What went wrong."}}},"description":"One entry per problem."}}}}}},"405":{"description":"Not on the staging environment, for example on production. The Allow header is GET.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":405,"description":"HTTP status code."},"title":{"type":"string","example":"Method Not Allowed","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}},"500":{"description":"deleted_at could not be saved, including when the value sent is the one the contact already has.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","example":"500","description":"HTTP status code, as a string."},"detail":{"type":"string","example":"No archived contact found with id: 1","description":"What went wrong."}}},"description":"One entry per problem."}}}}}}}},"delete":{"summary":"Permanently delete an archived contact","description":"Removes an archived contact for good. The contact can no longer be restored or listed. Only API users in the Admin group may call this; any other user gets 404. Returns 200 with an empty object, also when the id was already gone, so a repeated delete is harmless. To remove several at once, use POST /contactArchives/deleteList.","operationId":"delete-archived-contact","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"The archived contact's id, as listed by GET /contactArchives.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"404":{"description":"The API user is not in the Admin group.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"description":"HTTP status code."},"title":{"type":"string","example":"Not Found","description":"Short name of the error."}}},"description":"One entry per problem."}}}}}}}}},"/contactAutomation/report":{"get":{"summary":"Export an automation's contacts as CSV","description":"Returns a CSV file of the automation's contact automations (runs), usually one row for each time a contact entered. Each row has the contact's ID, email, first name, last name and phone, the account name when the account has the Accounts feature, one column for each custom field of the automation's lists (global fields too), the date entered, the last date and whether the run is completed (1 or 0). Column titles are in the user's language. With g_id and g_status=1, two more columns give the time the contact took to reach the goal and when they reached it. The export is not paged: limit and offset do not apply.\n\nMore filters: tags[] keeps runs whose contact now has any of the tags; a contact with several of them appears once for each. lists[] keeps runs linked to any of the lists. min_time and max_time keep runs whose time in the automation, in seconds, is above min_time and at most max_time. With g_id, g_tagid and g_tags[] keep runs that reached the goal with all of those tags, and g_listid and g_lists[] runs that reached it on all of those lists; tags[] and lists[] take their place when sent. g_min_time and g_max_time do the same for the time taken to reach the goal. Send at most one of the goal tag and list filters, and do not combine g_min_time or g_max_time with min_time or max_time: those combinations do not filter as described. ids keeps only the runs with those IDs, sent comma-separated or as an array. The filters parameters of GET /automations/{seriesId}/contactAutomations also apply. orders[<key>]=asc or desc sorts by name, first_name, last_name, email, cdate, score (with scoreid), goal_completion (with g_id) or a run column.\n\nReturns 404 if no automation has the id. Only GET runs the report; any other method gets an empty answer.","operationId":"export-automation-contacts-report","x-canonical-resource":"contactAutomations","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactAutomationHelperAutomation"},{"name":"g_id","in":"query","description":"ID of a goal in the automation. Needed for g_status. goal is another name for it, and wins when both are sent.","schema":{"type":"integer"}},{"name":"g_status","in":"query","description":"With a goal: 1 lists only runs that reached the goal and adds the goal columns, 0 lists only runs that did not. A value that is not a number counts as 0. Other numbers list every run.","schema":{"type":["integer","string"]}},{"name":"q","in":"query","description":"Lists only contacts whose email, first name, last name, phone or account name contains this text, or whose first or last name on one of their list subscriptions does.","schema":{"type":"string"}}],"responses":{"200":{"description":"The CSV file, sent as an attachment named export.csv. It starts with a UTF-8 byte order mark and a header row.","content":{"text/csv":{"schema":{"type":"string"},"example":"Contact ID,Email,First Name,Last Name,Phone,Date Entered,Last Date,Completed\n110,sam@example.com,Sam,Example,,2026-10-14 09:12:44,2026-10-15 10:02:11,1\n"}}},"404":{"description":"automation is missing or no automation has that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationHelperNotFound"},"example":{"message":"No Result found for Series with id 9"}}}}}}},"/contactAutomation/sendEmail":{"post":{"summary":"Send an automation's one-to-one email step","description":"Called back by the outbound email queue when a contact reaches a one-to-one email step of an automation. Not called by the app. The email is built from the step's subject and message, personalized for the contact and the deal, and sent to the contact, with the step's cc and bcc, through the deal connection (the user's mailbox connected through Nylas). When the email-threading feature is on and the step replies to an earlier one-to-one email step, it is sent in that email's thread. If the earlier email is no longer in the mailbox, or looking it up fails, it is sent as a new email. If the earlier email has not synced yet, the request fails so the queue tries again later.\n\nuuid stops duplicate sends: a request whose uuid is being handled, or was already sent, gets 400 and changes nothing. When subscriberSeriesId names a run, the outcome is recorded in its automation history, so the step shows as sent or failed. This happens after the Nylas call, also when no answer comes back, and for a bad body, a missing step, contact or deal, or a missing deal connection. Nothing is recorded for a duplicate, a deal connection that is not on Nylas v3, an earlier email that has not synced, or a method other than POST. A successful send also saves the email with its recipients on the contact and deal timeline and records it as sent by the step. When Nylas says the mailbox is not allowed to send and subscriberSeriesId names a run, the deal connection is marked as unable to send. This request does not check the sending rate limit; the step checks it before queueing.\n\nOnly POST runs the send; any other method gets 405. Most failures answer 400 so the queue does not try again. Other Nylas statuses pass through as they are.","operationId":"send-automation-outbound-email-step","x-canonical-resource":"contactAutomations","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationOutboundEmailSend"},"example":{"blockId":230,"seriesId":12,"subscriberId":110,"subscriberSeriesId":7,"dealConnectionId":3,"logId":0,"dealId":15,"uuid":"6f1c2a4e-91b3-11f0-8de9-0242ac120002"}}}},"responses":{"200":{"description":"Nylas sent the email. The body is empty."},"400":{"description":"Nothing was sent, and the queue does not try again. The causes: a required field is missing or the body is an empty object; the step, contact or deal does not exist; no deal connection has dealConnectionId; the uuid is being handled or was already sent; Nylas rejects the request or the mailbox is not allowed to send. The body is empty, except for a deal connection that is not on Nylas v3: then the body is an errors array whose detail is \"Nylas v2 sending is no longer supported\", or \"Retrieving Nylas v2 messages is no longer supported\" for a threaded reply."},"405":{"description":"The method is not POST. The body is empty."},"502":{"description":"No answer came back from Nylas. The body is empty, and the queue tries again."}}}},"/contactAutomation/showcase":{"get":{"summary":"Retrieve an automation's showcase","description":"How many times contacts entered the automation, plus the ten tags and ten lists most held by those contacts, and how long runs took, in groups. A contact who entered more than once counts once for each run. When nobody entered, tags, lists and timespans are empty. Legacy endpoint with no method check: any HTTP method is answered the same way; GET is the documented verb.","operationId":"retrieve-automation-showcase","x-canonical-resource":"contactAutomations","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactAutomationHelperAutomation"}],"responses":{"200":{"description":"The showcase.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationShowcase"},"example":{"entries":5,"tags":[{"count":"3","id":"22","tag":"blog"}],"lists":[],"timespans":[{"min":20,"max":80,"count":5}]}}}},"404":{"description":"No automation has that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationHelperNotFound"},"example":{"message":"No Result found for Series with id 9"}}}},"422":{"description":"automation is missing, empty or 0. The body is plain text.","content":{"text/plain":{"schema":{"type":"string"},"example":"automation is required"}}}}}},"/contactAutomation/stats":{"get":{"summary":"Retrieve an automation's completion stats","description":"How many times contacts entered the automation, how many of those runs completed, the completion rate, how it changed since 30 days ago and the average time to complete. When nobody entered, or no run completed, every number except entered is 0. Legacy endpoint with no method check: any HTTP method is answered the same way; GET is the documented verb.","operationId":"retrieve-automation-completion-stats","x-canonical-resource":"contactAutomations","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactAutomationHelperAutomation"}],"responses":{"200":{"description":"The stats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCompletionStats"},"example":{"entered":10,"completed":7,"rate":"70.0000","rateChange":"20.0000","averageTime":3600000}}}},"403":{"description":"automation is missing, empty or 0. The body is plain text.","content":{"text/plain":{"schema":{"type":"string"},"example":"automation is required"}}},"404":{"description":"No automation has that id, or the stats could not be read. The body is a plain-text message.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/contactAutomationLogs":{"get":{"summary":"List all contact automation history entries","description":"Lists the history entries kept for contacts' runs through automations, across the whole account. For most runs this is not the full step history: only some kinds of steps, such as waits, goals and sends, keep an entry here. For the full step history of one run, use GET /automations/{seriesId}/contactAutomations/{contactAutomationId}/steps. To read one run's entries, use GET /contactAutomations/{id}/automationLogs. The list has no filters or sort options, and entries come in no guaranteed order. Page with limit and offset, or fetch specific entries with ids.","operationId":"list-all-contact-automation-logs","x-canonical-resource":"contactAutomations","parameters":[{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the entries.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated entry IDs to return. When set, only those entries are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of history entries under contactAutomationLogs, with the number of matching entries in meta.total. contactAutomationLogs is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactAutomationLogs":{"type":"array","description":"The history entries on this page. For most runs, only some kinds of steps have an entry.","items":{"$ref":"#/components/schemas/ContactAutomationLogEntry"}},"meta":{"type":"object","description":"About the whole result, not just this page.","properties":{"total":{"type":"integer","description":"Number of matching entries across all pages. When ids is set, the number of those ids that exist. When the account has very many entries and ids is not set, this can be an estimate; total_is_approximate then says so.","example":1},"total_is_approximate":{"type":"boolean","description":"true when total is an estimate rather than an exact count. Only present on some accounts.","example":false}}}}},"examples":{"Result":{"value":{"contactAutomationLogs":[{"seriesid":"2","blockid":"5","subscriberid":"110","contactseriesid":"7","tstamp":"2026-10-14T09:12:44-05:00","res":"1","links":{"automation":"https://example.api-us1.com/api/3/contactAutomationLogs/31/automation","block":"https://example.api-us1.com/api/3/contactAutomationLogs/31/block","contact":"https://example.api-us1.com/api/3/contactAutomationLogs/31/contact","contactAutomation":"https://example.api-us1.com/api/3/contactAutomationLogs/31/contactAutomation"},"id":"31","automation":"2","block":"5","contact":"110","contactAutomation":"7"}],"meta":{"total":1,"total_is_approximate":false}}}}}}}},"deprecated":false}},"/contactAutomationLogs/{id}":{"get":{"summary":"Retrieve a contact automation history entry","description":"Returns one history entry by its ID. Each entry records one step of a contact's run through an automation. For most runs only some kinds of steps, such as waits, goals and sends, keep an entry here. Returns 404 if no entry has the id.","operationId":"retrieve-a-contact-automation-log","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the history entry.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The history entry under contactAutomationLog.","content":{"application/json":{"schema":{"type":"object","properties":{"contactAutomationLog":{"description":"The history entry.","allOf":[{"$ref":"#/components/schemas/ContactAutomationLogEntry"}]}}},"examples":{"Result":{"value":{"contactAutomationLog":{"seriesid":"2","blockid":"5","subscriberid":"110","contactseriesid":"7","tstamp":"2026-10-14T09:12:44-05:00","res":"1","links":{"automation":"https://example.api-us1.com/api/3/contactAutomationLogs/31/automation","block":"https://example.api-us1.com/api/3/contactAutomationLogs/31/block","contact":"https://example.api-us1.com/api/3/contactAutomationLogs/31/contact","contactAutomation":"https://example.api-us1.com/api/3/contactAutomationLogs/31/contactAutomation"},"id":"31","automation":"2","block":"5","contact":"110","contactAutomation":"7"}}}}}}},"404":{"description":"No history entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says which id was not found.","example":"No Result found for SubscriberSeriesLog with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for SubscriberSeriesLog with id 100"}}}}}}},"deprecated":false}},"/contactAutomationStats":{"get":{"summary":"List contact automation stats","description":"Not supported. Always returns 404, whatever the query. To get one contact's stats for one automation, use GET /contactAutomationStats/{id}.","operationId":"list-all-contact-automation-stats","x-canonical-resource":"contactAutomations","x-internal":true,"responses":{"404":{"$ref":"#/components/responses/ContactAutomationStatsNotSupported"}}},"post":{"summary":"Create a contact automation stat","description":"Not supported. Always returns 405 with Allow: GET, unless the body is a non-empty JSON array or a non-empty, non-zero JSON value that is not an object, which returns 400 first. Nothing is changed.","operationId":"create-a-contact-automation-stat","x-canonical-resource":"contactAutomations","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"responses":{"400":{"$ref":"#/components/responses/ContactAutomationStatsBodyNotObject"},"405":{"$ref":"#/components/responses/ContactAutomationStatsMethodNotAllowed"}}}},"/contactAutomationStats/{id}":{"get":{"summary":"Retrieve a contact's stats for one automation","description":"Returns how far one contact has got in one automation: whether it finished, the share of steps done, and when it last entered and finished. The id joins the contact id and the automation id with a hyphen, contact first. The body holds the automation under automation, the contact under contact, and the stats under contactAutomationStat. Returns 404 when the id is not two numbers joined by a hyphen, when the automation or the contact does not exist, or when the contact has no history in the automation. No history means the contact has never taken a step in it, the automation has no blocks, or the automation is hidden.","operationId":"retrieve-a-contact-automation-stat","x-canonical-resource":"contactAutomations","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactAutomationStatId"}],"responses":{"200":{"description":"The automation, the contact and the stats.","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"$ref":"#/components/schemas/ContactAutomationStatAutomation"},"contact":{"$ref":"#/components/schemas/ContactAutomationStatContact"},"contactAutomationStat":{"$ref":"#/components/schemas/ContactAutomationStat"}}},"examples":{"Result":{"value":{"automation":{"name":"Welcome series","cdate":"2026-01-05T09:30:00-06:00","mdate":"2026-02-10T14:00:00-06:00","status":"1","links":{"blocks":"https://example.api-us1.com/api/3/automations/6/blocks","contactAutomations":"https://example.api-us1.com/api/3/automations/6/contactAutomations"},"id":"6"},"contact":{"cdate":"2026-01-02T08:00:00-06:00","email":"sam@example.com","firstName":"Sam","lastName":"Example","deleted":"0","udate":"2026-02-01T10:00:00-06:00","links":{"contactAutomations":"https://example.api-us1.com/api/3/contacts/1/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC"},"id":"1"},"contactAutomationStat":{"id":"1-6","automation":"6","contact":"1","isCompleted":false,"percentCompleted":67,"lastCompletedDate":"2026-01-20T12:00:00-06:00","lastEnteredDate":"2026-02-02T12:00:00-06:00"}}}}}}},"404":{"description":"No history, a missing automation or contact, or a malformed id. No history gets an errors array. The other cases get a message, such as No Result found for Subscriber with id 1 for a missing contact.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ContactAutomationStatErrors"},{"$ref":"#/components/schemas/ContactAutomationStatMessage"}]},"examples":{"No history":{"value":{"errors":[{"status":404,"title":"Not Found","detail":"Contact 1 has no history yet for Automation 6"}]}},"Automation not found":{"value":{"message":"No Result found for Series with id 6"}},"Malformed id":{"value":{"message":"No Result found for ContactAutomationStat with id 1-abc"}}}}}}}},"put":{"summary":"Update a contact automation stat","description":"Not supported. Always returns 405 with Allow: GET, unless the body is a non-empty JSON array or a non-empty, non-zero JSON value that is not an object, which returns 400 first. Nothing is changed.","operationId":"update-a-contact-automation-stat","x-canonical-resource":"contactAutomations","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactAutomationStatId"}],"responses":{"400":{"$ref":"#/components/responses/ContactAutomationStatsBodyNotObject"},"405":{"$ref":"#/components/responses/ContactAutomationStatsMethodNotAllowed"}}},"patch":{"summary":"Patch a contact automation stat","description":"Not supported. Always returns 405 with Allow: GET, unless the body is a non-empty JSON array or a non-empty, non-zero JSON value that is not an object, which returns 400 first. Nothing is changed.","operationId":"patch-a-contact-automation-stat","x-canonical-resource":"contactAutomations","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactAutomationStatId"}],"responses":{"400":{"$ref":"#/components/responses/ContactAutomationStatsBodyNotObject"},"405":{"$ref":"#/components/responses/ContactAutomationStatsMethodNotAllowed"}}},"delete":{"summary":"Delete a contact automation stat","description":"Not supported. Always returns 405 with Allow: GET. Nothing is deleted.","operationId":"delete-a-contact-automation-stat","x-canonical-resource":"contactAutomations","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactAutomationStatId"}],"responses":{"405":{"$ref":"#/components/responses/ContactAutomationStatsMethodNotAllowed"}}}},"/contactAutomationStats/{id}/{relationship}":{"get":{"summary":"Retrieve a related record of a contact automation stat","description":"Not supported. Always returns 404, whatever the id and the relationship.","operationId":"retrieve-contact-automation-stat-related","x-canonical-resource":"contactAutomations","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactAutomationStatId"},{"name":"relationship","in":"path","required":true,"description":"Any name. Every value returns 404.","schema":{"type":"string"}}],"responses":{"404":{"$ref":"#/components/responses/ContactAutomationStatsNotSupported"}}}},"/contactAutomations":{"post":{"summary":"Add a contact to an automation","description":"Add a contact to an automation, or to several at once, so it enters the workflow and starts moving through its actions. An add through the API counts as added manually, so the automation's setting for how often a contact may enter does not apply: adding the same contact again starts another run instead of failing, up to 100 adds per contact per automation in 24 hours, after which the call answers 403. Only an active automation (status 1) is guaranteed to accept contacts. A draft (0) or inactive (2) automation answers 422 \"The automation you have selected is inactive.\" for every contact, and so does a paused (3) one unless the account's automations accept entries while paused, so check the status in GET /automations first. Name the contact with contact, its id, or with contact_email, its email address; when no contact has that address one is created first, which needs permission to add contacts and room under the account's contact limit, and the new contact stays even if the add then fails. Name the automation with automation, one id, or with automations, up to 25 ids. Every automation named must be active: one that is not refuses the whole call with 422 before any contact is created or added. An automation or contact id that does not exist answers 422, not 404. With automation the response contactAutomation is the contact's run in the automation, with its id and status: 1 while in progress, 2 once ended. With automations each automation is added on its own and the response carries contactAutomations, the runs created, with meta.succeeded and meta.failed listing the automation ids that did and did not take the contact; an automation the contact could not enter, such as one without a start step, is reported under failed while the others still succeed. The call answers 201 when at least one automation took the contact, 422 when none did, or 403 when the rate limit refused every one of them.","operationId":"create-new-contactautomation","x-canonical-resource":"contactAutomations","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactAutomation":{"description":"Which contact to add, and to which automations.","properties":{"contact":{"oneOf":[{"type":"integer","format":"int32"},{"type":"string"}],"description":"Id of the contact to add. Send this or contact_email. An existing contact's email address or 32-character hash is also accepted here; unlike contact_email, this never creates a contact, and an unknown value answers 422."},"contact_email":{"type":"string","format":"email","description":"Email address of the contact to add, instead of contact. When no contact has this address one is created with it first, which needs permission to add contacts and counts against the account's contact limit; the new contact stays even if the add then fails."},"automation":{"type":"integer","description":"Id of the automation to add the contact to. Send this or automations.","format":"int32"},"automations":{"type":"array","items":{"type":"integer","format":"int32"},"minItems":1,"maxItems":25,"description":"Ids of up to 25 automations to add the contact to in one call, instead of automation. Each is added on its own; meta.succeeded and meta.failed in the response list the ids that did and did not take the contact."}},"type":"object","allOf":[{"anyOf":[{"required":["contact"]},{"required":["contact_email"]}]},{"anyOf":[{"required":["automation"]},{"required":["automations"]}]}],"additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"contactAutomation":{"contact":"117","automation":"42"}}},"Request Example (by email, several automations)":{"value":{"contactAutomation":{"contact_email":"sam@example.com","automations":[42,43]}}}}}}},"responses":{"201":{"description":"Created. One contactAutomation when the request named automation; contactAutomations plus meta when it named automations.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2018-08-06T16:26:06-05:00\",\n            \"email\": \"johndoe@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"\",\n            \"lastName\": \"\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"2130706433\",\n            \"ua\": null,\n            \"hash\": \"054aa0acede49e07a844420c879b3c30\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": null,\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2018-09-21 12:04:40\",\n            \"updated_utc_timestamp\": \"2018-09-21 12:04:40\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/64/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/64/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/64/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/64/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/64/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/64/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/64/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/64/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/:version/contacts/64/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/64/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/64/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/64/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/64/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/64/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/64/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/64/scoreValues\"\n            },\n            \"id\": \"64\",\n            \"organization\": null\n        }\n    ],\n    \"contactAutomation\": {\n        \"contact\": \"64\",\n        \"seriesid\": \"2\",\n        \"startid\": 0,\n        \"status\": 1,\n        \"lastblock\": \"4\",\n        \"completedElements\": 1,\n        \"totalElements\": 2,\n        \"completed\": 0,\n        \"completeValue\": 50,\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/automation\",\n            \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/contact\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/contactGoals\"\n        },\n        \"id\": \"3\",\n        \"automation\": \"2\"\n    }\n}"},"Result (automations array)":{"value":"{\n    \"contactAutomations\": [\n        {\n            \"contact\": \"64\",\n            \"seriesid\": \"2\",\n            \"startid\": 0,\n            \"status\": 1,\n            \"lastblock\": \"4\",\n            \"completedElements\": 1,\n            \"totalElements\": 2,\n            \"completed\": 0,\n            \"completeValue\": 50,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/3/contactGoals\"\n            },\n            \"id\": \"3\",\n            \"automation\": \"2\"\n        },\n        {\n            \"contact\": \"64\",\n            \"seriesid\": \"3\",\n            \"startid\": 0,\n            \"status\": 1,\n            \"lastblock\": \"7\",\n            \"completedElements\": 0,\n            \"totalElements\": 3,\n            \"completed\": 0,\n            \"completeValue\": 0,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/4/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/4/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/4/contactGoals\"\n            },\n            \"id\": \"4\",\n            \"automation\": \"3\"\n        }\n    ],\n    \"meta\": {\n        \"succeeded\": [\n            2,\n            3\n        ],\n        \"failed\": [\n            5\n        ]\n    }\n}"}},"schema":{"oneOf":[{"title":"single automation","type":"object","properties":{"contacts":{"description":"The contact the run belongs to, when the response includes it.","type":"array","items":{"type":"object","properties":{"cdate":{"description":"When the contact was created, in ISO 8601 with the account's UTC offset. Null when not recorded.","type":["string","null"],"example":"2018-08-06T16:26:06-05:00"},"email":{"description":"The contact's email address. Null when the contact was created without one.","type":["string","null"],"example":"johndoe@example.com"},"phone":{"description":"The contact's phone number. Empty when not set.","type":"string","example":""},"firstName":{"description":"The contact's first name. Empty when not set.","type":"string","example":""},"lastName":{"description":"The contact's last name. Empty when not set.","type":"string","example":""},"orgid":{"description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none. The current account link is accountContacts.","type":"string","example":"0"},"segmentio_id":{"description":"Id of the contact in the Segment integration. Empty when the contact did not come from Segment.","type":"string","example":""},"bounced_hard":{"description":"Number of hard bounces recorded for the contact. Some update paths reset it to \"0\" when the email address changes.","type":"string","example":"0"},"bounced_soft":{"description":"Number of soft bounces recorded for the contact.","type":"string","example":"0"},"bounced_date":{"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced.","type":["string","null"]},"ip":{"description":"IPv4 address the contact was added from, stored as a whole number in the form PHP's ip2long produces. \"0\" when not recorded.","type":"string","example":"2130706433"},"ua":{"description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded.","type":["string","null"]},"hash":{"description":"A 32-character identifier for the contact. Set by the database when the contact is created and replaced by the database when the email address changes. Some older creation paths derive it from the id and email address.","type":"string","example":"054aa0acede49e07a844420c879b3c30"},"socialdata_lastcheck":{"description":"When social profile data was last looked up for the contact, as YYYY-MM-DD HH:MM:SS. Null when never looked up.","type":["string","null"]},"email_local":{"description":"The part of the email address before the @ sign. Not maintained by current code, so usually empty.","type":"string","example":""},"email_domain":{"description":"The part of the email address after the @ sign. Set by the database when the contact is inserted and whenever the email address changes.","type":"string","example":""},"sentcnt":{"description":"Number of campaigns that have been sent to the contact.","type":"string","example":"0"},"rating_tstamp":{"description":"Date the contact's engagement rating last changed, as YYYY-MM-DD. Null when never rated. The rating itself is not returned.","type":["string","null"]},"gravatar":{"description":"Gravatar lookup status. \"0\" not looked up yet, \"1\" looked up and no image found, \"2\" looked up and an image found, \"3\" use the image from the contact's appended social profile data (plusAppend) instead.","type":"string","example":"0"},"deleted":{"description":"\"1\" when the contact has been soft-deleted. A deleted contact is moved to the archive, so contacts returned here normally have \"0\".","type":"string","example":"0"},"anonymized":{"description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise.","type":"string","example":"0"},"adate":{"description":"When activity was last generated for the contact, in ISO 8601 with the account's UTC offset. Null when activity has never been generated.","type":["string","null"]},"udate":{"description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Moves on any save of the record, including saves that change nothing, and, through database triggers, on list, tag, custom field, score, note and task changes.","type":["string","null"]},"edate":{"description":"Watermark for email activity generation: the contact's stored emails have been turned into activities up to this time. In ISO 8601 with the account's UTC offset. Null when email activity has never been generated for the contact.","type":["string","null"]},"deleted_at":{"description":"When the contact was soft-deleted, as YYYY-MM-DD HH:MM:SS. Null for a contact that has not been deleted.","type":["string","null"]},"created_utc_timestamp":{"description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS. Set by the database.","type":"string","example":"2018-09-21 12:04:40"},"updated_utc_timestamp":{"description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Set by the database on every change and by the application on save. Despite the name it is not in UTC; it moves on every change to the row, including counters such as sentcnt that do not move udate.","type":"string","example":"2018-09-21 12:04:40"},"links":{"description":"URLs of the reads for the contact's related records.","type":"object","properties":{"bounceLogs":{"description":"URL of GET /contacts/{id}/bounceLogs.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/bounceLogs"},"contactAutomations":{"description":"URL of GET /contacts/{id}/contactAutomations.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactAutomations"},"contactData":{"description":"URL of GET /contacts/{id}/contactData.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactData"},"contactGoals":{"description":"URL of GET /contacts/{id}/contactGoals.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactGoals"},"contactLists":{"description":"URL of GET /contacts/{id}/contactLists.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactLists"},"contactLogs":{"description":"URL of GET /contacts/{id}/contactLogs.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactLogs"},"contactTags":{"description":"URL of GET /contacts/{id}/contactTags.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactTags"},"contactDeals":{"description":"URL of GET /contacts/{id}/contactDeals.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/contactDeals"},"deals":{"description":"URL of GET /contacts/{id}/deals.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/deals"},"fieldValues":{"description":"URL of GET /contacts/{id}/fieldValues.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/fieldValues"},"geoIps":{"description":"URL of GET /contacts/{id}/geoIps.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/geoIps"},"notes":{"description":"URL of GET /contacts/{id}/notes.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/notes"},"organization":{"description":"URL of GET /contacts/{id}/organization.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/organization"},"plusAppend":{"description":"URL of GET /contacts/{id}/plusAppend.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/plusAppend"},"trackingLogs":{"description":"URL of GET /contacts/{id}/trackingLogs.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/trackingLogs"},"scoreValues":{"description":"URL of GET /contacts/{id}/scoreValues.","type":"string","example":"https://:account.api-us1.com/api/:version/contacts/64/scoreValues"}}},"id":{"description":"Id of the contact.","type":"string","example":"64"},"organization":{"description":"Id of the account the contact belongs to through the legacy account link. The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts.","type":["string","null"]}}}},"contactAutomation":{"description":"The run that was created.","type":"object","properties":{"contact":{"description":"Id of the contact on this run.","type":"string","example":"64"},"seriesid":{"description":"Id of the automation. The same value as automation.","type":"string","example":"2"},"startid":{"description":"Id of the start trigger that added the contact. 0 when the contact was added another way, such as through this API or by hand.","type":"integer","example":0,"default":0},"status":{"description":"1 while the contact is moving through the automation, 2 once the run has ended.","type":"integer","example":1,"default":0},"batchid":{"description":"Where the run is in processing. A new run carries a processing id, or paused when the automation is paused and holds new entries.","type":["string","null"]},"lastblock":{"description":"Id of the last step (automation block) the contact reached.","type":"string","example":"4"},"in_als":{"description":"Internal flag for where the run's history is stored. Not useful to API callers.","type":["integer","string","null"]},"completedElements":{"description":"Number of steps counted as done, up to and including the last step reached, worked out from the automation's current layout. 0 when the last step reached has since been removed.","type":"integer","example":1},"totalElements":{"description":"Number of steps in the automation, counting every branch.","type":"integer","example":2},"completed":{"description":"1 when the run has ended (status 2), otherwise 0.","type":"integer","example":0,"default":0},"completeValue":{"description":"Percent of the automation done. 100 once the run has ended or when the automation has no steps, otherwise completedElements out of totalElements, rounded.","type":"number","example":50,"default":0},"links":{"description":"URLs of the reads for the run's related records.","type":"object","properties":{"automation":{"description":"URL of the automation this run is in.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/automation"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/contact"},"contactGoals":{"description":"URL of the goals the contact reached in this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/contactGoals"},"automationLogs":{"description":"URL of the history entries recorded for this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/automationLogs"},"subscriberSeriesEnd":{"description":"URL of the record of how the run ended.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/subscriberSeriesEnd"}}},"id":{"description":"Id of the run (contactAutomation).","type":"string","example":"3"},"automation":{"description":"Id of the automation.","type":"string","example":"2"}}}},"required":["contactAutomation"]},{"title":"automations array","type":"object","properties":{"contactAutomations":{"type":"array","description":"One run per automation the contact was added to.","items":{"type":"object","properties":{"contact":{"description":"Id of the contact on this run.","type":"string","example":"64"},"seriesid":{"description":"Id of the automation. The same value as automation.","type":"string","example":"2"},"startid":{"description":"Id of the start trigger that added the contact. 0 when the contact was added another way, such as through this API or by hand.","type":"integer","example":0,"default":0},"status":{"description":"1 while the contact is moving through the automation, 2 once the run has ended.","type":"integer","example":1,"default":0},"batchid":{"description":"Where the run is in processing. A new run carries a processing id, or paused when the automation is paused and holds new entries.","type":["string","null"]},"lastblock":{"description":"Id of the last step (automation block) the contact reached.","type":"string","example":"4"},"in_als":{"description":"Internal flag for where the run's history is stored. Not useful to API callers.","type":["integer","string","null"]},"completedElements":{"description":"Number of steps counted as done, up to and including the last step reached, worked out from the automation's current layout. 0 when the last step reached has since been removed.","type":"integer","example":1},"totalElements":{"description":"Number of steps in the automation, counting every branch.","type":"integer","example":2},"completed":{"description":"1 when the run has ended (status 2), otherwise 0.","type":"integer","example":0,"default":0},"completeValue":{"description":"Percent of the automation done. 100 once the run has ended or when the automation has no steps, otherwise completedElements out of totalElements, rounded.","type":"number","example":50,"default":0},"links":{"description":"URLs of the reads for the run's related records.","type":"object","properties":{"automation":{"description":"URL of the automation this run is in.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/automation"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/contact"},"contactGoals":{"description":"URL of the goals the contact reached in this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/contactGoals"},"automationLogs":{"description":"URL of the history entries recorded for this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/automationLogs"},"subscriberSeriesEnd":{"description":"URL of the record of how the run ended.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/3/subscriberSeriesEnd"}}},"id":{"description":"Id of the run (contactAutomation).","type":"string","example":"3"},"automation":{"description":"Id of the automation.","type":"string","example":"2"}}}},"meta":{"description":"Which automations took the contact.","type":"object","properties":{"succeeded":{"type":"array","items":{"type":"integer"},"description":"Ids of the automations the contact was added to."},"failed":{"type":"array","items":{"type":"integer"},"description":"Ids of the automations the contact could not enter, such as one without a start step."}}}},"required":["contactAutomations","meta"]}]}}}},"400":{"description":"Neither contact nor contact_email was sent, contact_email is not an email address, neither automation nor automations was sent, automations is empty or names more than 25 automations, or an automation id is not a positive integer."},"403":{"description":"The API user may not edit contacts, or this contact has already been added to this automation 100 times in the last 24 hours.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"This would exceed the rate limit of this endpoint, which is 100 calls per subscriber/series over 24 hours.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer"},"title":{"description":"The HTTP status text.","type":"string"},"detail":{"description":"What went wrong.","type":"string"}}}}}}}}},"422":{"description":"An automation named in the request is not active (draft, inactive, or paused), which refuses the whole call; no automation named has a start step; or an automation or contact id does not exist."}},"deprecated":false},"get":{"summary":"List all automations a contact is in","description":"Lists contacts' runs through automations, one entry per time a contact entered an automation, 20 per page by default and at most 100 per page (limit). Without a filter it covers every run in the account; users outside the Admin group only see runs of contacts on a list their group may access, or on no list. Each entry carries the run's status and progress. Runs that have ended may also be described in subscriberSeriesEnds. For one contact's runs, use GET /contacts/{id}/contactAutomations. This call does not refuse unknown filters or orderings; it ignores them.","operationId":"list-all-contact-automations","x-canonical-resource":"contactAutomations","responses":{"200":{"description":"The runs on this page.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomations\": [\n        {\n            \"contact\": \"10003\",\n            \"seriesid\": \"1\",\n            \"startid\": \"0\",\n            \"status\": \"2\",\n            \"batchid\": null,\n            \"adddate\": \"2018-11-16T02:32:33-06:00\",\n            \"remdate\": \"2018-11-16T02:32:33-06:00\",\n            \"timespan\": \"0\",\n            \"lastblock\": \"1\",\n            \"lastlogid\": \"0\",\n            \"lastdate\": \"2018-11-16T02:32:33-06:00\",\n            \"in_als\": null,\n            \"completedElements\": 0,\n            \"totalElements\": 1,\n            \"completed\": 1,\n            \"completeValue\": 100,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/contactGoals\",\n                \"automationLogs\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/automationLogs\",\n                \"subscriberSeriesEnd\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/subscriberSeriesEnd\"\n            },\n            \"id\": \"1\",\n            \"automation\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 1,\n        \"showcase_stats\": []\n    }\n}"}},"schema":{"type":"object","properties":{"contactAutomations":{"description":"The runs on this page.","type":"array","items":{"type":"object","properties":{"contact":{"description":"Id of the contact on this run.","type":"string","example":"10003"},"seriesid":{"description":"Id of the automation. The same value as automation.","type":"string","example":"1"},"startid":{"description":"Id of the start trigger that added the contact. 0 when the contact was added another way, such as through this API or by hand.","type":"string","example":"0"},"status":{"description":"1 while the contact is moving through the automation, 2 once the run has ended.","type":"string","example":"2"},"batchid":{"description":"Where the run is in processing: null while waiting, otherwise a state such as queued, scheduled, paused, error or completed, or an id while a worker is processing it.","type":["string","null"]},"adddate":{"description":"When the contact entered the automation, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-11-16T02:32:33-06:00"},"remdate":{"description":"When the run ended, in ISO 8601 with the account's UTC offset. Null while the run is in progress.","type":["string","null"],"example":"2018-11-16T02:32:33-06:00"},"timespan":{"description":"Seconds from entering to the end of the run. Null while the run is in progress.","type":["string","null"],"example":"0"},"lastblock":{"description":"Id of the last step (automation block) the contact reached.","type":"string","example":"1"},"lastlogid":{"description":"Id of the last history entry recorded for this run. \"0\" when none has been recorded.","type":"string","example":"0"},"lastdate":{"description":"When the run last changed state, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-11-16T02:32:33-06:00"},"in_als":{"description":"Internal flag for where the run's history is stored. Not useful to API callers.","type":["string","null"]},"completedElements":{"description":"Number of steps counted as done, up to and including the last step reached, worked out from the automation's current layout. 0 when the last step reached has since been removed.","type":"integer","example":0},"totalElements":{"description":"Number of steps in the automation, counting every branch but not the start trigger or the else and split-group blocks.","type":"integer","example":1},"completed":{"description":"1 when the run has ended (status 2), otherwise 0.","type":"integer","example":1,"default":0},"completeValue":{"description":"Percent of the automation done. 100 once the run has ended or when the automation has no steps, otherwise completedElements out of totalElements, rounded.","type":"number","example":100,"default":0},"links":{"description":"URLs of the reads for the run's related records.","type":"object","properties":{"automation":{"description":"URL of the automation this run is in.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/automation"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/contact"},"contactGoals":{"description":"URL of the goals the contact reached in this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/contactGoals"},"automationLogs":{"description":"URL of the history entries recorded for this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/automationLogs"},"subscriberSeriesEnd":{"description":"URL of the record of how the run ended.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/subscriberSeriesEnd"}}},"id":{"description":"Id of the run (contactAutomation).","type":"string","example":"1"},"automation":{"description":"Id of the automation.","type":"string","example":"1"}}}},"meta":{"description":"About the whole result, not just this page.","type":"object","properties":{"total":{"description":"Number of runs that match. When the account has very many runs and no filter narrows the list, this can be an estimate; total_is_approximate then says so.","type":"integer","example":1},"total_is_approximate":{"description":"true when total is an estimate rather than an exact count. Only present on some accounts.","type":"boolean"},"showcase_stats":{"description":"Completion figures for the filtered runs: completion_time (average seconds to finish) and completion_rate (percent finished). An empty array unless the request filters by goal, tags, lists or time taken.","type":["array","object"]}}},"subscriberSeriesEnds":{"description":"How each run that has ended was ended, for runs on this page that have an end record.","type":"array","items":{"$ref":"#/components/schemas/SubscriberSeriesEnd"}}}}}}}},"deprecated":false},"delete":{"summary":"Remove a contact from an automation by contact and automation","description":"Removes the contact's active entry in the automation, identified by the contact (`contact` ID or `contact_email`) and the automation ID, without needing the contactAutomation ID. Only an active entry is removed; a completed entry is left as history. Use `DELETE /contactAutomations/{id}` when the contactAutomation ID is known.","operationId":"remove-a-contact-from-an-automation","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"automation","in":"query","description":"ID of the automation to remove the contact from","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"contact","in":"query","description":"ID of the contact. Required unless `contact_email` is given; ignored when `contact_email` is given.","schema":{"type":"integer","format":"int32"}},{"name":"contact_email","in":"query","description":"Email address of the contact. Takes precedence over `contact` when both are given.","schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"The run was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The API user does not have permission to edit contacts.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to edit a contact\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer","example":403},"title":{"description":"The HTTP status text.","type":"string","example":"Forbidden"},"detail":{"description":"What went wrong.","type":"string","example":"You do not have permission to edit a contact"}}}}}}}}},"404":{"description":"The contact, the automation, or an active entry of that contact in that automation does not exist.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\",\n            \"detail\": \"Contact automation not found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer","example":404},"title":{"description":"The HTTP status text.","type":"string","example":"Not Found"},"detail":{"description":"What went wrong.","type":"string","example":"Contact automation not found"}}}}}}}}},"422":{"description":"A required parameter is missing or invalid.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"The automation parameter is required.\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/automation\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer","example":422},"title":{"description":"The HTTP status text.","type":"string","example":"Invalid attribute"},"detail":{"description":"What went wrong.","type":"string","example":"The automation parameter is required."},"source":{"description":"Which request value is wrong.","type":"object","properties":{"pointer":{"description":"Path of the value in the request, such as /data/attributes/automation.","type":"string","example":"/data/attributes/automation"}}}}}}}}}}}},"deprecated":false}},"/contactAutomations/{id}":{"get":{"summary":"Retrieve an automation a contact is in","description":"Returns one run of a contact through an automation, with its status and progress. If the run has ended, subscriberSeriesEnds may say how. Users outside the Admin group can only read runs of contacts on a list their group may access, or on no list.","operationId":"retrieve-a-contactautomation","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The run.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomation\": {\n        \"contact\": \"110\",\n        \"seriesid\": \"2\",\n        \"startid\": \"0\",\n        \"status\": \"2\",\n        \"batchid\": null,\n        \"adddate\": \"2018-09-19T09:44:26-05:00\",\n        \"remdate\": \"2018-09-19T09:44:26-05:00\",\n        \"timespan\": \"0\",\n        \"lastblock\": \"5\",\n        \"lastlogid\": \"2\",\n        \"lastdate\": \"2018-09-19T09:44:26-05:00\",\n        \"in_als\": null,\n        \"completedElements\": 1,\n        \"totalElements\": 2,\n        \"completed\": 1,\n        \"completeValue\": 100,\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/automation\",\n            \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/contact\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/contactGoals\",\n            \"automationLogs\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/automationLogs\",\n            \"subscriberSeriesEnd\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/subscriberSeriesEnd\"\n        },\n        \"id\": \"2\",\n        \"automation\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactAutomation":{"description":"The run.","type":"object","properties":{"contact":{"description":"Id of the contact on this run.","type":"string","example":"110"},"seriesid":{"description":"Id of the automation. The same value as automation.","type":"string","example":"2"},"startid":{"description":"Id of the start trigger that added the contact. 0 when the contact was added another way, such as through this API or by hand.","type":"string","example":"0"},"status":{"description":"1 while the contact is moving through the automation, 2 once the run has ended.","type":"string","example":"2"},"batchid":{"description":"Where the run is in processing: null while waiting, otherwise a state such as queued, scheduled, paused, error or completed, or an id while a worker is processing it.","type":["string","null"]},"adddate":{"description":"When the contact entered the automation, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"remdate":{"description":"When the run ended, in ISO 8601 with the account's UTC offset. Null while the run is in progress.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"timespan":{"description":"Seconds from entering to the end of the run. Null while the run is in progress.","type":["string","null"],"example":"0"},"lastblock":{"description":"Id of the last step (automation block) the contact reached.","type":"string","example":"5"},"lastlogid":{"description":"Id of the last history entry recorded for this run. \"0\" when none has been recorded.","type":"string","example":"2"},"lastdate":{"description":"When the run last changed state, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"in_als":{"description":"Internal flag for where the run's history is stored. Not useful to API callers.","type":["string","null"]},"completedElements":{"description":"Number of steps counted as done, up to and including the last step reached, worked out from the automation's current layout. 0 when the last step reached has since been removed.","type":"integer","example":1},"totalElements":{"description":"Number of steps in the automation, counting every branch but not the start trigger or the else and split-group blocks.","type":"integer","example":2},"completed":{"description":"1 when the run has ended (status 2), otherwise 0.","type":"integer","example":1,"default":0},"completeValue":{"description":"Percent of the automation done. 100 once the run has ended or when the automation has no steps, otherwise completedElements out of totalElements, rounded.","type":"number","example":100,"default":0},"links":{"description":"URLs of the reads for the run's related records.","type":"object","properties":{"automation":{"description":"URL of the automation this run is in.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/automation"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/contact"},"contactGoals":{"description":"URL of the goals the contact reached in this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/contactGoals"},"automationLogs":{"description":"URL of the history entries recorded for this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/automationLogs"},"subscriberSeriesEnd":{"description":"URL of the record of how the run ended.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/subscriberSeriesEnd"}}},"id":{"description":"Id of the run (contactAutomation).","type":"string","example":"2"},"automation":{"description":"Id of the automation.","type":"string","example":"2"}}},"subscriberSeriesEnds":{"description":"How the run was ended. Present only when the run has an end record.","type":"array","items":{"$ref":"#/components/schemas/SubscriberSeriesEnd"}}}}}}},"403":{"description":"The caller is outside the Admin group and the contact is only on lists their group may not access. An id that does not exist also gets this answer for those callers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationError"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to this ContactAutomation"}]}}}},"404":{"description":"No run has this id. Callers in the Admin group get this; others get 403.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberSeries with id 3\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which id was not found.","type":"string","example":"No Result found for SubscriberSeries with id 3"}}}}}}},"deprecated":false},"delete":{"summary":"Remove a contact from an automation","description":"Deletes a contact's run through an automation, so the contact no longer shows as being in it. The run's start records go with it. This call does not record an end or send a cancel for waits the contact is scheduled for. To stop a run and keep it as history, use PUT /contactAutomations/{id} with status 2 and completed true instead. Needs permission to edit contacts.","operationId":"delete-a-contactautomation","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The run was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The caller does not have permission to edit contacts. Rarely, the same status is used when the run could not be deleted; that answer has a plain-text body, Failed to delete contactAutomation, even though it is sent as application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationError"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to edit a contact"}]}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"description":"Says which id was not found.","type":"string","example":"No Result found for SubscriberSeries with id 3"}}}}}}},"deprecated":false},"put":{"summary":"Update a contact automation","description":"Ends a contact's run through an automation. `status` is the only writable field. Sending `completed: true` also cancels any wait the contact is scheduled for in that automation and records the end as cancelled through the API; send it together with `status: 2`. PATCH /contactAutomations/{id} is also accepted and does the same, with the same body and responses.","operationId":"update-a-contactautomation","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactAutomation":{"description":"The change to make.","type":"object","properties":{"status":{"type":"integer","description":"1 = active, 2 = completed","enum":[1,2],"format":"int32"},"completed":{"type":"boolean","description":"When true, cancels pending waits for this contact in the automation and records the end. Not stored; send with `status: 2`."}},"required":["status"]}},"additionalProperties":false},"examples":{"Request Example":{"value":{"contactAutomation":{"status":2,"completed":true}}}}}}},"responses":{"200":{"description":"The run after the change.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomation\": {\n        \"contact\": \"110\",\n        \"seriesid\": \"2\",\n        \"startid\": \"0\",\n        \"status\": 2,\n        \"batchid\": \"completed\",\n        \"adddate\": \"2018-09-19T09:44:26-05:00\",\n        \"remdate\": \"2018-09-19T10:02:11-05:00\",\n        \"timespan\": 1065,\n        \"lastblock\": \"5\",\n        \"lastlogid\": \"2\",\n        \"lastdate\": \"2018-09-19T09:44:26-05:00\",\n        \"in_als\": \"3\",\n        \"completedElements\": 1,\n        \"totalElements\": 2,\n        \"completed\": 1,\n        \"completeValue\": 100,\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/automation\",\n            \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/contact\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/contactGoals\",\n            \"automationLogs\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/automationLogs\",\n            \"subscriberSeriesEnd\": \"https://:account.api-us1.com/api/:version/contactAutomations/2/subscriberSeriesEnd\"\n        },\n        \"id\": \"2\",\n        \"automation\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactAutomation":{"description":"The run after the change.","type":"object","properties":{"contact":{"description":"Id of the contact on this run.","type":"string","example":"110"},"seriesid":{"description":"Id of the automation. The same value as automation.","type":"string","example":"2"},"startid":{"description":"Id of the start trigger that added the contact. 0 when the contact was added another way, such as through this API or by hand.","type":"string","example":"0"},"status":{"description":"1 while the contact is moving through the automation, 2 once the run has ended. Echoes the value sent, so it may be a number.","type":["integer","string"],"example":2},"batchid":{"description":"Where the run is in processing: null while waiting, otherwise a state such as queued, scheduled, paused, error or completed, or an id while a worker is processing it.","type":["string","null"]},"adddate":{"description":"When the contact entered the automation, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"remdate":{"description":"When the run ended, in ISO 8601 with the account's UTC offset. Null while the run is in progress.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"timespan":{"description":"Seconds from entering to the end of the run. Null while the run is in progress. A number when this call ended the run.","type":["integer","string","null"],"example":1065},"lastblock":{"description":"Id of the last step (automation block) the contact reached.","type":"string","example":"5"},"lastlogid":{"description":"Id of the last history entry recorded for this run. \"0\" when none has been recorded.","type":"string","example":"2"},"lastdate":{"description":"When the contact last moved through a step or processing state, in ISO 8601 with the account's UTC offset.","type":["string","null"],"example":"2018-09-19T09:44:26-05:00"},"in_als":{"description":"Internal flag for where the run's history is stored. Not useful to API callers.","type":["string","null"]},"completedElements":{"description":"Number of steps counted as done, up to and including the last step reached, worked out from the automation's current layout. 0 when the last step reached has since been removed.","type":"integer","example":1},"totalElements":{"description":"Number of steps in the automation, counting every branch.","type":"integer","example":2},"completed":{"description":"1 when the run has ended (status 2), otherwise 0.","type":"integer","example":1,"default":0},"completeValue":{"description":"Percent of the automation done. 100 once the run has ended or when the automation has no steps, otherwise completedElements out of totalElements, rounded.","type":"number","example":100,"default":0},"links":{"description":"URLs of the reads for the run's related records.","type":"object","properties":{"automation":{"description":"URL of the automation this run is in.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/automation"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/contact"},"contactGoals":{"description":"URL of the goals the contact reached in this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/contactGoals"},"automationLogs":{"description":"URL of the history entries recorded for this run.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/automationLogs"},"subscriberSeriesEnd":{"description":"URL of the record of how the run ended.","type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/2/subscriberSeriesEnd"}}},"id":{"description":"Id of the run (contactAutomation).","type":"string","example":"2"},"automation":{"description":"Id of the automation.","type":"string","example":"2"}}},"contacts":{"description":"The contact the run belongs to, in the same shape as contacts in the POST /contactAutomations 201 response. Present when saving the run loaded the contact.","type":"array","items":{"type":"object"}}}}}}},"400":{"description":"The body is a non-empty JSON list or a non-empty single value instead of an object (an empty body, 0, false or an empty string is read as an empty object). Checked before anything else.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 400,\n            \"title\": \"Bad Request\",\n            \"detail\": \"Request body must be a JSON object, array given.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer"},"title":{"description":"The HTTP status text.","type":"string"},"detail":{"description":"What went wrong.","type":"string"}}}}}}}}},"403":{"description":"The API user does not have permission to edit contacts.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to edit a contact\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status code.","type":"integer","example":403},"title":{"description":"The HTTP status text.","type":"string","example":"Forbidden"},"detail":{"description":"What went wrong.","type":"string","example":"You do not have permission to edit a contact"}}}}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberSeries with id 3\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which id was not found.","type":"string","example":"No Result found for SubscriberSeries with id 3"}}}}}},"422":{"description":"The change is not allowed: a run that has ended (status 2) cannot be set back to 1. When completed was true, the cancel of waits and the end record have already been made by then.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"Can't change status once Completed.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/status\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"The errors. There is one.","type":"array","items":{"type":"object","properties":{"title":{"description":"What went wrong.","type":"string"},"detail":{"description":"Empty.","type":"string"},"code":{"description":"Kind of error, here field_invalid.","type":"string"},"error":{"description":"Empty.","type":"string"},"source":{"description":"Which value is wrong.","type":"object","properties":{"pointer":{"description":"Path of the value, here /data/attributes/status.","type":"string"}}}}}}}}}}}},"deprecated":false}},"/contactAutomations/{id}/automation":{"get":{"summary":"Retrieve the automation of a contact automation","description":"Returns the automation this run is in, under automation. The body is an empty object {} when that automation no longer exists. Returns 404 if the run does not exist.","operationId":"retrieve-contactautomation-automation","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation (the run)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The automation under automation, or an empty object ({}) when it no longer exists.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"automation\": {\n        \"name\": \"Welcome series\",\n        \"cdate\": \"2026-01-14T09:12:44-06:00\",\n        \"mdate\": \"2026-01-15T10:02:11-06:00\",\n        \"userid\": \"1\",\n        \"status\": \"1\",\n        \"entered\": \"12\",\n        \"exited\": \"4\",\n        \"hidden\": \"0\",\n        \"links\": {\n            \"campaigns\": \"https://:account.api-us1.com/api/3/automations/2/campaigns\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/3/automations/2/contactGoals\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/3/automations/2/contactAutomations\",\n            \"blocks\": \"https://:account.api-us1.com/api/3/automations/2/blocks\",\n            \"goals\": \"https://:account.api-us1.com/api/3/automations/2/goals\",\n            \"sms\": \"https://:account.api-us1.com/api/3/automations/2/sms\",\n            \"sitemessages\": \"https://:account.api-us1.com/api/3/automations/2/sitemessages\",\n            \"triggers\": \"https://:account.api-us1.com/api/3/automations/2/triggers\"\n        },\n        \"id\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"automation":{"description":"The automation: every column of the automation, its links and its id. The main fields are listed here.","type":"object","properties":{"name":{"description":"Name of the automation.","type":"string"},"cdate":{"description":"When the automation was created. Null when not set.","type":["string","null"]},"status":{"description":"0 draft, 1 active, 2 inactive, 3 paused.","type":"string"},"links":{"description":"URLs of the automation's related reads.","type":"object"},"id":{"description":"Id of the automation. Use it with GET /automations/{id}.","type":"string"}}}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationNotFound"}}}}}}},"/contactAutomations/{id}/automationLogs":{"get":{"summary":"List the history of a contact automation","description":"Returns the history entries kept for this run, under contactAutomationLogs. For most runs this is not the full step history: only some kinds of steps, such as waits, goals and sends, keep an entry here. For the full step history, use GET /automations/{seriesId}/contactAutomations/{contactAutomationId}/steps. The list is not paged. The order is not guaranteed. Returns 404 if the run does not exist.","operationId":"list-contactautomation-automation-logs","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation (the run)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The history entries under contactAutomationLogs; an empty list when none are recorded.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomationLogs\": [\n        {\n            \"seriesid\": \"2\",\n            \"blockid\": \"5\",\n            \"subscriberid\": \"110\",\n            \"contactseriesid\": \"2\",\n            \"tstamp\": \"2026-01-14T09:12:44-06:00\",\n            \"res\": \"1\",\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/3/contactAutomationLogs/31/automation\",\n                \"block\": \"https://:account.api-us1.com/api/3/contactAutomationLogs/31/block\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactAutomationLogs/31/contact\",\n                \"contactAutomation\": \"https://:account.api-us1.com/api/3/contactAutomationLogs/31/contactAutomation\"\n            },\n            \"id\": \"31\",\n            \"automation\": \"2\",\n            \"block\": \"5\",\n            \"contact\": \"110\",\n            \"contactAutomation\": \"2\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contactAutomationLogs":{"description":"The history entries kept for this run. For most runs, only some kinds of steps have an entry.","type":"array","items":{"$ref":"#/components/schemas/ContactAutomationLog"}}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationNotFound"}}}}}}},"/contactAutomations/{id}/contact":{"get":{"summary":"Retrieve the contact of a contact automation","description":"Returns the contact on this run, under contact. The body is an empty object {} when the contact no longer exists. Users outside the Admin group also get {} when the contact is only on lists their group may not access. Returns 404 if the run does not exist.","operationId":"retrieve-contactautomation-contact","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation (the run)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact under contact, or an empty object ({}).","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contact\": {\n        \"cdate\": \"2026-01-14T09:10:02-06:00\",\n        \"email\": \"sam@example.com\",\n        \"phone\": \"\",\n        \"firstName\": \"Sam\",\n        \"lastName\": \"Example\",\n        \"orgid\": \"0\",\n        \"deleted\": \"0\",\n        \"udate\": \"2026-01-14T09:10:02-06:00\",\n        \"links\": {\n            \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/110/contactGoals\"\n        },\n        \"id\": \"110\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contact":{"description":"The contact, in the same shape as contact in GET /contacts/{id}, where the full record is documented. The main fields are listed here. Only the contact itself comes back; none of the arrays that GET /contacts/{id} adds beside it.","type":"object","properties":{"email":{"description":"Email address of the contact.","type":"string"},"firstName":{"description":"First name.","type":"string"},"lastName":{"description":"Last name.","type":"string"},"links":{"description":"URLs of the contact's related reads.","type":"object"},"id":{"description":"Id of the contact.","type":"string"}}}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationNotFound"}}}}}}},"/contactAutomations/{id}/contactGoals":{"get":{"summary":"List the goals reached in a contact automation","description":"Returns the automation goals the contact reached in this run, under contactGoals. The list is not paged. The order is not guaranteed. Returns 404 if the run does not exist.","operationId":"list-contactautomation-contact-goals","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation (the run)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The goals under contactGoals; an empty list when the contact reached none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactGoals\": [\n        {\n            \"goalid\": \"4\",\n            \"seriesid\": \"2\",\n            \"subscriberid\": \"110\",\n            \"subscriberseriesid\": \"2\",\n            \"timespan\": \"3600\",\n            \"tstamp\": \"2026-01-14T10:12:44-06:00\",\n            \"links\": {\n                \"goal\": \"https://:account.api-us1.com/api/3/contactGoals/3/goal\",\n                \"automation\": \"https://:account.api-us1.com/api/3/contactGoals/3/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactGoals/3/contact\",\n                \"contactAutomation\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactAutomation\",\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalLists\",\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalTags\"\n            },\n            \"id\": \"3\",\n            \"goal\": \"4\",\n            \"automation\": \"2\",\n            \"contact\": \"110\",\n            \"contactAutomation\": \"2\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contactGoals":{"description":"One entry per goal the contact reached in this run.","type":"array","items":{"$ref":"#/components/schemas/ContactAutomationGoal"}}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationNotFound"}}}}}}},"/contactAutomations/{id}/subscriberSeriesEnd":{"get":{"summary":"Retrieve how a contact automation ended","description":"Returns the record of how this run ended, under subscriberSeriesEnd. The body is an empty object {} when the run has no end record, for example while it is in progress. When a run has more than one end record, one of them is returned. Returns 404 if the run does not exist.","operationId":"retrieve-contactautomation-end","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contactAutomation (the run)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The end record under subscriberSeriesEnd, or an empty object ({}) when there is none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"subscriberSeriesEnd\": {\n        \"subscriber_series_id\": \"2\",\n        \"cause\": \"api_cancel_automation\",\n        \"context\": \"null\",\n        \"created_timestamp\": \"2026-01-15 10:02:11\",\n        \"links\": {\n            \"subscriberSeries\": \"https://:account.api-us1.com/api/3/subscriberSeriesEnds/7/subscriberSeries\"\n        },\n        \"id\": \"7\",\n        \"subscriberSeries\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"subscriberSeriesEnd":{"$ref":"#/components/schemas/SubscriberSeriesEnd"}}}}}},"404":{"description":"No run has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAutomationNotFound"}}}}}}},"/contactConversionPoints":{"get":{"summary":"List all contact conversion points","description":"A contact conversion point is one touchpoint: something a contact did or received before converting, such as an email open, a link click, a delivered SMS or a site visit. Revenue from the conversion is attributed to these touchpoints. The app writes them when a contact converts, from the contact's recent activity. Filter by contact or type. Without an order, points come in no guaranteed order. Page with limit and offset, or fetch specific points with ids. Returns 403 when the account does not have Attribution.","operationId":"list-all-contact-conversion-points","x-canonical-resource":"conversion","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Return only points for this contact id. Exact match.","schema":{"type":"integer"}},{"name":"filters[type]","in":"query","description":"Return only points of this type, such as LinkData. Exact match.","schema":{"type":"string"}},{"name":"orders[subscriberid]","in":"query","description":"Sort by contact id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[tstamp]","in":"query","description":"Sort by time. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limit","in":"query","description":"Number of points to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of points to skip. Use with limit to page through the points.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated point ids to return. When set, only those points are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of points under contactConversionPoints, with the number of matching points in meta.total. contactConversionPoints is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoints":{"type":"array","description":"The points on this page.","items":{"$ref":"#/components/schemas/ContactConversionPoint"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching points, before limit and offset."}}}}},"examples":{"Result":{"value":{"contactConversionPoints":[{"contact":"6199","type":"LinkData","relid":"8812","pointdata":{"event":{"type":"EMAIL_LINK_CLICK"},"revenue_generator":{"revenue_generator_type":"Campaign","revenue_generator_id":"27"}},"tstamp":"2026-09-01T14:03:12-05:00","links":{"contact":"https://example.api-us1.com/api/3/contactConversionPoints/15/contact","attributions":"https://example.api-us1.com/api/3/contactConversionPoints/15/attributions"},"id":"15"}],"meta":{"total":1}}}}}}},"403":{"$ref":"#/components/responses/AttributionNotEnabled"}}},"post":{"summary":"Create a contact conversion point","description":"Creates one point. The fields are saved as sent, without checks, so any contact id and any type are accepted. The time is set to now. The response repeats the values as sent and leaves out fields that were not sent. true and false are turned into 1 and 0 first. The stored value can still differ, for example when a text relid is saved as 0. pointdata is {} when not sent. A body without contactConversionPoint still creates a point, with contact 0, an empty type and relid 0. Returns 400 when the body is not a JSON object, and 403 when the account does not have Attribution. Send only the fields listed in the body. A body copied from a read is not saved, because it has links. A value of contact, type or relid that is an object or a list is not saved either. Internal: the app writes points itself when a contact converts.","operationId":"create-a-contact-conversion-point","x-canonical-resource":"conversion","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoint":{"$ref":"#/components/schemas/ContactConversionPointFields"}}},"example":{"contactConversionPoint":{"contact":"6199","type":"LinkData","relid":"8812","pointdata":{"event":{"type":"EMAIL_LINK_CLICK"},"revenue_generator":{"revenue_generator_type":"Campaign","revenue_generator_id":"27"}}}}}}},"responses":{"201":{"description":"The new point under contactConversionPoint.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoint":{"$ref":"#/components/schemas/ContactConversionPointSaved"}}},"example":{"contactConversionPoint":{"pointdata":{"event":{"type":"EMAIL_LINK_CLICK"},"revenue_generator":{"revenue_generator_type":"Campaign","revenue_generator_id":"27"}},"type":"LinkData","relid":"8812","contact":"6199","tstamp":"2026-09-01T14:03:12-05:00","links":{"contact":"https://example.api-us1.com/api/3/contactConversionPoints/15/contact","attributions":"https://example.api-us1.com/api/3/contactConversionPoints/15/attributions"},"id":"15"}}}}},"400":{"$ref":"#/components/responses/ContactConversionPointBadBody"},"403":{"$ref":"#/components/responses/AttributionNotEnabled"}}}},"/contactConversionPoints/{id}":{"get":{"summary":"Retrieve a contact conversion point","description":"A contact conversion point is one touchpoint: something a contact did or received before converting, such as an email open, a link click, a delivered SMS or a site visit. Revenue from the conversion is attributed to these touchpoints. The app writes them when a contact converts, from the contact's recent activity. Returns one point by its id. Returns 404 if no point has the id, and 403 when the account does not have Attribution.","operationId":"retrieve-a-contact-conversion-point","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionPointId"}],"responses":{"200":{"description":"The point under contactConversionPoint.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoint":{"$ref":"#/components/schemas/ContactConversionPoint"}}}}}},"403":{"$ref":"#/components/responses/AttributionNotEnabled"},"404":{"$ref":"#/components/responses/ContactConversionPointNotFound"}}},"put":{"summary":"Update a contact conversion point","description":"Updates one point. PATCH does the same. Only the fields sent change, and they are saved as sent, without checks. The time cannot be changed. The response holds the whole point: stored values come back as strings and sent values come back as sent. true and false are turned into 1 and 0 first. The stored value can still differ. Returns 404 if no point has the id, 400 when the body is not a JSON object, and 403 when the account does not have Attribution. Send only the fields listed in the body. A body copied from a read is not saved, because it has links. A value of contact, type or relid that is an object or a list is not saved either. Internal: the app writes points itself when a contact converts.","operationId":"update-a-contact-conversion-point","x-canonical-resource":"conversion","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactConversionPointId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoint":{"$ref":"#/components/schemas/ContactConversionPointFields"}}},"example":{"contactConversionPoint":{"relid":"8813"}}}}},"responses":{"200":{"description":"The updated point under contactConversionPoint.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionPoint":{"$ref":"#/components/schemas/ContactConversionPointSaved"}}},"example":{"contactConversionPoint":{"contact":"6199","type":"LinkData","relid":"8813","pointdata":{"event":{"type":"EMAIL_LINK_CLICK"},"revenue_generator":{"revenue_generator_type":"Campaign","revenue_generator_id":"27"}},"tstamp":"2026-09-01T14:03:12-05:00","links":{"contact":"https://example.api-us1.com/api/3/contactConversionPoints/15/contact","attributions":"https://example.api-us1.com/api/3/contactConversionPoints/15/attributions"},"id":"15"}}}}},"400":{"$ref":"#/components/responses/ContactConversionPointBadBody"},"403":{"$ref":"#/components/responses/AttributionNotEnabled"},"404":{"$ref":"#/components/responses/ContactConversionPointNotFound"}}},"delete":{"summary":"Delete a contact conversion point","description":"Deletes one point. Attributions that credit the point are not deleted and keep its id. Returns 404 if no point has the id, and 403 when the account does not have Attribution. A delete that fails on a database error such as a deadlock also returns 403. That body is a plain sentence, not JSON, even though it is labelled application/json. Internal: the app writes points itself when a contact converts.","operationId":"delete-a-contact-conversion-point","x-canonical-resource":"conversion","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactConversionPointId"}],"responses":{"200":{"description":"The point was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The account does not have Attribution, or the delete failed on a database error such as a deadlock. A failed delete returns the sentence Failed to delete contactConversionPoint. It is not JSON, though the content type is application/json.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ContactConversionPointErrors"},{"type":"string","description":"Not JSON. The sentence Failed to delete contactConversionPoint."}]},"examples":{"AttributionNotEnabled":{"value":{"errors":[{"status":"403","detail":"Upgrade your account to enable Attribution"}]}},"DeleteFailed":{"value":"Failed to delete contactConversionPoint"}}}}},"404":{"$ref":"#/components/responses/ContactConversionPointNotFound"}}}},"/contactConversionPoints/{id}/attributions":{"get":{"summary":"List the attributions of a contact conversion point","description":"Returns the attributions that credit one point. An attribution gives part of a conversion's revenue to the campaign or message behind the touchpoint. The id is the id of the point. The response is not paged, and the attributions come in no guaranteed order. attributions is an empty array when there are none. Returns 404 if no point has the id, and 403 when the account does not have Attribution.","operationId":"list-contact-conversion-point-attributions","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionPointId"}],"responses":{"200":{"description":"The attributions under attributions.","content":{"application/json":{"schema":{"type":"object","properties":{"attributions":{"type":"array","description":"The attributions of the point.","items":{"$ref":"#/components/schemas/ContactConversionPointAttribution"}}}}}}},"403":{"$ref":"#/components/responses/AttributionNotEnabled"},"404":{"$ref":"#/components/responses/ContactConversionPointNotFound"}}}},"/contactConversionPoints/{id}/contact":{"get":{"summary":"Retrieve the contact of a contact conversion point","description":"Returns the contact that one point belongs to. The id is the id of the point, not of the contact. Returns an empty object {} when the contact no longer exists or the point has none. Returns 404 if no point has the id, and 403 when the account does not have Attribution.","operationId":"retrieve-contact-conversion-point-contact","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionPointId"}],"responses":{"200":{"description":"The contact under contact, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/ContactConversionPointContact"}}}}}},"403":{"$ref":"#/components/responses/AttributionNotEnabled"},"404":{"$ref":"#/components/responses/ContactConversionPointNotFound"}}}},"/contactConversionSources":{"get":{"summary":"List a contact's visit sources since its last conversion","description":"Lists the pages a contact visited since its most recent conversion, with the UTM values of each visit. Each item is one tracked page visit. Nothing is stored for this list: it is worked out from site tracking on each call. A contact with no conversion gets all its tracked page visits. Every page visit counts, even one with no UTM values. Items come in no guaranteed order. filters[subscriberid] is required. Internal: the app uses it to show where a contact came from.","operationId":"list-contact-conversion-sources","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"name":"filters[subscriberid]","in":"query","required":true,"description":"Id of the contact whose visits to list.","schema":{"type":"integer"},"example":42},{"name":"limit","in":"query","description":"Maximum number of visits to return. Send a positive whole number.","schema":{"type":"integer","minimum":1},"example":20}],"responses":{"200":{"description":"The visits under contactConversionSources, with their count in meta.total. contactConversionSources is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionSources":{"type":"array","description":"The visits.","items":{"$ref":"#/components/schemas/ContactConversionSource"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Number of items in this response."}}}}},"examples":{"Result":{"value":{"contactConversionSources":[{"campaign":"fall_sale","source":"newsletter","medium":"email","referrer":"","id":"5d41402abc4b2a76b9719d911017c592","url":"https://www.example.com/pricing?utm_source=newsletter&utm_medium=email&utm_campaign=fall_sale","tstamp":"2026-10-05T09:15:00-05:00"},{"campaign":"","referrer":"https://www.example.com/blog","id":"7d793037a0760186574b0282f2f435e7","url":"https://www.example.com/contact","tstamp":"2026-10-06T14:02:31-05:00"}],"meta":{"total":2}}}}}}},"404":{"description":"No contact has the id in filters[subscriberid]. A value that is not a number may be read as 0. The message always shows the id as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found."}}},"example":{"message":"No Result found for Subscriber with id 999"}}}},"422":{"description":"filters[subscriberid] is missing.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"string","description":"One message, in the user's language. It is a string, not an array."}}}}}}}},"post":{"summary":"Create a contact conversion source","description":"This operation does not work. There is no stored record behind this resource. A body that is not a JSON object returns 400. Otherwise it returns 201 when the body sets no field under contactConversionSource other than id, with an unsaved object whose id is null; nothing is created. It returns 500 once any other field is set. Internal.","operationId":"create-a-contact-conversion-source","x-canonical-resource":"conversion","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionSource":{"type":"object","description":"Fields to save."}}}}}},"responses":{"201":{"description":"Returned when the body sets no field other than id: the body is empty, or contactConversionSource is missing, empty, null or a single value. The object is not saved.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionSource":{"type":"object","properties":{"links":{"type":"object","properties":{"contact":{"type":"string"}}},"id":{"type":"null"}}}}},"example":{"contactConversionSource":{"links":{"contact":"https://example.api-us1.com/api/3/contactConversionSources//contact"},"id":null}}}}},"400":{"$ref":"#/components/responses/ContactConversionSourceBadBody"},"500":{"$ref":"#/components/responses/ContactConversionSourceError"}}}},"/contactConversionSources/{id}":{"get":{"summary":"Retrieve a contact conversion source","description":"This operation does not work. There is no stored record behind this resource. It returns 500 for any id. Internal.","operationId":"retrieve-a-contact-conversion-source","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionSourceId"}],"responses":{"500":{"$ref":"#/components/responses/ContactConversionSourceError"}}},"put":{"summary":"Update a contact conversion source","description":"This operation does not work. There is no stored record behind this resource. A body that is not a JSON object gets 400 first. Any other body, including an empty one, returns 500 for any id. Internal.","operationId":"update-a-contact-conversion-source","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionSourceId"}],"responses":{"400":{"$ref":"#/components/responses/ContactConversionSourceBadBody"},"500":{"$ref":"#/components/responses/ContactConversionSourceError"}},"x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionSource":{"type":"object","description":"Fields to save."}}}}}}},"patch":{"summary":"Update a contact conversion source (PATCH)","description":"This operation does not work. There is no stored record behind this resource. It works the same as PUT. A body that is not a JSON object gets 400 first. Any other body, including an empty one, returns 500 for any id. Internal.","operationId":"patch-a-contact-conversion-source","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionSourceId"}],"responses":{"400":{"$ref":"#/components/responses/ContactConversionSourceBadBody"},"500":{"$ref":"#/components/responses/ContactConversionSourceError"}},"x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversionSource":{"type":"object","description":"Fields to save."}}}}}}},"delete":{"summary":"Delete a contact conversion source","description":"This operation does not work. There is no stored record behind this resource. It returns 500 for any id. Internal.","operationId":"delete-a-contact-conversion-source","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionSourceId"}],"responses":{"500":{"$ref":"#/components/responses/ContactConversionSourceError"}},"x-destructive":true,"x-bulk-operation":false}},"/contactConversionSources/{id}/{relationship}":{"get":{"summary":"Retrieve a related record of a contact conversion source","description":"This operation does not work. There is no stored record behind this resource. It returns 500 for any id. Internal.","operationId":"retrieve-contact-conversion-source-related","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionSourceId"},{"name":"relationship","in":"path","required":true,"description":"Name of the related record. contact is the only one defined.","schema":{"type":"string"},"example":"contact"}],"responses":{"500":{"$ref":"#/components/responses/ContactConversionSourceError"}}}},"/contactConversions":{"get":{"summary":"List all contact conversions","description":"A contact conversion records one time a contact reached a conversion. It is added when one of the conversion's triggers fires for the contact, for example a tracked event, a visited URL, an automation step or an e-commerce order. It keeps the amount and currency booked at that moment. The list shows only entries whose conversion is visible. It leaves out hidden conversions, such as the built-in e-commerce reporting conversion. Entries with no order are left out when the account lacks deals, e-commerce data or site messages, or the API user's group lacks the deals permission. Entries made by an order are left out when the account lacks e-commerce data. Filter by contact or by date. Without an order, entries come in no guaranteed order. Page with limit and offset, or fetch specific entries with ids. Returns 403 if the account does not have attribution.","operationId":"list-all-contact-conversions","x-canonical-resource":"conversion","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Return only entries for this contact id. Exact match.","schema":{"type":"integer"}},{"name":"filters[cdate]","in":"query","description":"Return only entries made at exactly this date and time. Write the date and time that cdate shows, as YYYY-MM-DD HH:MM:SS.","schema":{"type":"string"}},{"name":"orders[subscriberid]","in":"query","description":"Sort by contact id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[cdate]","in":"query","description":"Sort by date. DESC, in any case, sorts newest first; any other value sorts oldest first.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the entries.","schema":{"type":"integer","minimum":0}},{"name":"ids","in":"query","description":"Comma-separated entry ids to return. When set, only those entries are returned, at most one per id. offset still applies.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of entries under contactConversions, with the number of matching entries in meta.total. contactConversions is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversions":{"type":"array","description":"The entries on this page.","items":{"$ref":"#/components/schemas/ContactConversion"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"string","description":"Number of matching entries, before limit and offset, as a string.","example":"1"}}}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"}}},"post":{"summary":"Create a contact conversion","description":"Creates one entry. The fields are saved as sent, without checks, so any contact, conversion and trigger ids are accepted. An empty body, or one without contactConversion, still creates an entry: every field gets its default, such as 0 for the ids and an empty string for the amount. cdate is set to now and cannot be sent. A fired trigger does more than this call. This call does not check the conversion's limit per contact, refuse a second entry for the same contact and order, collect touchpoints, add a contact activity entry or start automations. The new entry still counts toward the limit for later triggers. An activity entry can still be added later, when the contact's activity is next brought up to date, if the conversion is visible. Like a fired trigger, a create still does two more things. First, unless a feature flag turns it off, it queues background attribution work. That work credits touchpoints only when triggerType is ecommerce. Second, during the request and for any triggerType, it looks at the contact's active automations that use the conversion, directly or through an initiative. In each one whose current step is found, it logs the conversion and, if the automation exits on conversion, ends the contact's run. An entry without converted_by_type is later left out of reads, updates and deletes in the same cases as an entry with no order. The response has the fields that were sent, as sent, after true and false are turned into 1 and 0. Ids of 0 in contact, conversion and conversiontrigger come back as null. It always has cdate, udate, value, contact, links, convertedBy and id, and conversiontrigger when conversionTrigger is sent. It also has conversion when the contact has active automations. value is read back from the entry: an empty string when none was sent, and a sent \"15.50\" comes back as 15.5. Returns 400 when the body is not a JSON object, and 403 if the account does not have attribution. Send only the fields listed in the body, with the types listed. Internal: the app adds entries itself when a trigger fires.","operationId":"create-a-contact-conversion","x-canonical-resource":"conversion","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversion":{"$ref":"#/components/schemas/ContactConversionFields"}}},"example":{"contactConversion":{"contact":"12","conversion":"3","conversionTrigger":"5","triggerType":"ecommerce","value":15.5,"currency":"usd","converted_by_type":"EcomOrder","converted_by_id":"88"}}}}},"responses":{"201":{"description":"The new entry under contactConversion.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversion":{"$ref":"#/components/schemas/ContactConversionSaved"}}},"example":{"contactConversion":{"contact":"12","conversion":"3","conversionTrigger":"5","triggerType":"ecommerce","currency":"usd","converted_by_type":"EcomOrder","converted_by_id":"88","cdate":"2026-09-01T14:03:12-05:00","udate":"2026-09-01T14:03:12-05:00","value":15.5,"id":"41","conversiontrigger":"5","convertedBy":{"type":"ecom-order","id":"88"}}}}}},"400":{"$ref":"#/components/responses/ContactConversionBadBody"},"403":{"$ref":"#/components/responses/ContactConversionForbidden"}}}},"/contactConversions/{id}":{"get":{"summary":"Retrieve a contact conversion","description":"A contact conversion records one time a contact reached a conversion. It is added when one of the conversion's triggers fires for the contact, for example a tracked event, a visited URL, an automation step or an e-commerce order. It keeps the amount and currency booked at that moment. Returns one entry by its id, even when its conversion is hidden. Entries with no order are left out when the account lacks deals, e-commerce data or site messages, or the API user's group lacks the deals permission. Entries made by an order are left out when the account lacks e-commerce data. Returns 404 if no entry has the id, or if the entry is left out this way.","operationId":"retrieve-a-contact-conversion","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The entry under contactConversion.","content":{"application/json":{"schema":{"type":"object","properties":{"contactConversion":{"$ref":"#/components/schemas/ContactConversion"}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}},"put":{"summary":"Update a contact conversion","description":"Updates one entry. PATCH does the same. Only the fields sent change, and they are saved as sent, without checks. cdate cannot be changed. An update runs none of the extra work of a create: no attribution work and no automation steps. The response holds the whole entry. Stored values come back as strings and sent values come back as sent, with two exceptions. value comes back as a number when there is one, so a stored 1550 or a sent \"15.50\" comes back as 15.5. Ids of 0 in contact, conversion and conversiontrigger come back as null. true and false are turned into 1 and 0 first. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}. Returns 400 when the body is not a JSON object, and 403 if the account does not have attribution. Send only the fields listed in the body, with the types listed. Internal: the app adds entries itself when a trigger fires.","operationId":"update-a-contact-conversion","x-canonical-resource":"conversion","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactConversion":{"$ref":"#/components/schemas/ContactConversionFields"}}},"example":{"contactConversion":{"value":20}}}}},"responses":{"200":{"$ref":"#/components/responses/ContactConversionUpdated"},"400":{"$ref":"#/components/responses/ContactConversionBadBody"},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}},"delete":{"summary":"Delete a contact conversion","description":"Deletes one entry and its contact activity entries. Attributions that credit the entry are not deleted and keep its id. Touchpoints are not deleted either. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}. Returns 403 if the account does not have attribution. A delete that fails on a database error such as a deadlock also returns 403. That body is a plain sentence, not JSON, even though it is labelled application/json. Internal: the app adds entries itself when a trigger fires.","operationId":"delete-a-contact-conversion","x-canonical-resource":"conversion","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The entry was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The account does not have attribution, or the delete failed on a database error such as a deadlock. A failed delete returns the sentence Failed to delete contactConversion. It is not JSON, though the content type is application/json.","content":{"application/json":{"schema":{"type":["object","string"],"description":"The attribution error as JSON, or the sentence Failed to delete contactConversion."},"examples":{"AttributionNotEnabled":{"value":{"errors":[{"status":"403","detail":"Upgrade your account to enable Attribution"}]}},"DeleteFailed":{"value":"Failed to delete contactConversion"}}}}},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/activities":{"get":{"summary":"List the activities of a contact conversion","description":"Returns the contact activity entries made for one entry. There is usually one, or none for a hidden conversion. The id is the id of the entry. The list is not paged, and the order is not guaranteed. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}.","operationId":"list-contact-conversion-activities","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The activities under activities, an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"activities":{"type":"array","items":{"$ref":"#/components/schemas/ContactConversionActivity"}}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/attributions":{"get":{"summary":"List the attributions of a contact conversion","description":"Returns how one entry's amount was credited to campaigns and other touchpoints the contact engaged with before converting. The id is the id of the entry. Usually only entries made by an order have attributions. The list is not paged, and the order is not guaranteed. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}.","operationId":"list-contact-conversion-attributions","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The attributions under attributions, an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"attributions":{"type":"array","items":{"$ref":"#/components/schemas/ContactConversionAttribution"}}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/contact":{"get":{"summary":"Retrieve the contact of a contact conversion","description":"Returns the contact who converted. The id is the id of the entry. Returns an empty object {} when the contact no longer exists. Users outside the Admin group also get {} when the contact is only on lists their group may not access. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}.","operationId":"retrieve-contact-conversion-contact","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The contact under contact, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/ContactConversionContact"}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/conversion":{"get":{"summary":"Retrieve the conversion of a contact conversion","description":"Returns the conversion that one entry belongs to, hidden or not. The id is the id of the entry. Returns an empty object {} when the conversion no longer exists. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}.","operationId":"retrieve-contact-conversion-conversion","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The conversion under conversion, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"conversion":{"$ref":"#/components/schemas/ContactConversionConversion"}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/conversiontrigger":{"get":{"summary":"Retrieve the trigger of a contact conversion","description":"Returns the trigger that fired for one entry. The id is the id of the entry. The trigger comes back under conversionTrigger. Returns an empty object {} when the trigger no longer exists. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}.","operationId":"retrieve-contact-conversion-conversion-trigger","x-canonical-resource":"conversion","parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The trigger under conversionTrigger, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"conversionTrigger":{"$ref":"#/components/schemas/ContactConversionTrigger"}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactConversions/{id}/convertedBy":{"get":{"summary":"Retrieve the record that made a contact conversion","description":"Returns the record that made one entry, such as an e-commerce order, under a key named for its type, for example ecomOrder. The id is the id of the entry. Returns 404 if no entry has the id, or if the entry is left out, as for GET /contactConversions/{id}. Otherwise, it returns an empty object {} when that record no longer exists.","operationId":"retrieve-contact-conversion-converted-by","x-canonical-resource":"conversion","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ContactConversionId"}],"responses":{"200":{"description":"The order under ecomOrder, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"ecomOrder":{"$ref":"#/components/schemas/ContactConversionOrder"}}}}}},"403":{"$ref":"#/components/responses/ContactConversionForbidden"},"404":{"$ref":"#/components/responses/ContactConversionNotFound"}}}},"/contactData":{"get":{"summary":"List contact data records","description":"Lists the contact data records in the account: one per contact that has one, holding extra information about the contact, mostly where the contact appears to be located. To read one contact's record by contact ID, use GET /contacts/{id}/contactData instead. The location fields (geoIp4, geoCountry2, geo_country, geoState, geoCity, geoZip, geoLat, geoLon, geoTz, geoTzOffset, geoTstamp) are filled by a MaxMind GeoIP lookup of an IP address recorded for the contact, for example when the contact subscribes, opens or clicks a tracked email, or is added through the v1 API with an ip4 value; contact enrichment can also fill the city, state, country, country code and zip when they are blank, and sets geoTstamp when it does. The ga_campaign_*, ga_first_visit, ga_times_visited, fb_id, fb_name and tw_id fields are legacy columns that the application no longer writes. Values come back as strings; tstamp, geoTstamp and ga_first_visit are ISO 8601 dates or null. The list has no filters or sort options: filters and orders are ignored, and the order of the records is not guaranteed. Page with limit and offset. No permission beyond API access is checked: any API user can list the records of every contact in the account. A normal contact delete keeps the record, so the list can include records of contacts that no longer exist. Merging contacts removes the record of the contact that was merged away.","operationId":"list-contact-data","x-canonical-resource":"contact","parameters":[{"name":"limit","in":"query","description":"Number of records to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of records to skip. Use with limit to page through the records.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated record IDs (not contact IDs) to return. When set, only those records are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of contact data records under contactData, with the number of matching records in meta.total.","content":{"application/json":{"schema":{"type":"object","properties":{"contactData":{"type":"array","description":"The records on this page.","items":{"$ref":"#/components/schemas/ContactDatum"}},"meta":{"type":"object","description":"Information about the whole list.","properties":{"total":{"type":"integer","example":2,"description":"Number of matching records, ignoring limit and offset."}}}}},"examples":{"Result":{"value":"{\n    \"contactData\": [\n        {\n            \"contact\": \"4\",\n            \"tstamp\": \"2021-06-09T14:35:10-05:00\",\n            \"geoTstamp\": null,\n            \"geoIp4\": \"0\",\n            \"geoCountry2\": \"\",\n            \"geo_country\": \"\",\n            \"geoState\": \"\",\n            \"geoCity\": \"\",\n            \"geoZip\": \"\",\n            \"geoArea\": \"0\",\n            \"geoLat\": \"0.000000\",\n            \"geoLon\": \"0.000000\",\n            \"geoTz\": \"\",\n            \"geoTzOffset\": \"0.00\",\n            \"ga_campaign_source\": \"\",\n            \"ga_campaign_name\": \"\",\n            \"ga_campaign_medium\": \"\",\n            \"ga_campaign_term\": \"\",\n            \"ga_campaign_content\": \"\",\n            \"ga_campaign_customsegment\": \"\",\n            \"ga_first_visit\": null,\n            \"ga_times_visited\": \"0\",\n            \"fb_id\": \"0\",\n            \"fb_name\": \"\",\n            \"tw_id\": \"0\",\n            \"created_timestamp\": \"2021-06-09 14:35:10\",\n            \"updated_timestamp\": \"2021-06-09 14:35:10\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": [],\n            \"id\": \"12\"\n        },\n        {\n            \"contact\": \"7\",\n            \"tstamp\": \"2021-06-09T14:35:10-05:00\",\n            \"geoTstamp\": \"2021-07-01T09:12:44-05:00\",\n            \"geoIp4\": \"3221225985\",\n            \"geoCountry2\": \"US\",\n            \"geo_country\": \"United States\",\n            \"geoState\": \"Illinois\",\n            \"geoCity\": \"Chicago\",\n            \"geoZip\": \"60601\",\n            \"geoArea\": \"0\",\n            \"geoLat\": \"41.878100\",\n            \"geoLon\": \"-87.629800\",\n            \"geoTz\": \"America/Chicago\",\n            \"geoTzOffset\": \"0.00\",\n            \"ga_campaign_source\": \"\",\n            \"ga_campaign_name\": \"\",\n            \"ga_campaign_medium\": \"\",\n            \"ga_campaign_term\": \"\",\n            \"ga_campaign_content\": \"\",\n            \"ga_campaign_customsegment\": \"\",\n            \"ga_first_visit\": null,\n            \"ga_times_visited\": \"0\",\n            \"fb_id\": \"0\",\n            \"fb_name\": \"\",\n            \"tw_id\": \"0\",\n            \"created_timestamp\": \"2021-06-09 14:35:10\",\n            \"updated_timestamp\": \"2021-07-01 09:12:44\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": [],\n            \"id\": \"15\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}}}}}},"deprecated":false}},"/contactData/{id}":{"get":{"summary":"Retrieve a contact data record","description":"Returns one contact data record by its own ID (not the contact ID). To read a contact's record by contact ID, use GET /contacts/{id}/contactData. The location fields (geoIp4, geoCountry2, geo_country, geoState, geoCity, geoZip, geoLat, geoLon, geoTz, geoTzOffset, geoTstamp) are filled by a MaxMind GeoIP lookup of an IP address recorded for the contact, for example when the contact subscribes, opens or clicks a tracked email, or is added through the v1 API with an ip4 value; contact enrichment can also fill the city, state, country, country code and zip when they are blank, and sets geoTstamp when it does. The ga_campaign_*, ga_first_visit, ga_times_visited, fb_id, fb_name and tw_id fields are legacy columns that the application no longer writes. Values come back as strings; tstamp, geoTstamp and ga_first_visit are ISO 8601 dates or null. No permission beyond API access is checked. Returns 404 if no record has this ID.","operationId":"retrieve-contact-data-record","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","required":true,"description":"ID of the contact data record (not the contact ID).","schema":{"type":"integer"}}],"responses":{"200":{"description":"The record under contactDatum.","content":{"application/json":{"schema":{"type":"object","properties":{"contactDatum":{"$ref":"#/components/schemas/ContactDatum"}}},"examples":{"Result":{"value":"{\n    \"contactDatum\": {\n        \"contact\": \"4\",\n        \"tstamp\": \"2021-06-09T14:35:10-05:00\",\n        \"geoTstamp\": null,\n        \"geoIp4\": \"0\",\n        \"geoCountry2\": \"\",\n        \"geo_country\": \"\",\n        \"geoState\": \"\",\n        \"geoCity\": \"\",\n        \"geoZip\": \"\",\n        \"geoArea\": \"0\",\n        \"geoLat\": \"0.000000\",\n        \"geoLon\": \"0.000000\",\n        \"geoTz\": \"\",\n        \"geoTzOffset\": \"0.00\",\n        \"ga_campaign_source\": \"\",\n        \"ga_campaign_name\": \"\",\n        \"ga_campaign_medium\": \"\",\n        \"ga_campaign_term\": \"\",\n        \"ga_campaign_content\": \"\",\n        \"ga_campaign_customsegment\": \"\",\n        \"ga_first_visit\": null,\n        \"ga_times_visited\": \"0\",\n        \"fb_id\": \"0\",\n        \"fb_name\": \"\",\n        \"tw_id\": \"0\",\n        \"created_timestamp\": \"2021-06-09 14:35:10\",\n        \"updated_timestamp\": \"2021-06-09 14:35:10\",\n        \"created_by\": \"0\",\n        \"updated_by\": \"0\",\n        \"links\": [],\n        \"id\": \"12\"\n    }\n}"}}}}},"404":{"description":"No contact data record has this ID. Body: message, \"No Result found for SubscriberData with id\" followed by the ID as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"description":"Says which record was not found and its ID.","type":"string","example":"No Result found for SubscriberData with id 121"}}},"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberData with id 121\"\n}"}}}}}},"deprecated":false}},"/contactDeals":{"post":{"summary":"Create a secondary contact","description":"Add a contact to a deal as a secondary contact, with an optional role. contact and deal must name existing records, and the contact must not already be on the deal. When the deal has no primary contact and no other linked contact yet, the contact added becomes its primary contact. The addition is recorded as a deal activity. Needs the deals permission.","operationId":"create-a-secondary-contact","x-canonical-resource":"contactDeals","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactDeal":{"properties":{"deal":{"type":["integer","string"],"description":"Id of the deal."},"contact":{"type":["integer","string"],"description":"Id of the contact."},"role":{"type":"integer","description":"Id of the deal role the contact holds on this deal, from GET /dealRoles. Not validated: an id with no matching role is accepted.","format":"int32"}},"required":["deal","contact"],"type":"object","description":"The link to create or change."}}},"examples":{"Request Example":{"value":{"contactDeal":{"contact":1,"deal":2}}}}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"deals\": [\n        {\n            \"hash\": \"c7b5a271\",\n            \"owner\": \"1\",\n            \"contact\": \"2\",\n            \"organization\": null,\n            \"group\": \"1\",\n            \"stage\": \"1\",\n            \"title\": \"deal1\",\n            \"description\": \"\",\n            \"percent\": \"0\",\n            \"cdate\": \"2018-10-31T13:33:09-05:00\",\n            \"mdate\": \"2018-10-31T13:33:09-05:00\",\n            \"nexttaskid\": null,\n            \"value\": \"10000\",\n            \"currency\": \"usd\",\n            \"winProbability\": null,\n            \"winProbabilityMdate\": \"2018-10-31T13:33:09-05:00\",\n            \"status\": \"0\",\n            \"activitycount\": \"1\",\n            \"nextdealid\": \"2\",\n            \"edate\": null,\n            \"links\": {\n                \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/2/dealActivities\",\n                \"contact\": \"https://:account.api-us1.com/api/3/deals/2/contact\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/2/contactDeals\",\n                \"group\": \"https://:account.api-us1.com/api/3/deals/2/group\",\n                \"nextTask\": \"https://:account.api-us1.com/api/3/deals/2/nextTask\",\n                \"notes\": \"https://:account.api-us1.com/api/3/deals/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/3/deals/2/organization\",\n                \"owner\": \"https://:account.api-us1.com/api/3/deals/2/owner\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/2/scoreValues\",\n                \"stage\": \"https://:account.api-us1.com/api/3/deals/2/stage\",\n                \"tasks\": \"https://:account.api-us1.com/api/3/deals/2/tasks\",\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/2/dealCustomFieldData\"\n            },\n            \"id\": \"2\",\n            \"isDisabled\": false\n        }\n    ],\n    \"contactDeal\": {\n        \"contact\": 1,\n        \"deal\": 2,\n        \"cdate\": \"2019-02-25T09:00:02-06:00\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/3/contactDeals/3/deal\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactDeals/3/contact\"\n        },\n        \"id\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"hash":{"type":"string","description":"Random eight-character code given to the deal when it was created.","examples":["c7b5a271"]},"owner":{"type":["string","null"],"description":"Deal's owner id. Null when the deal has no owner.","examples":["1"]},"contact":{"type":["string","null"],"description":"Deal's primary contact id. Null when the deal has an account and no primary contact.","examples":["2"]},"organization":{"description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount.","type":["string","null"]},"group":{"type":"string","description":"Deal's pipeline id.","examples":["1"]},"stage":{"type":"string","description":"Deal's stage id.","examples":["1"]},"title":{"type":"string","description":"Deal's title.","examples":["deal1"]},"description":{"type":"string","description":"Deal's description. Empty when none.","examples":[""]},"percent":{"type":"string","description":"Deal's percentage.","examples":["0"]},"cdate":{"type":"string","description":"When the deal was created.","examples":["2018-10-31T13:33:09-05:00"]},"mdate":{"type":"string","description":"When the deal was last changed, including when an activity was added to it.","examples":["2018-10-31T13:33:09-05:00"]},"nexttaskid":{"description":"Id of the deal's next open task. Null (0 on older deals) when there is none.","type":["string","null"]},"value":{"type":"string","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","examples":["10000"]},"currency":{"type":"string","description":"Deal's currency in 3-digit ISO format, lowercased.","examples":["usd"]},"winProbability":{"description":"Predicted chance of winning the deal, as a whole percentage rounded up. Returned as a number, not a string. Null when the account does not have win probability or it has not been calculated yet.","type":["number","null"]},"winProbabilityMdate":{"type":["string","null"],"description":"When winProbability was last updated. Null when it has never been calculated or the account does not have win probability.","examples":["2018-10-31T13:33:09-05:00"]},"status":{"type":"string","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\").","examples":["0"]},"activitycount":{"type":"string","description":"Number of activities recorded on the deal.","examples":["1"]},"nextdealid":{"type":"string","description":"Internal pointer used to order the pipeline's open deals: the id of the deal that follows this one. 0 when there is none.","examples":["2"]},"edate":{"description":"When email activity was last gathered for the deal. Null when it never was. Returned as YYYY-MM-DD HH:MM:SS, not in ISO 8601 format.","type":["string","null"]},"links":{"type":"object","properties":{"dealActivities":{"type":"string","description":"URL to list the deal's activities.","examples":["https://:account.api-us1.com/api/3/deals/2/dealActivities"]},"contact":{"type":"string","description":"URL to the deal's primary contact.","examples":["https://:account.api-us1.com/api/3/deals/2/contact"]},"contactDeals":{"type":"string","description":"URL to list the links between the deal and its contacts.","examples":["https://:account.api-us1.com/api/3/deals/2/contactDeals"]},"group":{"type":"string","description":"URL to the deal's pipeline.","examples":["https://:account.api-us1.com/api/3/deals/2/group"]},"nextTask":{"type":"string","description":"URL to the deal's next open task.","examples":["https://:account.api-us1.com/api/3/deals/2/nextTask"]},"notes":{"type":"string","description":"URL to list the deal's notes.","examples":["https://:account.api-us1.com/api/3/deals/2/notes"]},"organization":{"type":"string","description":"URL to the deal's account (same as account).","examples":["https://:account.api-us1.com/api/3/deals/2/organization"]},"owner":{"type":"string","description":"URL to the deal's owner.","examples":["https://:account.api-us1.com/api/3/deals/2/owner"]},"scoreValues":{"type":"string","description":"URL to list the deal's score values.","examples":["https://:account.api-us1.com/api/3/deals/2/scoreValues"]},"stage":{"type":"string","description":"URL to the deal's stage.","examples":["https://:account.api-us1.com/api/3/deals/2/stage"]},"tasks":{"type":"string","description":"URL to list the deal's tasks.","examples":["https://:account.api-us1.com/api/3/deals/2/tasks"]},"dealCustomFieldData":{"type":"string","description":"URL to list the deal's custom field values.","examples":["https://:account.api-us1.com/api/3/deals/2/dealCustomFieldData"]}},"description":"URLs of the deal's related resources."},"id":{"type":"string","description":"Id of the deal.","examples":["2"]},"isDisabled":{"type":"boolean","description":"True when the current user cannot see the deal: it is in a pipeline they cannot see, or they may not see all deals and do not own it. Such a deal comes back with only id, title, status and isDisabled.","examples":[false]}},"description":"The deal."},"description":"The linked deal, sideloaded. This lists its main fields; see GET /deals/{id} for the rest."},"contactDeal":{"type":"object","properties":{"contact":{"type":["integer","string"],"default":0,"description":"Id of the contact linked to the deal, echoed as sent.","examples":[1]},"deal":{"type":["integer","string"],"default":0,"description":"Id of the deal, echoed as sent.","examples":[2]},"role":{"type":["integer","string","null"],"description":"Id of the contact's deal role; only present when the request sent it. Null when 0 or null is sent.","examples":[1]},"cdate":{"type":"string","description":"When the contact was linked to the deal, in ISO 8601.","examples":["2019-02-25T09:00:02-06:00"]},"links":{"type":"object","description":"URLs of the link's related reads.","properties":{"deal":{"type":"string","description":"URL that returns the deal, GET /contactDeals/{id}/deal.","examples":["https://:account.api-us1.com/api/3/contactDeals/3/deal"]},"contact":{"type":"string","description":"URL that returns the contact, GET /contactDeals/{id}/contact.","examples":["https://:account.api-us1.com/api/3/contactDeals/3/contact"]},"role":{"type":"string","description":"URL that returns the contact's deal role, GET /contactDeals/{id}/role.","examples":["https://:account.api-us1.com/api/3/contactDeals/3/role"]}}},"id":{"type":"string","description":"Id of the link. This is not the contact id or the deal id.","examples":["3"]}},"description":"The link, with the values as sent; it is not read back."}}}}}},"403":{"description":"The API user does not have the deals permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","example":"Forbidden","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says that the deals permission is needed."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"Permissions for Deals is required to create a deal contact\"\n        }\n    ]\n}"}}}}},"422":{"description":"contact or deal is missing or names a record that does not exist, or this contact is already on this deal.","content":{"application/json":{"examples":{"already exists":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The given contact is already associated to the deal\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/contact\"\n            }\n        }\n    ]\n}"},"required field missing":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The contactDeal contact was not provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/contact\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The given contact is already associated to the deal","description":"What was wrong."},"detail":{"type":"string","example":"","description":"Always empty here."},"code":{"type":"string","example":"field_invalid","description":"Machine-readable reason, such as field_missing, related_missing or field_invalid."},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/contact","description":"The body field that failed, such as /data/attributes/contact."}},"description":"Where the problem is."}}},"description":"One entry per problem."}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"add_contact_to_deal","title":"Add Contact to Deal","description":"Associate an existing contact with a deal, optionally with a deal role id from list_deal_roles. The contact must not already be on the deal; on a deal with no contacts yet, the contact becomes its primary contact.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List all secondary contacts","description":"Lists links between contacts and deals, 20 per page by default and up to 100 per page (limit). By default only secondary contacts are listed: a link for the deal's primary contact, and a link whose deal no longer exists, are left out. Send include_primary_contact=1 to also list primary contacts, with each deal's primary contact first. Narrow the list with filters[deal] and filters[contact], which match exactly. The order of the other links is not guaranteed. lastContactDate and lastContactType are added when the contact has had a qualifying activity. Only one link per contact on the page carries them; the contact's other links leave them out. Needs the deals permission. For one contact's links use GET /contacts/{id}/contactDeals; for one deal's links use GET /deals/{id}/contactDeals.","operationId":"list-all-secondary-contacts","x-canonical-resource":"contactDeals","responses":{"200":{"description":"A page of links.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactDeals\": [\n        {\n            \"deal\": \"2\",\n            \"contact\": \"1\",\n            \"cdate\": \"2019-02-25T08:16:56-06:00\",\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/3/contactDeals/1/deal\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactDeals/1/contact\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactDeals":{"type":"array","description":"The links on this page.","items":{"type":"object","properties":{"deal":{"type":"string","example":"2","description":"Id of the deal."},"contact":{"type":"string","example":"1","description":"Id of the contact linked to the deal."},"role":{"type":["string","null"],"example":null,"description":"Id of the contact's deal role on this deal, from GET /dealRoles. Null when none is set."},"cdate":{"type":["string","null"],"example":"2019-02-25T08:16:56-06:00","description":"When the contact was linked to the deal, in ISO 8601. Null when not recorded."},"created_timestamp":{"type":"string","example":"2019-02-25 08:16:56","description":"When the link row was created, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago)."},"updated_timestamp":{"type":"string","example":"2019-02-25 08:16:56","description":"When the link row last changed, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago)."},"created_by":{"type":["string","null"],"example":null,"description":"Id of the user recorded as creating the link. Usually null."},"updated_by":{"type":["string","null"],"example":null,"description":"Id of the user recorded as last changing the link. Usually null."},"links":{"type":"object","description":"URLs of the link's related reads.","properties":{"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/deal","description":"URL that returns the deal, GET /contactDeals/{id}/deal."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/contact","description":"URL that returns the contact, GET /contactDeals/{id}/contact."},"role":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/role","description":"URL that returns the contact's deal role, GET /contactDeals/{id}/role."}}},"id":{"type":"string","example":"1","description":"Id of the link. This is not the contact id or the deal id."},"lastContactDate":{"type":["string","null"],"example":"2026-09-30T11:02:41-05:00","description":"When the contact last had a qualifying activity: a one-to-one or campaign email, an automation start or finish, a forward, a reply, a text sent or received, an automation goal, a deal task, or an email in the contact's email activity. Absent when the contact has had none. Only one link per contact on the page carries it; the contact's other links leave it out."},"lastContactType":{"type":["string","null"],"example":"Email","description":"Kind of that last activity, in the API user's language: Email, Text, or the deal task's type name. Task when the task no longer exists, and null when the task has no type. Absent when lastContactDate is absent."}}}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"string","example":"1","description":"Number of matching links, ignoring limit and offset, as a string."}}}}}}}},"403":{"description":"The API user does not have the deals permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","example":"Forbidden","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says that the deals permission is needed."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"Permissions for Deals is required to retrieve a deal contact\"\n        }\n    ]\n}"}}}}}},"deprecated":false,"parameters":[{"name":"filters[deal]","in":"query","description":"Only links to this deal id.","schema":{"type":"integer"}},{"name":"filters[contact]","in":"query","description":"Only links for this contact id.","schema":{"type":"integer"}},{"name":"include_primary_contact","in":"query","description":"Send 1 to also list each deal's primary contact, sorted first. Without it, primary contacts are left out.","schema":{"type":"integer","enum":[0,1]}},{"name":"limit","in":"query","description":"Number of links per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of links to skip before the page starts. Default 0.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated link ids to fetch. Overrides limit; offset still applies.","schema":{"type":"string"}}]}},"/contactDeals/{id}":{"get":{"summary":"Retrieve a secondary contact","description":"Returns one link between a contact and a deal by the link's id. It can be a primary-contact link as well as a secondary one. lastContactDate and lastContactType are not included here. Needs the deals permission; 404 when no link has this id.","operationId":"retrieve-a-secondary-contact","x-canonical-resource":"contactDeals","parameters":[{"name":"id","in":"path","description":"Id of the link (the contactDeal id), not the contact or deal id.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The link.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactDeal\": {\n        \"deal\": \"2\",\n        \"contact\": \"1\",\n        \"cdate\": \"2019-02-25T08:16:56-06:00\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/3/contactDeals/1/deal\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactDeals/1/contact\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactDeal":{"type":"object","description":"The link between the contact and the deal.","properties":{"deal":{"type":"string","example":"2","description":"Id of the deal."},"contact":{"type":"string","example":"1","description":"Id of the contact linked to the deal."},"role":{"type":["string","null"],"example":null,"description":"Id of the contact's deal role on this deal, from GET /dealRoles. Null when none is set."},"cdate":{"type":["string","null"],"example":"2019-02-25T08:16:56-06:00","description":"When the contact was linked to the deal, in ISO 8601. Null when not recorded."},"created_timestamp":{"type":"string","example":"2019-02-25 08:16:56","description":"When the link row was created, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago)."},"updated_timestamp":{"type":"string","example":"2019-02-25 08:16:56","description":"When the link row last changed, as YYYY-MM-DD HH:MM:SS in US Central time (America/Chicago)."},"created_by":{"type":["string","null"],"example":null,"description":"Id of the user recorded as creating the link. Usually null."},"updated_by":{"type":["string","null"],"example":null,"description":"Id of the user recorded as last changing the link. Usually null."},"links":{"type":"object","description":"URLs of the link's related reads.","properties":{"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/deal","description":"URL that returns the deal, GET /contactDeals/{id}/deal."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/contact","description":"URL that returns the contact, GET /contactDeals/{id}/contact."},"role":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/role","description":"URL that returns the contact's deal role, GET /contactDeals/{id}/role."}}},"id":{"type":"string","example":"1","description":"Id of the link. This is not the contact id or the deal id."}}}}}}}},"403":{"description":"The API user does not have the deals permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","example":"Forbidden","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says that the deals permission is needed."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"Permissions for Deals is required to retrieve a deal contact\"\n        }\n    ]\n}"}}}}},"404":{"description":"No link has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberDeal with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberDeal with id 100","description":"Says no secondary contact link has this id."}}}}}}},"deprecated":false},"put":{"summary":"Update a secondary contact","description":"Update an existing secondary contact on a deal: the contact it links, the deal it links to, and the contact's role on that deal. Only the properties present in the request change. Changing contact removes the previous contact's score values for the deal and logs the change on the deal. Changing deal moves the link only: neither deal records an activity and the previous deal keeps its score values. Changing role is recorded as a deal activity. 404 if no secondary contact has this id; 422 if contact or deal is emptied or names a record that does not exist. Needs the deals permission.","operationId":"update-a-secondary-contact","x-canonical-resource":"contactDeals","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Secondary Contact's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactDeal":{"properties":{"deal":{"type":["integer","string"],"description":"Id of the deal."},"contact":{"type":["integer","string"],"description":"Id of the contact."},"role":{"type":"integer","description":"Id of the deal role the contact holds on this deal, from GET /dealRoles. Not validated: an id with no matching role is accepted.","format":"int32"}},"required":[],"type":"object","description":"The link to create or change."}}},"examples":{"Request Example":{"value":{"contactDeal":{"contact":4,"role":1}}}}}}},"responses":{"200":{"description":"The updated secondary contact.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"deals\": [\n        {\n            \"hash\": \"c7b5a271\",\n            \"owner\": \"1\",\n            \"contact\": \"2\",\n            \"organization\": null,\n            \"group\": \"1\",\n            \"stage\": \"1\",\n            \"title\": \"deal1\",\n            \"description\": \"\",\n            \"percent\": \"0\",\n            \"cdate\": \"2018-10-31T13:33:09-05:00\",\n            \"mdate\": \"2018-10-31T13:33:09-05:00\",\n            \"nexttaskid\": null,\n            \"value\": \"10000\",\n            \"currency\": \"usd\",\n            \"winProbability\": null,\n            \"winProbabilityMdate\": \"2018-10-31T13:33:09-05:00\",\n            \"status\": \"0\",\n            \"activitycount\": \"1\",\n            \"nextdealid\": \"2\",\n            \"edate\": null,\n            \"links\": {\n                \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/2/dealActivities\",\n                \"contact\": \"https://:account.api-us1.com/api/3/deals/2/contact\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/2/contactDeals\",\n                \"group\": \"https://:account.api-us1.com/api/3/deals/2/group\",\n                \"nextTask\": \"https://:account.api-us1.com/api/3/deals/2/nextTask\",\n                \"notes\": \"https://:account.api-us1.com/api/3/deals/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/3/deals/2/organization\",\n                \"owner\": \"https://:account.api-us1.com/api/3/deals/2/owner\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/2/scoreValues\",\n                \"stage\": \"https://:account.api-us1.com/api/3/deals/2/stage\",\n                \"tasks\": \"https://:account.api-us1.com/api/3/deals/2/tasks\",\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/2/dealCustomFieldData\"\n            },\n            \"id\": \"2\",\n            \"isDisabled\": false\n        }\n    ],\n    \"contactDeal\": {\n        \"deal\": \"2\",\n        \"contact\": 4,\n        \"role\": 1,\n        \"cdate\": \"2019-02-25T08:16:56-06:00\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/3/contactDeals/1/deal\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactDeals/1/contact\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"hash":{"type":"string","example":"c7b5a271","description":"Random eight-character code given to the deal when it was created."},"owner":{"type":["string","null"],"example":"1","description":"Deal's owner id. Null when the deal has no owner."},"contact":{"type":["string","null"],"example":"2","description":"Deal's primary contact id. Null when the deal has an account and no primary contact."},"organization":{"description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount.","type":["string","null"]},"group":{"type":"string","example":"1","description":"Deal's pipeline id."},"stage":{"type":"string","example":"1","description":"Deal's stage id."},"title":{"type":"string","example":"deal1","description":"Deal's title."},"description":{"type":"string","example":"","description":"Deal's description. Empty when none."},"percent":{"type":"string","example":"0","description":"Deal's percentage."},"cdate":{"type":"string","example":"2018-10-31T13:33:09-05:00","description":"When the deal was created."},"mdate":{"type":"string","example":"2018-10-31T13:33:09-05:00","description":"When the deal was last changed, including when an activity was added to it."},"nexttaskid":{"description":"Id of the deal's next open task. Null (0 on older deals) when there is none.","type":["string","null"]},"value":{"type":"string","example":"10000","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero."},"currency":{"type":"string","example":"usd","description":"Deal's currency in 3-digit ISO format, lowercased."},"winProbability":{"description":"Predicted chance of winning the deal, as a whole percentage rounded up. Returned as a number, not a string. Null when the account does not have win probability or it has not been calculated yet.","type":["number","null"]},"winProbabilityMdate":{"type":["string","null"],"example":"2018-10-31T13:33:09-05:00","description":"When winProbability was last updated. Null when it has never been calculated or the account does not have win probability."},"status":{"type":"string","example":"0","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")."},"activitycount":{"type":"string","example":"1","description":"Number of activities recorded on the deal."},"nextdealid":{"type":"string","example":"2","description":"Internal pointer used to order the pipeline's open deals: the id of the deal that follows this one. 0 when there is none."},"edate":{"description":"When email activity was last gathered for the deal. Null when it never was. Returned as YYYY-MM-DD HH:MM:SS, not in ISO 8601 format.","type":["string","null"]},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/dealActivities","description":"URL to list the deal's activities."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/contact","description":"URL to the deal's primary contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/contactDeals","description":"URL to list the links between the deal and its contacts."},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/group","description":"URL to the deal's pipeline."},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/nextTask","description":"URL to the deal's next open task."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/notes","description":"URL to list the deal's notes."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/organization","description":"URL to the deal's account (same as account)."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/owner","description":"URL to the deal's owner."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/scoreValues","description":"URL to list the deal's score values."},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/stage","description":"URL to the deal's stage."},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/tasks","description":"URL to list the deal's tasks."},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/2/dealCustomFieldData","description":"URL to list the deal's custom field values."}},"description":"URLs of the deal's related resources."},"id":{"type":"string","example":"2","description":"Id of the deal."},"isDisabled":{"type":"boolean","example":false,"description":"True when the current user cannot see the deal: it is in a pipeline they cannot see, or they may not see all deals and do not own it. Such a deal comes back with only id, title, status and isDisabled."}},"description":"The deal."},"description":"The linked deal, sideloaded. This lists its main fields; see GET /deals/{id} for the rest."},"contactDeal":{"type":"object","properties":{"deal":{"type":["integer","string"],"example":"2","description":"Id of the deal. As sent when sent; otherwise the stored id, as a string."},"contact":{"type":["integer","string"],"example":4,"default":0,"description":"Id of the contact linked to the deal. As sent when sent; otherwise the stored id, as a string."},"role":{"type":["integer","string","null"],"example":1,"description":"Id of the contact's deal role on this deal, from GET /dealRoles. As sent when sent; otherwise the stored id, as a string. Null when none is set."},"cdate":{"type":["string","null"],"example":"2019-02-25T08:16:56-06:00","description":"When the contact was linked to the deal, in ISO 8601. Null when not recorded."},"created_timestamp":{"type":"string","example":"2019-02-25 09:00:02","description":"When the link was created, as YYYY-MM-DD HH:MM:SS rather than the ISO 8601 form cdate uses."},"updated_timestamp":{"type":"string","example":"2019-02-25 09:00:02","description":"When the link last changed, as YYYY-MM-DD HH:MM:SS. Shows the value from before this update."},"created_by":{"type":["string","null"],"example":"1","description":"Id of the user recorded as creating the link, or null."},"updated_by":{"type":["string","null"],"example":"1","description":"Id of the user recorded as last changing the link, or null."},"links":{"type":"object","description":"URLs of the link's related reads.","properties":{"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/deal","description":"URL that returns the deal, GET /contactDeals/{id}/deal."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/contact","description":"URL that returns the contact, GET /contactDeals/{id}/contact."},"role":{"type":"string","example":"https://:account.api-us1.com/api/3/contactDeals/1/role","description":"URL that returns the contact's deal role, GET /contactDeals/{id}/role."}}},"id":{"type":"string","example":"1","description":"Id of the link. This is not the contact id or the deal id."}},"description":"The stored link with the sent changes applied. It is not read back after saving: fields that were not sent come back as their stored values, and updated_timestamp shows its value from before this update."}}}}}},"403":{"description":"The API user does not have the deals permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","example":"Forbidden","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says that the deals permission is needed."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"Permissions for Deals is required to update a deal contact\"\n        }\n    ]\n}"}}}}},"404":{"description":"No secondary contact with this id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberDeal with id 100","description":"Says no secondary contact link has this id."}}},"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberDeal with id 100\"\n}"}}}}},"422":{"description":"contact or deal was emptied, or names a record that does not exist.","content":{"application/json":{"examples":{"relation does not exist":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The related contact does not exist.\",\n            \"detail\": \"\",\n            \"code\": \"related_missing\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/contact\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The related contact does not exist.","description":"What was wrong."},"detail":{"type":"string","example":"","description":"Always empty here."},"code":{"type":"string","example":"related_missing","description":"Machine-readable reason, such as field_missing, related_missing or field_invalid."},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/contact","description":"The body field that failed, such as /data/attributes/contact."}},"description":"Where the problem is."}}},"description":"One entry per problem."}}}}}}},"deprecated":false},"delete":{"summary":"Delete a secondary contact","description":"Removes a contact from a deal by the link's id. The deal and the contact themselves are not deleted. The contact's score values for that deal are deleted, and the removal is recorded as a deal activity. Needs the deals permission; 404 when no link has this id.","operationId":"delete-a-secondary-contact","x-canonical-resource":"contactDeals","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of the link (the contactDeal id), not the contact or deal id.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The link was removed. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{ }"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The API user does not have the deals permission. Also returned, as a plain sentence (\"Failed to delete contactDeal\") with an application/json Content-Type, when the delete itself fails.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","example":"Forbidden","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says that the deals permission is needed."}}}}}},{"type":"string","description":"The plain-sentence failure.","example":"Failed to delete contactDeal"}]},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"Permissions for Deals is required to delete a deal contact\"\n        }\n    ]\n}"}}}}},"404":{"description":"No link has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberDeal with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberDeal with id 100","description":"Says no secondary contact link has this id."}}}}}}},"deprecated":false}},"/contactEmails":{"get":{"summary":"List contact emails","description":"Lists the one-to-one emails that users sent to contacts, for example from a contact or deal page in ActiveCampaign, or logged by the ActiveCampaign Chrome extension for Gmail. Each record links the email's message, the contact, the user who sent it, and the deal and CRM account it was filed against. The subject and body are on the linked message, not in the record. If the API user's group does not have the deals permission, emails filed against a deal are left out of the list and of meta.total. There are no filters and no sort options, and the order of the records is not guaranteed. Page with limit and offset, or use ids to fetch specific records.","operationId":"list-all-contact-emails","x-canonical-resource":"emailActivities","parameters":[{"name":"ids","in":"query","description":"Comma-separated list of email record IDs to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return for each call. Default is 20; maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"A page of email records under contactEmails, with the number of matching records in meta.total.","content":{"application/json":{"schema":{"type":"object","properties":{"contactEmails":{"type":"array","description":"The email records on this page. An empty list when there are none.","items":{"$ref":"#/components/schemas/ContactEmail"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, ignoring limit and offset.","example":2}}}}},"examples":{"Result":{"value":"{\n    \"contactEmails\": [\n        {\n            \"messageid\": \"37\",\n            \"seriesid\": \"0\",\n            \"messageheader\": \"<0123abcd@example.com>\",\n            \"userid\": \"1\",\n            \"d_id\": \"0\",\n            \"subscriberid\": \"12\",\n            \"account\": null,\n            \"ip\": \"3221225985\",\n            \"sdate\": \"2024-03-05T10:15:00-06:00\",\n            \"source\": \"\",\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/contactEmails/7/user\",\n                \"deal\": \"https://:account.api-us1.com/api/3/contactEmails/7/deal\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactEmails/7/contact\",\n                \"message\": \"https://:account.api-us1.com/api/3/contactEmails/7/message\",\n                \"activity\": \"https://:account.api-us1.com/api/3/contactEmails/7/activity\",\n                \"account\": \"https://:account.api-us1.com/api/3/contactEmails/7/account\"\n            },\n            \"id\": \"7\",\n            \"user\": \"1\",\n            \"deal\": null,\n            \"contact\": \"12\",\n            \"message\": \"37\"\n        },\n        {\n            \"messageid\": \"39\",\n            \"seriesid\": \"0\",\n            \"messageheader\": null,\n            \"userid\": \"1\",\n            \"d_id\": \"4\",\n            \"subscriberid\": \"12\",\n            \"account\": \"2\",\n            \"ip\": \"3221225985\",\n            \"sdate\": \"2024-03-06T09:01:12-06:00\",\n            \"source\": \"\",\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/contactEmails/9/user\",\n                \"deal\": \"https://:account.api-us1.com/api/3/contactEmails/9/deal\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactEmails/9/contact\",\n                \"message\": \"https://:account.api-us1.com/api/3/contactEmails/9/message\",\n                \"activity\": \"https://:account.api-us1.com/api/3/contactEmails/9/activity\",\n                \"account\": \"https://:account.api-us1.com/api/3/contactEmails/9/account\"\n            },\n            \"id\": \"9\",\n            \"user\": \"1\",\n            \"deal\": \"4\",\n            \"contact\": \"12\",\n            \"message\": \"39\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}}}}},"403":{"description":"The request has no valid API token. The body is empty."}},"deprecated":false}},"/contactEmails/{id}":{"get":{"summary":"Retrieve a contact email","description":"Returns a single one-to-one email record that a user sent to a contact. The subject and body are on the linked message, not in the record. Returns 404 if no email record has the id.","operationId":"retrieve-a-contact-email","x-canonical-resource":"emailActivities","parameters":[{"name":"id","in":"path","description":"ID of the email record.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The email record under contactEmail.","content":{"application/json":{"schema":{"type":"object","properties":{"contactEmail":{"$ref":"#/components/schemas/ContactEmail"}}},"examples":{"Result":{"value":"{\n    \"contactEmail\": {\n        \"messageid\": \"37\",\n        \"seriesid\": \"0\",\n        \"messageheader\": \"<0123abcd@example.com>\",\n        \"userid\": \"1\",\n        \"d_id\": \"0\",\n        \"subscriberid\": \"12\",\n        \"account\": null,\n        \"ip\": \"3221225985\",\n        \"sdate\": \"2024-03-05T10:15:00-06:00\",\n        \"source\": \"\",\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/3/contactEmails/7/user\",\n            \"deal\": \"https://:account.api-us1.com/api/3/contactEmails/7/deal\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactEmails/7/contact\",\n            \"message\": \"https://:account.api-us1.com/api/3/contactEmails/7/message\",\n            \"activity\": \"https://:account.api-us1.com/api/3/contactEmails/7/activity\",\n            \"account\": \"https://:account.api-us1.com/api/3/contactEmails/7/account\"\n        },\n        \"id\": \"7\",\n        \"user\": \"1\",\n        \"deal\": null,\n        \"contact\": \"12\",\n        \"message\": \"37\"\n    }\n}"}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"description":"No email record has this id. Body: message, \"No Result found for SubscriberEmail with id\" followed by the id as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no email record has the id.","example":"No Result found for SubscriberEmail with id 100"}}},"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberEmail with id 100\"\n}"}}}}}},"deprecated":false}},"/contactGoalLists":{"get":{"summary":"List all contact goal list entries","description":"A contact goal list entry records one list the contact was on when it reached an automation goal. Each reached goal gets one entry for every list the contact belonged to at that moment, whatever the subscription status. Filter by list or by reached goal. Without an order, entries come in no guaranteed order. Page with limit and offset, or fetch specific entries with ids.","operationId":"list-all-contact-goal-lists","x-canonical-resource":"contactAutomations","parameters":[{"name":"filters[listid]","in":"query","description":"Return only entries for this list id. Exact match.","schema":{"type":"integer"}},{"name":"filters[subscribergoalid]","in":"query","description":"Return only entries for this reached goal, the id from GET /contactGoals/{id}. Exact match.","schema":{"type":"integer"}},{"name":"orders[listid]","in":"query","description":"Sort by list id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[subscribergoalid]","in":"query","description":"Sort by reached goal id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the entries.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated entry ids to return. When set, only those entries are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of entries under contactGoalLists, with the number of matching entries in meta.total. contactGoalLists is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalLists":{"type":"array","description":"The entries on this page.","items":{"$ref":"#/components/schemas/ContactGoalList"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching entries, before limit and offset."}}}}},"examples":{"Result":{"value":{"contactGoalLists":[{"listid":"3","subscribergoalid":"41","links":{"list":"https://example.api-us1.com/api/3/contactGoalLists/12/list","contactGoal":"https://example.api-us1.com/api/3/contactGoalLists/12/contactGoal"},"id":"12","list":"3","contactGoal":"41"}],"meta":{"total":1}}}}}}}}}},"/contactGoalLists/{id}":{"get":{"summary":"Retrieve a contact goal list entry","description":"A contact goal list entry records one list the contact was on when it reached an automation goal. Returns one entry by its id. Returns 404 if no entry has the id.","operationId":"retrieve-a-contact-goal-list","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalListId"}],"responses":{"200":{"description":"The entry under contactGoalList.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalList":{"description":"The entry.","allOf":[{"$ref":"#/components/schemas/ContactGoalList"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalListNotFound"}}}},"/contactGoalLists/{id}/contactGoal":{"get":{"summary":"Retrieve the reached goal of a contact goal list entry","description":"Returns the reached goal that one entry belongs to: the contact, the automation, the goal and when it was reached. The id is the id of the entry, not of the goal. Returns an empty object {} when the reached goal no longer exists or the entry has none. Returns 404 if no entry has the id.","operationId":"retrieve-contact-goal-list-contact-goal","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalListId"}],"responses":{"200":{"description":"The reached goal under contactGoal, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoal":{"description":"The reached goal.","allOf":[{"$ref":"#/components/schemas/ContactGoalListContactGoal"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalListNotFound"}}}},"/contactGoalLists/{id}/list":{"get":{"summary":"Retrieve the list of a contact goal list entry","description":"Returns the stored list record that one entry points to. The id is the id of the entry, not of the list. The list comes back under result, not list, with its stored columns as text. Returns an empty object {} when the list no longer exists or the entry has no list. Returns 404 if no entry has the id. For the list in its usual shape, use GET /lists/{id} with the entry's list id.","operationId":"retrieve-contact-goal-list-list","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalListId"}],"responses":{"200":{"description":"The list under result, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"description":"The stored list record.","allOf":[{"$ref":"#/components/schemas/ContactGoalListList"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalListNotFound"}}}},"/contactGoalTags":{"get":{"summary":"List all contact goal tag entries","description":"A contact goal tag entry records one tag the contact had when it reached an automation goal. Each reached goal gets one entry for every tag the contact had at that moment. The entries are a snapshot: they do not change when the contact's tags change later. Filter by tag or by reached goal. Without an order, entries come in no guaranteed order. Page with limit and offset, or fetch specific entries with ids.","operationId":"list-all-contact-goal-tags","x-canonical-resource":"contactAutomations","parameters":[{"name":"filters[tagid]","in":"query","description":"Return only entries for this tag id. Exact match.","schema":{"type":"integer"}},{"name":"filters[subscribergoalid]","in":"query","description":"Return only entries for this reached goal (the contactGoal id on an entry). Exact match.","schema":{"type":"integer"}},{"name":"orders[tagid]","in":"query","description":"Sort by tag id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[subscribergoalid]","in":"query","description":"Sort by reached goal id. DESC, in any case, sorts high to low; any other value sorts low to high.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the entries.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated entry ids to return. When set, only those entries are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of entries under contactGoalTags, with the number of matching entries in meta.total. contactGoalTags is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalTags":{"type":"array","description":"The entries on this page.","items":{"$ref":"#/components/schemas/ContactGoalTag"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching entries, before limit and offset.","example":1}}}}},"examples":{"Result":{"value":{"contactGoalTags":[{"tagid":"5","subscribergoalid":"41","links":{"tag":"https://example.api-us1.com/api/3/contactGoalTags/12/tag","contactGoal":"https://example.api-us1.com/api/3/contactGoalTags/12/contactGoal"},"id":"12","tag":"5","contactGoal":"41"}],"meta":{"total":1}}}}}}}}}},"/contactGoalTags/{id}":{"get":{"summary":"Retrieve a contact goal tag entry","description":"A contact goal tag entry records one tag the contact had when it reached an automation goal. Returns one entry by its id. Returns 404 if no entry has the id.","operationId":"retrieve-a-contact-goal-tag","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalTagId"}],"responses":{"200":{"description":"The entry under contactGoalTag.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalTag":{"description":"The entry.","allOf":[{"$ref":"#/components/schemas/ContactGoalTag"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalTagNotFound"}}}},"/contactGoalTags/{id}/contactGoal":{"get":{"summary":"Retrieve the reached goal of a contact goal tag entry","description":"Returns the reached goal that one entry belongs to: the contact, the automation, the goal and when it was reached. The id is the id of the entry, not of the goal. Returns an empty object {} when the reached goal no longer exists or the entry has none. Returns 404 if no entry has the id.","operationId":"retrieve-contact-goal-tag-contact-goal","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalTagId"}],"responses":{"200":{"description":"The reached goal under contactGoal, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoal":{"description":"The reached goal.","allOf":[{"$ref":"#/components/schemas/ContactGoalTagContactGoal"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalTagNotFound"}}}},"/contactGoalTags/{id}/tag":{"get":{"summary":"Retrieve the tag of a contact goal tag entry","description":"Returns the tag that one entry points to, in the same shape as GET /tags/{id}. The id is the id of the entry, not of the tag. The tag is read as it is now, not as it was when the goal was reached, so its name may have changed since. Returns an empty object {} when the tag no longer exists or the entry's tagid is 0. Returns 404 if no entry has the id.","operationId":"retrieve-contact-goal-tag-tag","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalTagId"}],"responses":{"200":{"description":"The tag under tag, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"description":"The tag.","allOf":[{"$ref":"#/components/schemas/ContactGoalTagTag"}]}}}}}},"404":{"$ref":"#/components/responses/ContactGoalTagNotFound"}}}},"/contactGoals":{"get":{"summary":"List goal completions","description":"Lists goal completions. Each record says that a contact reached a goal in an automation. A contact normally has one record for each goal in each run through an automation. The filters are exact matches, and filters on different fields must all match. Several orders parameters sort in the order given. Without one, the order of the records is not guaranteed. Page with limit and offset, or use ids to fetch specific records.","operationId":"list-all-contact-goals","x-canonical-resource":"contactAutomations","parameters":[{"name":"limit","in":"query","description":"Number of goal completions to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Number of goal completions to skip. Use with limit to page through the list.","schema":{"type":"integer","format":"int32","default":0}},{"name":"ids","in":"query","description":"Comma-separated goal completion IDs to return. When set, limit does not apply, but offset still does.","schema":{"type":"string"}},{"name":"filters[goalid]","in":"query","description":"Return only completions of this goal ID.","schema":{"type":"integer","format":"int32"}},{"name":"filters[seriesid]","in":"query","description":"Return only completions in this automation ID.","schema":{"type":"integer","format":"int32"}},{"name":"filters[subscriberid]","in":"query","description":"Return only completions by this contact ID.","schema":{"type":"integer","format":"int32"}},{"name":"filters[subscriberseriesid]","in":"query","description":"Return only completions in this run through an automation (a contactAutomation ID).","schema":{"type":"integer","format":"int64"}},{"name":"filters[timespan]","in":"query","description":"Return only completions that took exactly this many seconds.","schema":{"type":"integer","format":"int32"}},{"name":"filters[tstamp]","in":"query","description":"Return only completions recorded at exactly this time, as YYYY-MM-DD HH:MM:SS in server local time. This is an exact match, not a range.","schema":{"type":"string"}},{"name":"orders[goalid]","in":"query","description":"Sort by goal ID. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[seriesid]","in":"query","description":"Sort by automation ID. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[subscriberid]","in":"query","description":"Sort by contact ID. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[subscriberseriesid]","in":"query","description":"Sort by contactAutomation ID. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[timespan]","in":"query","description":"Sort by the time the contact took to reach the goal. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"orders[tstamp]","in":"query","description":"Sort by when the completion was recorded. Case does not matter. Any value other than desc sorts ascending.","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"A page of goal completions under contactGoals, with the number of matching records in meta.total.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoals":{"type":"array","description":"The goal completions on this page. An empty list when there are none.","items":{"$ref":"#/components/schemas/ContactGoal"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, without limit and offset. When ids is set, the number of those ids that exist and match the filters.","example":1}}}}},"examples":{"Result":{"value":{"contactGoals":[{"goalid":"3","seriesid":"12","subscriberid":"6199","subscriberseriesid":"880","timespan":"86400","tstamp":"2026-09-01T14:03:12-05:00","links":{"goal":"https://example.api-us1.com/api/3/contactGoals/41/goal","automation":"https://example.api-us1.com/api/3/contactGoals/41/automation","contact":"https://example.api-us1.com/api/3/contactGoals/41/contact","contactAutomation":"https://example.api-us1.com/api/3/contactGoals/41/contactAutomation","contactGoalLists":"https://example.api-us1.com/api/3/contactGoals/41/contactGoalLists","contactGoalTags":"https://example.api-us1.com/api/3/contactGoals/41/contactGoalTags"},"id":"41","goal":"3","automation":"12","contact":"6199","contactAutomation":"880"}],"meta":{"total":1}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."}},"deprecated":false}},"/contactGoals/{id}":{"get":{"summary":"Retrieve a goal completion","description":"Returns one goal completion by its ID. The record says that a contact reached a goal in an automation. Returns 404 if no goal completion has the id.","operationId":"retrieve-a-contact-goal","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the goal completion.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The goal completion under contactGoal.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoal":{"description":"The goal completion.","allOf":[{"$ref":"#/components/schemas/ContactGoal"}]}}},"examples":{"Result":{"value":{"contactGoal":{"goalid":"3","seriesid":"12","subscriberid":"6199","subscriberseriesid":"880","timespan":"86400","tstamp":"2026-09-01T14:03:12-05:00","links":{"goal":"https://example.api-us1.com/api/3/contactGoals/41/goal","automation":"https://example.api-us1.com/api/3/contactGoals/41/automation","contact":"https://example.api-us1.com/api/3/contactGoals/41/contact","contactAutomation":"https://example.api-us1.com/api/3/contactGoals/41/contactAutomation","contactGoalLists":"https://example.api-us1.com/api/3/contactGoals/41/contactGoalLists","contactGoalTags":"https://example.api-us1.com/api/3/contactGoals/41/contactGoalTags"},"id":"41","goal":"3","automation":"12","contact":"6199","contactAutomation":"880"}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"description":"No goal completion has this id. Body: message, \"No Result found for SubscriberGoal with id\" followed by the id as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no goal completion has the id.","example":"No Result found for SubscriberGoal with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for SubscriberGoal with id 100"}}}}}}},"deprecated":false}},"/contactGoals/{id}/automation":{"get":{"summary":"Retrieve the automation of a goal completion","description":"Returns the automation that holds the goal, under automation. The id is the id of the goal completion, not of the automation. Returns an empty object {} when the automation no longer exists or seriesid is \"0\". Returns 404 if no goal completion has the id. The automation is also returned by GET /automations/{id}.","operationId":"retrieve-contact-goal-automation","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The automation under automation, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"description":"The automation.","allOf":[{"$ref":"#/components/schemas/ContactGoalAutomation"}]}}},"examples":{"Result":{"value":{"automation":{"name":"Welcome series","cdate":"2026-08-14T09:12:44-05:00","mdate":"2026-08-15T10:02:11-05:00","userid":"1","status":"1","entered":"120","exited":"40","hidden":"0","entitlements_violation":"0","source":"0","description":"","exit_on_unsubscribe":"0","exit_on_conversion":"0","multientry":"1","paused_at":null,"links":{"campaigns":"https://example.api-us1.com/api/3/automations/12/campaigns","contactGoals":"https://example.api-us1.com/api/3/automations/12/contactGoals","contactAutomations":"https://example.api-us1.com/api/3/automations/12/contactAutomations","blocks":"https://example.api-us1.com/api/3/automations/12/blocks","goals":"https://example.api-us1.com/api/3/automations/12/goals","sms":"https://example.api-us1.com/api/3/automations/12/sms","sitemessages":"https://example.api-us1.com/api/3/automations/12/sitemessages","triggers":"https://example.api-us1.com/api/3/automations/12/triggers"},"id":"12"}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactGoals/{id}/contact":{"get":{"summary":"Retrieve the contact of a goal completion","description":"Returns the contact who reached the goal, under contact. The id is the id of the goal completion, not of the contact. Returns an empty object {} when the contact no longer exists or subscriberid is \"0\". Users outside the Admin group also get {} when the contact is only on lists their group may not access. Returns 404 if no goal completion has the id. For the full contact record, see GET /contacts/{id}.","operationId":"retrieve-contact-goal-contact","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The contact under contact, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"description":"The contact.","allOf":[{"$ref":"#/components/schemas/ContactGoalContact"}]}}},"examples":{"Result":{"value":{"contact":{"cdate":"2026-08-14T09:10:02-05:00","email":"sam@example.com","phone":"","firstName":"Sam","lastName":"Example","orgid":"0","deleted":"0","udate":"2026-08-14T09:10:02-05:00","links":{"bounceLogs":"https://example.api-us1.com/api/3/contacts/6199/bounceLogs","contactAutomations":"https://example.api-us1.com/api/3/contacts/6199/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC","contactData":"https://example.api-us1.com/api/3/contacts/6199/contactData","contactGoals":"https://example.api-us1.com/api/3/contacts/6199/contactGoals","contactLists":"https://example.api-us1.com/api/3/contacts/6199/contactLists","contactLogs":"https://example.api-us1.com/api/3/contacts/6199/contactLogs","contactTags":"https://example.api-us1.com/api/3/contacts/6199/contactTags","contactDeals":"https://example.api-us1.com/api/3/contacts/6199/contactDeals","deals":"https://example.api-us1.com/api/3/contacts/6199/deals","fieldValues":"https://example.api-us1.com/api/3/contacts/6199/fieldValues","geoIps":"https://example.api-us1.com/api/3/contacts/6199/geoIps","notes":"https://example.api-us1.com/api/3/contacts/6199/notes","organization":"https://example.api-us1.com/api/3/contacts/6199/organization","plusAppend":"https://example.api-us1.com/api/3/contacts/6199/plusAppend","trackingLogs":"https://example.api-us1.com/api/3/contacts/6199/trackingLogs","scoreValues":"https://example.api-us1.com/api/3/contacts/6199/scoreValues","accountContacts":"https://example.api-us1.com/api/3/contacts/6199/accountContacts","automationEntryCounts":"https://example.api-us1.com/api/3/contacts/6199/automationEntryCounts"},"id":"6199","organization":null}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactGoals/{id}/contactAutomation":{"get":{"summary":"Retrieve the contact automation of a goal completion","description":"Returns the contact's run through the automation in which they reached the goal, under contactAutomation. The id is the id of the goal completion, not of the run. Returns an empty object {} when the run no longer exists or subscriberseriesid is \"0\". Returns 404 if no goal completion has the id. For the full run record, see GET /contactAutomations/{id}.","operationId":"retrieve-contact-goal-contact-automation","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The run under contactAutomation, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactAutomation":{"description":"The run.","allOf":[{"$ref":"#/components/schemas/ContactGoalContactAutomation"}]}}},"examples":{"Result":{"value":{"contactAutomation":{"contact":"6199","seriesid":"12","startid":"4","status":"1","batchid":null,"adddate":"2026-08-31T14:03:12-05:00","remdate":null,"timespan":null,"lastblock":"57","lastlogid":"940","lastdate":"2026-09-01T14:03:12-05:00","in_als":null,"completedElements":3,"totalElements":5,"completed":0,"completeValue":60,"links":{"automation":"https://example.api-us1.com/api/3/contactAutomations/880/automation","contact":"https://example.api-us1.com/api/3/contactAutomations/880/contact","contactGoals":"https://example.api-us1.com/api/3/contactAutomations/880/contactGoals","automationLogs":"https://example.api-us1.com/api/3/contactAutomations/880/automationLogs","subscriberSeriesEnd":"https://example.api-us1.com/api/3/contactAutomations/880/subscriberSeriesEnd"},"id":"880","automation":"12"}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactGoals/{id}/contactGoalLists":{"get":{"summary":"List the lists of a goal completion","description":"Returns the lists the contact was on when they reached the goal, under contactGoalLists. Each entry names one list. The entries are saved when the completion is recorded, so they do not follow later list changes. The list is not paged. The order is not guaranteed. Returns 404 if no goal completion has the id. For a list itself, use GET /lists/{id} with the entry's listid.","operationId":"list-contact-goal-contact-goal-lists","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The entries under contactGoalLists.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalLists":{"type":"array","description":"The entries. An empty list when there are none.","items":{"$ref":"#/components/schemas/ContactGoalList"}}}},"examples":{"Result":{"value":{"contactGoalLists":[{"listid":"3","subscribergoalid":"41","links":{"list":"https://example.api-us1.com/api/3/contactGoalLists/12/list","contactGoal":"https://example.api-us1.com/api/3/contactGoalLists/12/contactGoal"},"id":"12","list":"3","contactGoal":"41"}]}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactGoals/{id}/contactGoalTags":{"get":{"summary":"List the tags of a goal completion","description":"Returns the tags the contact had when they reached the goal, under contactGoalTags. Each entry names one tag. The entries are saved when the completion is recorded, so they do not follow later tag changes. The list is not paged. The order is not guaranteed. Returns 404 if no goal completion has the id. For a tag itself, use GET /tags/{id} with the entry's tagid.","operationId":"list-contact-goal-contact-goal-tags","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The entries under contactGoalTags.","content":{"application/json":{"schema":{"type":"object","properties":{"contactGoalTags":{"type":"array","description":"The entries. An empty list when there are none.","items":{"$ref":"#/components/schemas/ContactGoalTag"}}}},"examples":{"Result":{"value":{"contactGoalTags":[{"tagid":"5","subscribergoalid":"41","links":{"tag":"https://example.api-us1.com/api/3/contactGoalTags/12/tag","contactGoal":"https://example.api-us1.com/api/3/contactGoalTags/12/contactGoal"},"id":"12","tag":"5","contactGoal":"41"}]}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactGoals/{id}/goal":{"get":{"summary":"Retrieve the goal of a goal completion","description":"Returns the goal the contact reached, under goal. The id is the id of the goal completion, not of the goal. Returns an empty object {} when the goal no longer exists or goalid is \"0\". Returns 404 if no goal completion has the id. The goal is also returned by GET /goals/{id}.","operationId":"retrieve-contact-goal-goal","x-canonical-resource":"contactAutomations","parameters":[{"$ref":"#/components/parameters/ContactGoalId"}],"responses":{"200":{"description":"The goal under goal, or an empty object when there is none.","content":{"application/json":{"schema":{"type":"object","properties":{"goal":{"description":"The goal.","allOf":[{"$ref":"#/components/schemas/ContactGoalGoal"}]}}},"examples":{"Result":{"value":{"goal":{"blockid":"57","seriesid":"12","name":"Made a purchase","cdate":"2026-08-20T10:15:00-05:00","dirty_stats":"0","links":{"automation":"https://example.api-us1.com/api/3/goals/3/automation","automationBlock":"https://example.api-us1.com/api/3/goals/3/automationBlock","contactGoals":"https://example.api-us1.com/api/3/goals/3/contactGoals"},"id":"3","automation":"12","automationBlock":"57"}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."},"404":{"$ref":"#/components/responses/ContactGoalNotFound"}},"deprecated":false}},"/contactImports":{"get":{"summary":"List contact import log rows","description":"Each row is one line of the log that imports write as they run: one row for each row processed, imported or not. When a contact was imported but list subscriptions were skipped, there is one row per skipped subscription instead (res 2). Imports started from the app's import tool, imports submitted through POST /import/bulk_import, older sync imports and integrations' automatic syncs all write rows here. This endpoint returns every row in the account, with no way to narrow it to one import: filters and orders are ignored, and rows have no defined order. To see how one import went, use the endpoint for its kind: for an import started from the app or by an integration, GET /import/history to find it (for an app import, its processid matches the processid on these rows) and GET /import/history/{importId}/{type} for its failed or partly imported rows and their reasons; for an import submitted through POST /import/bulk_import, GET /import/info with its batchId. Use this endpoint only to fetch specific rows by ids. Paginated with limit (default 20, at most 100) and offset. No permission beyond API access is checked: any API user can read every row in the account, including emails from other groups' imports, unlike GET /import/history.","operationId":"list-contact-import-log-rows","x-canonical-resource":"import","parameters":[{"name":"limit","in":"query","description":"Number of rows to return. Defaults to 20; values above 100 are treated as 100. A value of 0, a negative number or a non-numeric value returns every row and ignores offset.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of rows to skip. Use with limit to page through the rows.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated row IDs to return. When set, only those rows are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"The rows. contactImports is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactImports":{"type":"array","description":"The log rows on this page.","items":{"$ref":"#/components/schemas/ContactImport"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of log rows in the account, or, when ids is set, the number of those ids that exist.","example":1}}}}},"examples":{"Result":{"value":{"contactImports":[{"processid":"3401","autosync":null,"email":"sam@example.com","res":"1","code":"0","msg":"Imported under ID: 6199.","tstamp":"2026-09-01T14:03:12-05:00","links":{"autosync":"https://example.api-us1.com/api/3/contactImports/19/autosync"},"id":"19"}],"meta":{"total":1}}}}}}}},"deprecated":false}},"/contactImports/{id}":{"get":{"summary":"Retrieve a contact import log row","description":"One row of the contact import log, by its ID. Each row is one line of the log that imports write as they run: one row for each row processed, imported or not. When a contact was imported but list subscriptions were skipped, there is one row per skipped subscription instead (res 2). Imports started from the app's import tool, imports submitted through POST /import/bulk_import, older sync imports and integrations' automatic syncs all write rows here. To see how one import went, use the endpoint for its kind: for an import started from the app or by an integration, GET /import/history to find it (for an app import, its processid matches the processid on these rows) and GET /import/history/{importId}/{type} for its failed or partly imported rows and their reasons; for an import submitted through POST /import/bulk_import, GET /import/info with its batchId. Returns 404 if no row has that ID. No permission beyond API access is checked: any API user can read every row in the account, including emails from other groups' imports, unlike GET /import/history.","operationId":"retrieve-a-contact-import-log-row","x-canonical-resource":"import","parameters":[{"name":"id","in":"path","description":"ID of the log row.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The row.","content":{"application/json":{"schema":{"type":"object","properties":{"contactImport":{"$ref":"#/components/schemas/ContactImport"}}},"examples":{"Result":{"value":{"contactImport":{"processid":"3401","autosync":null,"email":"sam@example.com","res":"1","code":"0","msg":"Imported under ID: 6199.","tstamp":"2026-09-01T14:03:12-05:00","links":{"autosync":"https://example.api-us1.com/api/3/contactImports/19/autosync"},"id":"19"}}}}}}},"404":{"description":"No log row has that ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for SubscriberImport with id 121"}}},"examples":{"Result":{"value":{"message":"No Result found for SubscriberImport with id 121"}}}}}}},"deprecated":false}},"/contactLists":{"get":{"summary":"List contact subscriptions to lists","description":"One row per contact-to-list subscription, carrying the contact id, the list id, the subscription status and its dates. Filter with contact to see every list one contact is on, with status to see the subscriptions in one state, or with sourceIds to see the subscriptions created through given sources, for example imports. There is no filter by list: a listid parameter is ignored and the unfiltered rows come back. There is no filter by date. Order parameters are ignored too: rows come back in table order whatever orders[...] is sent. meta.total is the number of subscription rows that match, as a string, not a number of contacts. To list or count the contacts on a list, use GET /contacts with listid, adding status for one membership status and meta=only for a count without records. 20 rows per request by default and at most 100; page with offset.","operationId":"list-all-contact-list-subscriptions","x-canonical-resource":"contactLists","parameters":[{"name":"contact","in":"query","description":"Return only the subscriptions of this contact id.","schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Return only subscriptions in this state: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced.","schema":{"type":"integer","format":"int32","enum":[0,1,2,3]}},{"name":"sourceIds","in":"query","style":"form","explode":true,"description":"Return only subscriptions created through these sources. Repeat the key for several values: sourceIds[]=1&sourceIds[]=5. A comma-separated value is not split: only its first number is used. Values: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail.","schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"limit","in":"query","description":"Number of subscription rows to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of subscription rows to skip before returning results. Use with limit to page.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The matching subscriptions and their total.","content":{"application/json":{"schema":{"type":"object","properties":{"contactLists":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"19","description":"Id of the contact."},"list":{"type":"string","example":"1","description":"Id of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form."},"seriesid":{"type":"string","example":"0","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation."},"sdate":{"type":"string","example":"2021-04-08T11:17:44-05:00","description":"When the contact was last subscribed to the list. Reset when a contact resubscribes."},"udate":{"type":["string","null"],"example":"2021-05-12T11:10:06-05:00","description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate."},"status":{"type":"string","example":"3","description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","example":"1","description":"Whether list autoresponders are sent to this contact for this list: 1 yes (the default), 0 suppressed for this membership."},"sync":{"type":"string","example":"1","description":"ID of the import or sync process that created the membership; 0 when it was not created by one."},"unsubreason":{"description":"The reason recorded with an unsubscribe. Empty when none was given."},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"first_name":{"type":"string","example":"John","description":"The contact's first name at the time of the request."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name at the time of the request."},"ip4Sub":{"type":"string","example":"XXXXXXXXXX","description":"The IPv4 address recorded when the contact subscribed, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"sourceid":{"type":"string","example":"1","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise."},"ip4_last":{"type":"string","example":"0","description":"The IPv4 address recorded on the last subscription change, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"ip4Unsub":{"type":"string","example":"0","description":"The IPv4 address recorded when the contact unsubscribed online, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"created_timestamp":{"type":"string","example":"2021-04-08 11:17:44","description":"When the membership record was created, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2021-05-12 11:10:06","description":"When the membership record was last changed, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"created_by":{"description":"ID of the account user who created the membership. Usually null."},"updated_by":{"description":"ID of the account user who last changed the membership. Usually null."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise."},"channel":{"type":["string","null"],"example":"email","description":"The list's channel, email or sms."},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/automation","description":"URL that returns the automation that subscribed the contact (seriesid)."},"list":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/list","description":"URL that returns the list."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/contact","description":"URL that returns the contact."},"form":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/form","description":"URL that returns the form that brought the contact onto the list."},"autosyncLog":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog","description":"URL that returns the sync run that created the membership."},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/campaign","description":"URL that returns the campaign the contact unsubscribed from."},"unsubscribeAutomation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation","description":"URL that returns the automation that unsubscribed the contact."},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/message","description":"URL that returns the message the contact unsubscribed from."}},"description":"URLs of the reads for the records this membership points to. A read returns an empty object when the membership points to none."},"id":{"type":"string","example":"19","description":"ID of the membership record."},"automation":{"description":"Same value as seriesid, or null when seriesid is 0. Deprecated."}}},"description":"One item per subscription row."},"meta":{"type":"object","properties":{"total":{"type":"string","example":"4945","description":"Number of subscription rows that match the filters, as a string. Not a number of contacts."}},"description":"Information about the whole result."}}}}}}}},"post":{"summary":"Update list status for a contact","description":"Subscribes a contact to a list, or changes the status of the contact's subscription to it. If the contact already has a membership on the list, that membership is updated and the response is 200; otherwise a new one is created and the response is 201. Needs the permission to edit contacts.\n\nIf the contact's membership on the list is currently unsubscribed, any change to it needs the permission to resubscribe contacts, whatever status you send, including another unsubscribe. Without it the request fails with 422.\n\nAny status other than 2 needs a contact that exists and a list that exists (404 otherwise), and a contact with an email address for an email list or with a phone number for an SMS list (400 otherwise). When the status becomes 1, sdate is set to now, udate and the unsubscribe details are cleared, the automations that start when a contact subscribes to this list are started, and the list's subscribe webhooks are called. A new active membership also gets the list's subscribe autoresponders and, when the list is set to send it, the list's last campaign; neither is sent when the contact is excluded from the list. When the list has a subscription notification set up, the notification email is also sent to the addresses configured on the list (not to the contact), even when the contact is excluded from the list.\n\nUnsubscribing (status 2) a contact who was on the list and not already unsubscribed runs the app's unsubscribe for that list: the automations that start when a contact unsubscribes from the list are started, the list's unsubscribe webhooks are called, the list's unsubscribe autoresponders are sent to the contact, and the list's unsubscribe notification email goes to the addresses configured on the list; each only when the list has one. No unsubscribe reason is recorded; this endpoint cannot set one. The membership is kept, with status 2 and udate set. The contact is not checked when unsubscribing.\n\nWith an API key, sourceid is stored as 4 (API), unless you send the number 8 (SMS).","operationId":"update-list-status-for-contact","x-canonical-resource":"contactLists","x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactList":{"properties":{"list":{"type":["integer","string"],"description":"Id of the list. Must be a positive number.","example":2},"contact":{"type":["integer","string"],"description":"Id of the contact. Must be a positive number.","example":1},"status":{"type":["integer","string"],"enum":[0,1,2,3,"0","1","2","3"],"description":"1 to subscribe, 2 to unsubscribe. 0 (unconfirmed) and 3 (bounced) are also accepted and stored as sent. See the operation description for what each does.","example":1},"sourceid":{"type":["integer","string"],"description":"With an API key this is stored as 4 (API) whatever you send, unless you send the number 8 (SMS), which is kept. The string \"8\" is stored as 4.","example":8},"responder":{"type":["integer","string"],"description":"1 (the default) or 0. 0 stops the list's later, scheduled autoresponders for this membership. It does not stop the subscribe autoresponders sent at once when the membership is created; use suppressInstantAutoresponder for that.","example":1},"sendInstantAutoresponder":{"type":["boolean","string","integer"],"description":"Set to true to send the list's subscribe autoresponders even when the contact was already on the list or had unsubscribed. With status 2, sends the list's unsubscribe autoresponders instead. Does nothing for status 0 or 3, when the contact is excluded from the list, or when the account does not have Campaigns. Cannot be true together with suppressInstantAutoresponder. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."},"suppressInstantAutoresponder":{"type":["boolean","string","integer"],"description":"Set to true to not send the list's subscribe autoresponders when this request creates the membership. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."},"sendLastCampaign":{"type":["boolean","string","integer"],"description":"Set to true to send the contact the last campaign sent to the list, even when the list is not set up to do that. Only for status 1, and not when the contact is excluded from the list. Accepts true, false, 1, 0 and the strings true, false, yes, no, on, off, 1 and 0, in any letter case. An empty string counts as false. Other values fail with 422."}},"required":["list","contact","status"],"type":"object","description":"The subscription to write."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"contactList":{"list":2,"contact":1,"status":1}}}}}}},"responses":{"200":{"description":"The contact already had a membership on the list, and it was updated.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2017-07-24T12:09:52-05:00\",\n            \"email\": \"johndoe@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"John\",\n            \"lastName\": \"Doe\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": \"\",\n            \"hash\": \"1234567890\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"1\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": \"2018-10-16T13:52:32-05:00\",\n            \"udate\": \"2018-10-16T13:50:18-05:00\",\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2018-10-01 08:40:10\",\n            \"updated_utc_timestamp\": \"2018-10-16 13:50:18\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/1/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/1/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/1/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/1/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/1/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/1/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/1/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/1/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/3/contacts/1/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/1/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/1/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/1/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/1/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/1/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/1/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/1/scoreValues\"\n            },\n            \"id\": \"1\",\n            \"organization\": null\n        }\n    ],\n    \"contactList\": {\n        \"contact\": \"1\",\n        \"list\": \"2\",\n        \"form\": null,\n        \"seriesid\": \"0\",\n        \"sdate\": \"2018-10-16T13:52:35-05:00\",\n        \"udate\": null,\n        \"status\": 1,\n        \"responder\": \"1\",\n        \"sync\": \"0\",\n        \"unsubreason\": \"\",\n        \"campaign\": null,\n        \"message\": null,\n        \"first_name\": \"John\",\n        \"last_name\": \"Doe\",\n        \"ip4Sub\": \"0\",\n        \"sourceid\": \"3\",\n        \"autosyncLog\": null,\n        \"ip4_last\": \"0\",\n        \"ip4Unsub\": \"0\",\n        \"created_timestamp\": \"2018-10-16 13:52:35\",\n        \"updated_timestamp\": \"2018-10-16 13:52:35\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"unsubscribeAutomation\": null,\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/:version/contactLists/2/automation\",\n            \"list\": \"https://:account.api-us1.com/api/:version/contactLists/2/list\",\n            \"contact\": \"https://:account.api-us1.com/api/:version/contactLists/2/contact\",\n            \"form\": \"https://:account.api-us1.com/api/:version/contactLists/2/form\",\n            \"autosyncLog\": \"https://:account.api-us1.com/api/:version/contactLists/2/autosyncLog\",\n            \"campaign\": \"https://:account.api-us1.com/api/:version/contactLists/2/campaign\",\n            \"unsubscribeAutomation\": \"https://:account.api-us1.com/api/:version/contactLists/2/unsubscribeAutomation\",\n            \"message\": \"https://:account.api-us1.com/api/:version/contactLists/2/message\"\n        },\n        \"id\": \"2\",\n        \"automation\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"type":"object","properties":{"cdate":{"type":["string","null"],"example":"2017-07-24T12:09:52-05:00","description":"When the contact was created, in ISO 8601 with the account's UTC offset. Null when not recorded."},"email":{"type":["string","null"],"example":"johndoe@example.com","description":"The contact's email address. Null when the contact was created without one."},"phone":{"type":"string","example":"","description":"The contact's phone number. Empty when not set."},"firstName":{"type":"string","example":"John","description":"The contact's first name. Empty when not set."},"lastName":{"type":"string","example":"Doe","description":"The contact's last name. Empty when not set."},"orgid":{"type":"string","example":"0","description":"ID of the account the contact belongs to through the legacy account link. \"0\" when there is none. The current account link is accountContacts."},"segmentio_id":{"type":"string","example":"","description":"ID of the contact in the Segment integration. Empty when the contact did not come from Segment."},"bounced_hard":{"type":"string","example":"0","description":"Number of hard bounces recorded for the contact. Some update paths reset it to \"0\" when the email address changes."},"bounced_soft":{"type":"string","example":"0","description":"Number of soft bounces recorded for the contact."},"bounced_date":{"type":["string","null"],"example":null,"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced."},"ip":{"type":"string","example":"0","description":"IPv4 address the contact was added from, stored as a whole number in the form PHP's ip2long produces. \"0\" when not recorded."},"ua":{"type":["string","null"],"example":"","description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded."},"hash":{"type":"string","example":"1234567890","description":"A 32-character identifier for the contact. Set by the database when the contact is created and replaced by the database when the email address changes. Some older creation paths derive it from the id and email address."},"socialdata_lastcheck":{"type":["string","null"],"example":null,"description":"When social profile data was last looked up for the contact, as YYYY-MM-DD HH:MM:SS. Null when never looked up."},"email_local":{"type":"string","example":"","description":"The part of the email address before the @ sign. Not maintained by current code, so usually empty."},"email_domain":{"type":"string","example":"","description":"The part of the email address after the @ sign. Set by the database when the contact is inserted and whenever the email address changes."},"sentcnt":{"type":"string","example":"1","description":"Number of campaigns that have been sent to the contact."},"rating_tstamp":{"type":["string","null"],"example":null,"description":"Date the contact's engagement rating last changed, as YYYY-MM-DD. Null when never rated. The rating itself is not returned."},"gravatar":{"type":"string","example":"0","description":"Gravatar lookup status. \"0\" not looked up yet, \"1\" looked up and no image found, \"2\" looked up and an image found, \"3\" use the image from the contact's appended social profile data (plusAppend) instead."},"deleted":{"type":"string","example":"0","description":"\"1\" when the contact has been soft-deleted. A deleted contact is moved to the archive, so contacts returned here normally have \"0\"."},"anonymized":{"type":"string","example":"0","description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise."},"adate":{"type":["string","null"],"example":"2018-10-16T13:52:32-05:00","description":"When activity was last generated for the contact, in ISO 8601 with the account's UTC offset. Null when activity has never been generated."},"udate":{"type":["string","null"],"example":"2018-10-16T13:50:18-05:00","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Moves on any save of the record, including saves that change nothing, and, through database triggers, on list, tag, custom field, score, note and task changes."},"deleted_at":{"type":["string","null"],"example":null,"description":"When the contact was soft-deleted, as YYYY-MM-DD HH:MM:SS. Null for a contact that has not been deleted."},"created_utc_timestamp":{"type":"string","example":"2018-10-01 08:40:10","description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS. Set by the database."},"updated_utc_timestamp":{"type":"string","example":"2018-10-16 13:50:18","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Set by the database on every change and by the application on save. Despite the name it is not in UTC; it moves on every change to the row, including counters such as sentcnt that do not move udate."},"links":{"type":"object","properties":{"bounceLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/bounceLogs","description":"URL of the read that lists the contact's bounce logs."},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactAutomations","description":"URL of the read that lists the automations the contact has entered. The URL includes limit=2500 and orders[lastdate]=DESC."},"contactData":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactData","description":"URL of the read for the contact's engagement data."},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactGoals","description":"URL of the read that lists the automation goals the contact has met."},"contactLists":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactLists","description":"URL of the read that lists the contact's list memberships."},"contactLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactLogs","description":"URL of the read that lists the contact's logs."},"contactTags":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactTags","description":"URL of the read that lists the tags on the contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/contactDeals","description":"URL of the read that lists the links between the contact and deals."},"deals":{"type":"string","example":"https://:account.api-us1.com/api/3/contacts/1/deals","description":"URL of the read that lists the contact's deals."},"fieldValues":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/fieldValues","description":"URL of the read that lists the contact's custom field values."},"geoIps":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/geoIps","description":"URL of the read that lists the IP addresses recorded for the contact."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/notes","description":"URL of the read that lists the contact's notes."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/organization","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts."},"plusAppend":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/plusAppend","description":"URL of the read for the contact's appended social profile data."},"trackingLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/trackingLogs","description":"URL of the read that lists the contact's tracking logs."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/1/scoreValues","description":"URL of the read that lists the contact's score values."}},"description":"URLs of the reads for the contact's related records."},"id":{"type":"string","example":"1","description":"ID of the contact."},"organization":{"type":["string","null"],"description":"ID of the account the contact belongs to through the legacy account link. The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."},"orgname":{"type":"string","description":"Name of the account named by orgid. Empty when there is none. Kept in step with orgid when the contact is saved.","example":""},"edate":{"type":["string","null"],"description":"Watermark for email activity generation: the contact's stored emails have been turned into activities up to this time. In ISO 8601 with the account's UTC offset. Null when email activity has never been generated for the contact.","example":null},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS. Set by the database.","example":"2007-05-05 12:49:09"},"updated_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Set by the database on every change and by the application on save.","example":"2007-05-05 12:49:09"},"created_by":{"type":["string","null"],"description":"ID of the user who created the contact. Null when not recorded.","example":null},"updated_by":{"type":["string","null"],"description":"ID of the user who last changed the contact. Null when not recorded.","example":null},"mpp_tracking":{"type":"string","description":"\"1\" when the contact has been detected as using Apple Mail Privacy Protection, \"0\" otherwise.","example":"0"},"last_click_date":{"type":["string","null"],"description":"When the contact last clicked a link in an email, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"last_open_date":{"type":["string","null"],"description":"When the contact last opened an email, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"last_mpp_open_date":{"type":["string","null"],"description":"When an open from Apple Mail Privacy Protection was last recorded for the contact, as YYYY-MM-DD HH:MM:SS. Null when never.","example":null},"best_send_hour":{"type":["string","null"],"description":"Hour of the day that predictive sending has chosen as the best time to email the contact. Null when not computed.","example":null},"sms_consent":{"type":["string","null"],"description":"\"1\" when the contact has agreed to receive SMS marketing, \"0\" when they have declined. Null when consent was never recorded, which counts as no consent.","example":null},"sms_consent_updated_at":{"type":["string","null"],"description":"When the SMS consent status last changed, as YYYY-MM-DD HH:MM:SS. Null when never recorded.","example":null},"whatsapp_id":{"type":["string","null"],"description":"The contact's WhatsApp user id from Meta. Null when the contact has no WhatsApp identity.","example":null},"whatsapp_username":{"type":["string","null"],"description":"The contact's WhatsApp username. Null when the contact has no WhatsApp identity.","example":null}}},"description":"The contact the membership belongs to, as a one-item array. The whole contact row is returned; the properties listed here are not complete, and GET /contacts/{id} describes every field. May be absent when the request changed nothing on the membership."},"contactList":{"type":"object","properties":{"contact":{"type":"string","example":"1","description":"ID of the contact."},"list":{"type":"string","example":"2","description":"ID of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form."},"seriesid":{"type":"string","example":"0","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation."},"sdate":{"type":"string","example":"2018-10-16T13:52:35-05:00","description":"When the contact was last subscribed to the list. Reset when a contact resubscribes."},"status":{"type":["integer","string"],"example":1,"default":0,"description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","example":"1","description":"Whether list autoresponders are sent to this contact for this list: 1 yes (the default), 0 suppressed for this membership."},"sync":{"type":"string","example":"0","description":"ID of the import or sync process that created the membership; 0 when it was not created by one."},"unsubreason":{"type":"string","example":"","description":"The reason recorded with an unsubscribe. Empty when none was given."},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise, and absent when an automation unsubscribed the contact (see unsubscribeAutomation)."},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"first_name":{"type":"string","example":"John","description":"The contact's first name, copied when the membership was created. It is not updated later, so it can be out of date."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name, copied when the membership was created. It is not updated later, so it can be out of date."},"ip4Sub":{"type":"string","example":"0","description":"The IPv4 address recorded when the contact subscribed, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"sourceid":{"type":"string","example":"3","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise."},"ip4_last":{"type":"string","example":"0","description":"The IPv4 address recorded on the last subscription change, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"ip4Unsub":{"type":"string","example":"0","description":"The IPv4 address recorded when the contact unsubscribed online, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise."},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/automation","description":"URL that returns the automation that subscribed the contact (seriesid)."},"list":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/list","description":"URL that returns the list."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/contact","description":"URL that returns the contact."},"form":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/form","description":"URL that returns the form that brought the contact onto the list."},"autosyncLog":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/autosyncLog","description":"URL that returns the sync run that created the membership."},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/campaign","description":"URL that returns the campaign the contact unsubscribed from."},"unsubscribeAutomation":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/unsubscribeAutomation","description":"URL that returns the automation that unsubscribed the contact."},"message":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/2/message","description":"URL that returns the message the contact unsubscribed from."}},"description":"URLs of the reads for the records this membership points to. A read returns an empty object when the membership points to none."},"id":{"type":"string","example":"2","description":"ID of the membership record."},"automation":{"description":"Same value as seriesid, or null when seriesid is 0. Deprecated."},"udate":{"type":["string","null"],"example":"2021-05-12T11:10:06-05:00","description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate."},"created_timestamp":{"type":"string","example":"2021-04-08 11:17:44","description":"When the membership record was created, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2021-05-12 11:10:06","description":"When the membership record was last changed before this request, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS. This request's own change is not reflected."},"created_by":{"description":"ID of the account user who created the membership. Usually null."},"updated_by":{"description":"ID of the account user who last changed the membership. Usually null."}},"description":"The membership after the write. When an existing membership was updated (200), this is the full row, as in GET /contactLists/{id}."}}}}}},"201":{"description":"A new membership was created. The body has the same fields as the 200 response: contacts and contactList.","content":{"application/json":{"schema":{"type":"object","description":"The same fields as the 200 response."}}}},"400":{"description":"The request was refused. The body is empty (Request body is empty.) or not valid JSON (Could not decode request body.); or it is a JSON value that is not an object: 0, false and null get a string status and no title, other values the number 400 and a title. Or, for any status other than 2, the contact has no email address and the list is an email list, or no phone number and the list is an SMS list.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status. A string for most errors; the number 400, with a title, for a JSON value that is not an object (other than 0, false or null).","example":"400"},"title":{"type":"string","description":"Only with a numeric status: Bad Request.","example":"Bad Request"},"detail":{"type":"string","description":"What went wrong.","example":"You cannot subscribe a contact without an email address to an email list"}}}}}},"example":{"errors":[{"status":"400","detail":"You cannot subscribe a contact without an email address to an email list"}]}}}},"403":{"description":"The user does not have the permission to edit contacts.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as a string.","example":"403"},"detail":{"type":"string","description":"What went wrong.","example":"No permission to subscribe"}}}}}},"example":{"errors":[{"status":"403","detail":"No permission to subscribe"}]}}}},"404":{"description":"For any status other than 2, the contact or the list does not exist.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for Subscriber with id 5"}}},"example":{"message":"No Result found for Subscriber with id 5"}}}},"422":{"description":"The request was not valid: contactList, or its contact, list or status, is missing or not valid (one errors item per problem, with source.pointer naming the field); a mail option is not a boolean, or sendInstantAutoresponder and suppressInstantAutoresponder are both true; or an unsubscribe names a list that does not exist. Refusing a change to an unsubscribed membership, when the user lacks the permission to resubscribe contacts, returns a plain sentence instead of a JSON object: Unsubscribed contact cannot be re-subscribed through API. The Content-Type is still application/json.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status. Missing when an unsubscribe names a list that does not exist.","example":422},"title":{"type":"string","description":"The kind of problem.","example":"Invalid attribute"},"detail":{"type":"string","description":"What went wrong.","example":"This field is missing."},"code":{"type":"string","description":"Only when an unsubscribe names a list that does not exist.","example":"related_missing"},"error":{"type":"string","description":"Only when an unsubscribe names a list that does not exist.","example":"list_not_exist"},"source":{"type":"object","description":"Where the problem is.","properties":{"pointer":{"type":"string","description":"The field that failed.","example":"/data/attributes/[contactList][contact]"}}}}}}}},{"type":"string","description":"The resubscribe refusal, as a plain sentence.","example":"Unsubscribed contact cannot be re-subscribed through API."}]}}}}},"deprecated":false}},"/contactLists/{id}":{"get":{"summary":"Retrieve a contact list subscription","description":"Returns one contact-to-list membership by its own ID. To find the ID, list subscriptions with `GET /contactLists?contact=` or follow `links.contactLists` on a contact.","operationId":"retrieve-a-contact-list-subscription","x-canonical-resource":"contactLists","parameters":[{"name":"id","in":"path","description":"ID of the contact list subscription (the contactList record, not the list)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The membership.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactList\": {\n        \"contact\": \"19\",\n        \"list\": \"1\",\n        \"form\": null,\n        \"seriesid\": \"0\",\n        \"sdate\": \"2021-04-08T11:17:44-05:00\",\n        \"udate\": null,\n        \"status\": \"1\",\n        \"responder\": \"1\",\n        \"sync\": \"1\",\n        \"unsubreason\": \"\",\n        \"campaign\": null,\n        \"message\": null,\n        \"first_name\": \"John\",\n        \"last_name\": \"Doe\",\n        \"ip4Sub\": \"0\",\n        \"sourceid\": \"4\",\n        \"autosyncLog\": null,\n        \"ip4_last\": \"0\",\n        \"ip4Unsub\": \"0\",\n        \"created_timestamp\": \"2021-04-08 11:17:44\",\n        \"updated_timestamp\": \"2021-04-08 11:17:44\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"unsubscribeAutomation\": null,\n        \"channel\": \"email\",\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/3/contactLists/19/automation\",\n            \"list\": \"https://:account.api-us1.com/api/3/contactLists/19/list\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactLists/19/contact\",\n            \"form\": \"https://:account.api-us1.com/api/3/contactLists/19/form\",\n            \"autosyncLog\": \"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog\",\n            \"campaign\": \"https://:account.api-us1.com/api/3/contactLists/19/campaign\",\n            \"unsubscribeAutomation\": \"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation\",\n            \"message\": \"https://:account.api-us1.com/api/3/contactLists/19/message\"\n        },\n        \"id\": \"19\",\n        \"automation\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contactList":{"type":"object","properties":{"contact":{"type":"string","example":"19","description":"Id of the contact."},"list":{"type":"string","example":"1","description":"Id of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form."},"seriesid":{"type":"string","example":"0","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation."},"sdate":{"type":"string","example":"2021-04-08T11:17:44-05:00","description":"When the contact was last subscribed to the list. Reset when a contact resubscribes."},"udate":{"type":["string","null"],"example":"2021-05-12T11:10:06-05:00","description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate."},"status":{"type":"string","example":"3","description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","example":"1","description":"Whether list autoresponders are sent to this contact for this list: 1 yes (the default), 0 suppressed for this membership."},"sync":{"type":"string","example":"1","description":"ID of the import or sync process that created the membership; 0 when it was not created by one."},"unsubreason":{"description":"The reason recorded with an unsubscribe. Empty when none was given."},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"first_name":{"type":"string","example":"John","description":"The contact's first name at the time of the request."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name at the time of the request."},"ip4Sub":{"type":"string","example":"XXXXXXXXXX","description":"The IPv4 address recorded when the contact subscribed, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"sourceid":{"type":"string","example":"1","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise."},"ip4_last":{"type":"string","example":"0","description":"The IPv4 address recorded on the last subscription change, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"ip4Unsub":{"type":"string","example":"0","description":"The IPv4 address recorded when the contact unsubscribed online, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"created_timestamp":{"type":"string","example":"2021-04-08 11:17:44","description":"When the membership record was created, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2021-05-12 11:10:06","description":"When the membership record was last changed, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"created_by":{"description":"ID of the account user who created the membership. Usually null."},"updated_by":{"description":"ID of the account user who last changed the membership. Usually null."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise."},"channel":{"type":["string","null"],"example":"email","description":"The list's channel, email or sms."},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/automation","description":"URL that returns the automation that subscribed the contact (seriesid)."},"list":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/list","description":"URL that returns the list."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/contact","description":"URL that returns the contact."},"form":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/form","description":"URL that returns the form that brought the contact onto the list."},"autosyncLog":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog","description":"URL that returns the sync run that created the membership."},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/campaign","description":"URL that returns the campaign the contact unsubscribed from."},"unsubscribeAutomation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation","description":"URL that returns the automation that unsubscribed the contact."},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/message","description":"URL that returns the message the contact unsubscribed from."}},"description":"URLs of the reads for the records this membership points to. A read returns an empty object when the membership points to none."},"id":{"type":"string","example":"19","description":"ID of the membership record."},"automation":{"description":"Same value as seriesid, or null when seriesid is 0. Deprecated."}},"description":"The membership."}}}}}},"404":{"description":"No membership has this id, or the list it belongs to was deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberList with id 19\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberList with id 19","description":"What was not found."}}}}}}},"deprecated":false},"put":{"summary":"Update a contact list subscription","description":"Updates one membership by its ID. `list`, `contact` and `status` must be sent and must match the record; `status` 2 unsubscribes, 1 re-subscribes. Re-subscribing a contact who unsubscribed requires the resubscribe permission and is refused for self-unsubscribes. Subscribing to an email list needs a contact with an email address, and to an SMS list a contact with a phone number. `POST /contactLists` does the same by list and contact without the record ID. To take a contact off a list, set `status` 2; the membership record is kept as consent history. PATCH /contactLists/{id} does the same thing.","operationId":"update-a-contact-list-subscription","x-canonical-resource":"contactLists","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contact list subscription (the contactList record, not the list)","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactList":{"type":"object","properties":{"list":{"type":"string","description":"ID of the list; must match the record"},"contact":{"type":"string","description":"ID of the contact; must match the record"},"status":{"type":"string","description":"0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced. Set 2 to unsubscribe and 1 to subscribe again."},"sourceid":{"type":"integer","description":"How the subscription was created; set 4 when re-subscribing through the API","format":"int32"},"responder":{"type":"string","description":"1 to keep sending list autoresponders to this contact (default), 0 to suppress them for this membership"}},"required":["list","contact","status"],"description":"The membership fields to change."}},"additionalProperties":false},"examples":{"Unsubscribe":{"value":{"contactList":{"list":"1","contact":"19","status":"2"}}},"Re-subscribe":{"value":{"contactList":{"list":"1","contact":"19","status":"1","sourceid":4}}}}}}},"responses":{"200":{"description":"The membership after the change.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactList\": {\n        \"contact\": \"19\",\n        \"list\": \"1\",\n        \"form\": null,\n        \"seriesid\": \"0\",\n        \"sdate\": \"2021-04-08T11:17:44-05:00\",\n        \"udate\": null,\n        \"status\": \"1\",\n        \"responder\": \"1\",\n        \"sync\": \"1\",\n        \"unsubreason\": \"\",\n        \"campaign\": null,\n        \"message\": null,\n        \"first_name\": \"John\",\n        \"last_name\": \"Doe\",\n        \"ip4Sub\": \"0\",\n        \"sourceid\": \"4\",\n        \"autosyncLog\": null,\n        \"ip4_last\": \"0\",\n        \"ip4Unsub\": \"0\",\n        \"created_timestamp\": \"2021-04-08 11:17:44\",\n        \"updated_timestamp\": \"2021-04-08 11:17:44\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"unsubscribeAutomation\": null,\n        \"channel\": \"email\",\n        \"links\": {\n            \"automation\": \"https://:account.api-us1.com/api/3/contactLists/19/automation\",\n            \"list\": \"https://:account.api-us1.com/api/3/contactLists/19/list\",\n            \"contact\": \"https://:account.api-us1.com/api/3/contactLists/19/contact\",\n            \"form\": \"https://:account.api-us1.com/api/3/contactLists/19/form\",\n            \"autosyncLog\": \"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog\",\n            \"campaign\": \"https://:account.api-us1.com/api/3/contactLists/19/campaign\",\n            \"unsubscribeAutomation\": \"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation\",\n            \"message\": \"https://:account.api-us1.com/api/3/contactLists/19/message\"\n        },\n        \"id\": \"19\",\n        \"automation\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contactList":{"type":"object","properties":{"contact":{"type":"string","example":"19","description":"Id of the contact."},"list":{"type":"string","example":"1","description":"Id of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form."},"seriesid":{"type":"string","example":"0","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation."},"sdate":{"type":"string","example":"2021-04-08T11:17:44-05:00","description":"When the contact was last subscribed to the list. Reset when a contact resubscribes."},"udate":{"type":["string","null"],"example":"2021-05-12T11:10:06-05:00","description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate."},"status":{"type":["integer","string"],"example":"3","description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","example":"1","description":"Whether list autoresponders are sent to this contact for this list: 1 yes (the default), 0 suppressed for this membership."},"sync":{"type":"string","example":"1","description":"ID of the import or sync process that created the membership; 0 when it was not created by one."},"unsubreason":{"description":"The reason recorded with an unsubscribe. Empty when none was given."},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"first_name":{"type":"string","example":"John","description":"The contact's first name at the time of the request."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name at the time of the request."},"ip4Sub":{"type":"string","example":"XXXXXXXXXX","description":"The IPv4 address recorded when the contact subscribed, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"sourceid":{"type":"string","example":"1","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise."},"ip4_last":{"type":"string","example":"0","description":"The IPv4 address recorded on the last subscription change, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"ip4Unsub":{"type":"string","example":"0","description":"The IPv4 address recorded when the contact unsubscribed online, as an integer in the form PHP's ip2long produces, sent as a string. \"0\" when there is none."},"created_timestamp":{"type":"string","example":"2021-04-08 11:17:44","description":"When the membership record was created, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2021-05-12 11:10:06","description":"When the membership record was last changed, in US Central time (America/Chicago), as YYYY-MM-DD HH:MM:SS."},"created_by":{"description":"ID of the account user who created the membership. Usually null."},"updated_by":{"description":"ID of the account user who last changed the membership. Usually null."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise."},"channel":{"type":["string","null"],"example":"email","description":"The list's channel, email or sms."},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/automation","description":"URL that returns the automation that subscribed the contact (seriesid)."},"list":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/list","description":"URL that returns the list."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/contact","description":"URL that returns the contact."},"form":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/form","description":"URL that returns the form that brought the contact onto the list."},"autosyncLog":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog","description":"URL that returns the sync run that created the membership."},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/campaign","description":"URL that returns the campaign the contact unsubscribed from."},"unsubscribeAutomation":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation","description":"URL that returns the automation that unsubscribed the contact."},"message":{"type":"string","example":"https://:account.api-us1.com/api/3/contactLists/19/message","description":"URL that returns the message the contact unsubscribed from."}},"description":"URLs of the reads for the records this membership points to. A read returns an empty object when the membership points to none."},"id":{"type":"string","example":"19","description":"ID of the membership record."},"automation":{"description":"Same value as seriesid, or null when seriesid is 0. Deprecated."}},"description":"The membership after the change."}}}}}},"400":{"description":"The request was refused. The body is empty (Request body is empty.), not valid JSON (Could not decode request body.), or a JSON value such as 0, false or null; these get a string status and no title. A non-empty JSON value that is not an object gets the number 400 and the title Bad Request. An empty JSON list [] fails with 422 instead. Or the contact cannot be subscribed to this list: no email address for an email list, or no phone number for an SMS list.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\": \"400\",\n      \"detail\": \"You cannot subscribe a contact without an email address to an email list\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":["string","integer"],"example":"400","description":"The HTTP status. The number 400 only for a non-empty JSON value that is not an object; a string otherwise."},"title":{"type":"string","example":"Bad Request","description":"Only with a numeric status: Bad Request."},"detail":{"type":"string","example":"You cannot subscribe a contact without an email address to an email list","description":"What went wrong."}}},"description":"One item."}}}}}},"403":{"description":"The user may not change this membership. Nearly unreachable: the access check passes for any signed-in user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status, as a string.","example":"403"},"detail":{"type":"string","description":"What went wrong.","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No membership has this id, or its list was deleted. When the request does not set status 2, an unknown contact or list also returns 404.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SubscriberList with id 19\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberList with id 19","description":"What was not found."}}}}}},"422":{"description":"The request was not valid: contactList, or its contact, list or status, is missing or not valid (one errors item per problem, with source.pointer naming the field). Refusing to resubscribe a contact who unsubscribed, when the user lacks the permission to resubscribe contacts, returns the plain sentence \"Unsubscribed contact cannot be re-subscribed through API.\" instead of JSON, although the Content-Type is still application/json.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","description":"One item per problem.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status.","example":422},"title":{"type":"string","description":"The kind of problem.","example":"Invalid attribute"},"detail":{"type":"string","description":"What went wrong.","example":"This field is missing."},"source":{"type":"object","description":"Where the problem is.","properties":{"pointer":{"type":"string","description":"The field that failed.","example":"/data/attributes/[contactList][status]"}}}}}}}},{"type":"string","description":"The plain-sentence resubscribe refusal.","example":"Unsubscribed contact cannot be re-subscribed through API."}]},"examples":{"Result":{"value":"Unsubscribed contact cannot be re-subscribed through API."}}}}}},"deprecated":false},"delete":{"summary":"Delete a contact list subscription","description":"Deletes one membership record by its ID. The row is removed, so the contact is no longer on the list and the record of that subscription is gone. This is not an unsubscribe. No unsubscribe date or reason is saved, and no automations, webhooks or emails are started. Contact activity entries that point at the membership are kept, and their link to it is cleared. Open app pages for the contact are told the membership was deleted. Returns 404 if no membership has the id, or if the list it belongs to was deleted. A delete that fails on a database error such as a deadlock returns 403. That body is a plain sentence, not JSON, even though it is labelled application/json. Internal. To take a contact off a list and keep the record, use PUT /contactLists/{id} with status 2.","operationId":"delete-a-contact-list-subscription","x-canonical-resource":"contactLists","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contact list subscription (the contactList record, not the list)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The membership was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The delete failed on a database error such as a deadlock. The body is the sentence Failed to delete contactList. It is not JSON, though the content type is application/json.","content":{"application/json":{"schema":{"type":"string","description":"The sentence Failed to delete contactList."},"examples":{"DeleteFailed":{"value":"Failed to delete contactList"}}}}},"404":{"description":"No membership has this id, or the list it belongs to was deleted.","content":{"application/json":{"examples":{"Result":{"value":{"message":"No Result found for SubscriberList with id 19"}}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberList with id 19","description":"What was not found."}}}}}}}}},"/contactLogs":{"get":{"summary":"List all contact log entries","description":"Lists the contact log entries in the account. merge is the only action written today: each merge of two contacts records one entry on the surviving contact. To read one contact's entries, use GET /contacts/{id}/contactLogs instead. The list has no filters or sort options, and entries come in no guaranteed order. Page with limit and offset, or fetch specific entries with ids.","operationId":"list-all-contact-logs","x-canonical-resource":"contact","parameters":[{"name":"limit","in":"query","description":"Number of entries to return. Defaults to 20; values above 100 are treated as 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of entries to skip. Use with limit to page through the entries.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated log entry IDs to return. When set, only those entries are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of log entries under contactLogs, with the number of matching entries in meta.total. contactLogs is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"contactLogs":{"type":"array","description":"The log entries on this page.","items":{"$ref":"#/components/schemas/ContactLog"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching entries, ignoring limit and offset. When ids is set, the number of those ids that exist.","example":1}}}}},"examples":{"Result":{"value":{"contactLogs":[{"userid":"1","subscriberid":"6199","name":"Sam Example","email":"sam@example.com","action":"merge","params":"{\"source\":{\"id\":\"6200\",\"name\":\"Sam Example\",\"email\":\"sam.example@example.com\"},\"destination\":{\"id\":\"6199\",\"name\":\"Sam Example\",\"email\":\"sam@example.com\"},\"fields\":[],\"automations\":[],\"resolutionField\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"},\"resolutionAutomation\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"}}","tstamp":"2026-09-01T14:03:12-05:00","created_timestamp":"2026-09-01 14:03:12","updated_timestamp":"2026-09-01 14:03:12","created_by":null,"updated_by":null,"links":{"contact":"https://example.api-us1.com/api/3/contactLogs/12/contact","user":"https://example.api-us1.com/api/3/contactLogs/12/user"},"id":"12","contact":"6199","user":"1"}],"meta":{"total":1}}}}}}}},"deprecated":false}},"/contactLogs/{id}":{"get":{"summary":"Retrieve a contact log entry","description":"Returns one contact log entry by its ID. merge is the only action written today: each merge of two contacts records one entry on the surviving contact. Returns 404 if no log entry has the id.","operationId":"retrieve-a-contact-log","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the log entry.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The log entry under contactLog.","content":{"application/json":{"schema":{"type":"object","properties":{"contactLog":{"description":"The log entry.","allOf":[{"$ref":"#/components/schemas/ContactLog"}]}}},"examples":{"Result":{"value":{"contactLog":{"userid":"1","subscriberid":"6199","name":"Sam Example","email":"sam@example.com","action":"merge","params":"{\"source\":{\"id\":\"6200\",\"name\":\"Sam Example\",\"email\":\"sam.example@example.com\"},\"destination\":{\"id\":\"6199\",\"name\":\"Sam Example\",\"email\":\"sam@example.com\"},\"fields\":[],\"automations\":[],\"resolutionField\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"},\"resolutionAutomation\":{\"email\":\"sam@example.com\",\"name\":\"Sam Example\"}}","tstamp":"2026-09-01T14:03:12-05:00","created_timestamp":"2026-09-01 14:03:12","updated_timestamp":"2026-09-01 14:03:12","created_by":null,"updated_by":null,"links":{"contact":"https://example.api-us1.com/api/3/contactLogs/12/contact","user":"https://example.api-us1.com/api/3/contactLogs/12/user"},"id":"12","contact":"6199","user":"1"}}}}}}},"404":{"description":"No log entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no log entry has the id.","example":"No Result found for SubscriberLog with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for SubscriberLog with id 100"}}}}}}},"deprecated":false}},"/contactPerformance/contactAccountGrowth":{"get":{"summary":"Retrieve the account's contact growth over a date range","description":"Contact counts for the whole account at the start and end of a date range, and the change in each. Today is the server's date. When the range ends today or later, the end counts are the current ones. The current counts are: total_contacts, every contact on the account; active_contacts, contacts subscribed to at least one list; inactive_contacts, the difference. The start counts then come from the reporting data service, or are the current counts too when startDate and endDate are the same day. If the service has no row for the range, the start counts are null and the three rates are 0. When the range ends before today, the reporting data service's row comes back as it sends it, and data is an empty array when the service has no row. Internal: backs the contacts overview report in the app.","operationId":"retrieve-contact-performance-account-growth","parameters":[{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The growth summary","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/ContactPerformanceGrowthSummary"},{"description":"No row for a range that ends before today.","type":"array","items":{},"maxItems":0}]}},"type":"object"},"example":{"data":{"first_inactive_contacts":200,"first_total_contacts":1200,"first_active_contacts":1000,"inactive_contacts":240,"active_contacts":"1260","active_contact_growth_rate":26,"total_contacts":"1500","total_contact_growth_rate":25,"inactive_contact_growth_rate":20}}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/contactAccountGrowthTrend":{"get":{"summary":"Retrieve the account's contact growth trend over a date range","description":"Contact counts for the whole account per period over a date range, from the reporting data service: the first 730 periods of the range, oldest first. When the range ends today (the server's date) or later, the counts of the last returned period are replaced with the current ones. The current counts are: total_contacts, every contact on the account; active_contacts, contacts subscribed to at least one list; inactive_contacts, the difference. data is an empty array when the service has no rows. Internal: backs the contacts overview report in the app.","operationId":"retrieve-contact-performance-account-growth-trend","parameters":[{"name":"trendPeriod","in":"query","description":"Length of each period of the trend: day, week, month, quarter or year. The check only looks for one of these words anywhere in the value, in any case, and the value goes to the reporting data service as sent. Also read as trend_period.","schema":{"type":"string","default":"quarter"},"example":"month"},{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The trend","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactPerformanceGrowthPoint"}}},"type":"object"},"example":{"data":[{"event_hour":"2026-09-01 00:00:00","total_contacts":1450,"active_contacts":1220,"inactive_contacts":230},{"event_hour":"2026-10-01 00:00:00","total_contacts":1500,"active_contacts":1260,"inactive_contacts":240}]}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead. For trendPeriod, detail is \"trendPeriod must be either day, week, month, quarter, or year.\" when it is sent empty, and \"This value should satisfy at least one of the following constraints: [1] day [2] week [3] month [4] quarter [5] year\" when it contains none of those words."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/contactListGrowth/{listId}":{"get":{"summary":"Retrieve a list's contact growth over a date range","description":"Contact counts for one list at the start and end of a date range, and the change in each. Today is the server's date. When the range ends today or later, the end counts are the current ones. The current counts are: total_contacts, every contact on the list, whatever its status there; active_contacts, contacts whose status on the list is active; inactive_contacts, the difference. All three are strings of digits, and \"0\" for a list with no contacts or an id no list has. The start counts then come from the reporting data service, or are the current counts too when startDate and endDate are the same day. If the service has no row for the range, the start counts are null and the three rates are 0. When the range ends before today, the reporting data service's row comes back as it sends it, with list_id, and data is an empty array when the service has no row. Internal: not part of the public API.","operationId":"retrieve-contact-performance-list-growth","parameters":[{"name":"listId","in":"path","description":"ID of the list. Only digits match this route: any other value answers 404.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The growth summary","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/ContactPerformanceGrowthSummary"},{"description":"No row for a range that ends before today.","type":"array","items":{},"maxItems":0}]}},"type":"object"},"example":{"data":{"first_inactive_contacts":20,"first_total_contacts":220,"first_active_contacts":200,"inactive_contacts":"30","active_contacts":"220","total_contacts":"250","active_contact_growth_rate":10,"total_contact_growth_rate":13.64,"inactive_contact_growth_rate":50}}}}},"404":{"description":"listId is not all digits, so no route matches. Body: errors, a list with one item with status \"404\" as a string and detail No route found for \"GET <url>\"."},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/contactListGrowthTrend/{listId}":{"get":{"summary":"Retrieve a list's contact growth trend over a date range","description":"Contact counts for one list per period over a date range, from the reporting data service: the first 730 periods of the range, oldest first, each with list_id. When the range ends today (the server's date) or later, the counts of the last returned period are replaced with the current ones. The current counts are the list's stored subscriber counts: total_contacts, the contacts on the list that are not deleted; active_contacts, its active contacts; inactive_contacts, the difference. When no counts are stored for the id, such as an id no list has, the last period keeps the service's counts. data is an empty array when the service has no rows. Internal: not part of the public API.","operationId":"retrieve-contact-performance-list-growth-trend","parameters":[{"name":"listId","in":"path","description":"ID of the list. A whole number written another way, such as 05 or 5.0, is read as 5. Any other value that is not a whole number, such as abc or 1.5, answers 422.","required":true,"schema":{"type":"string"}},{"name":"trendPeriod","in":"query","description":"Length of each period of the trend: day, week, month, quarter or year. The check only looks for one of these words anywhere in the value, in any case, and the value goes to the reporting data service as sent. Also read as trend_period.","schema":{"type":"string","default":"quarter"},"example":"month"},{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The trend","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactPerformanceGrowthPoint"}}},"type":"object"},"example":{"data":[{"list_id":5,"event_hour":"2026-10-01 00:00:00","total_contacts":250,"active_contacts":220,"inactive_contacts":30}]}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead. For trendPeriod, detail is \"trendPeriod must be either day, week, month, quarter, or year.\" when it is sent empty, and \"This value should satisfy at least one of the following constraints: [1] day [2] week [3] month [4] quarter [5] year\" when it contains none of those words. When the dates pass, an id that is not a whole number gives a different body: errors is one object, not a list, with status 422, title \"Invalid attribute\" and detail \"<name> must be an int\", such as \"listId must be an int\" or \"tagId must be an int\"."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/contactTagGrowth/{tagId}":{"get":{"summary":"Retrieve a tag's contact growth over a date range","description":"Contact counts for the contacts with one tag at the start and end of a date range, and the change in each. Today is the server's date. When the range ends today or later, the end counts are the current ones. The current counts are: total_contacts, contacts with the tag; active_contacts, those of them subscribed to at least one list; inactive_contacts, the difference. total_contacts and active_contacts are strings of digits and inactive_contacts is a number. For a tag no contact has, or an id no tag has, total_contacts is \"0\", active_contacts is null and inactive_contacts is 0. The start counts then come from the reporting data service, or are the current counts too when startDate and endDate are the same day. If the service has no row for the range, the start counts are null and the three rates are 0. When the range ends before today, the reporting data service's row comes back as it sends it, with tag_id, and data is an empty array when the service has no row. Internal: not part of the public API.","operationId":"retrieve-contact-performance-tag-growth","parameters":[{"name":"tagId","in":"path","description":"ID of the tag. A whole number written another way, such as 012 or 12.0, is read as 12. Any other value that is not a whole number, such as abc or 1.5, answers 422.","required":true,"schema":{"type":"string"}},{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The growth summary","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/ContactPerformanceGrowthSummary"},{"description":"No row for a range that ends before today.","type":"array","items":{},"maxItems":0}]}},"type":"object"},"example":{"data":{"first_inactive_contacts":40,"first_total_contacts":400,"first_active_contacts":360,"inactive_contacts":50,"active_contacts":"400","total_contacts":"450","active_contact_growth_rate":11.11,"total_contact_growth_rate":12.5,"inactive_contact_growth_rate":25}}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead. When the dates pass, an id that is not a whole number gives a different body: errors is one object, not a list, with status 422, title \"Invalid attribute\" and detail \"<name> must be an int\", such as \"listId must be an int\" or \"tagId must be an int\"."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/contactTagGrowthTrend/{tagId}":{"get":{"summary":"Retrieve a tag's contact growth trend over a date range","description":"Contact counts for the contacts with one tag per period over a date range, from the reporting data service: the first 730 periods of the range, oldest first, each with tag_id. When the range ends today (the server's date) or later, the counts of the last returned period are replaced with the current ones. The current counts are: total_contacts, contacts with the tag; active_contacts, those of them subscribed to at least one list; inactive_contacts, the difference. For a tag no contact has, or an id no tag has, all three are 0. data is an empty array when the service has no rows. Internal: not part of the public API.","operationId":"retrieve-contact-performance-tag-growth-trend","parameters":[{"name":"tagId","in":"path","description":"ID of the tag. A whole number written another way, such as 012 or 12.0, is read as 12. Any other value that is not a whole number, such as abc or 1.5, answers 422.","required":true,"schema":{"type":"string"}},{"name":"trendPeriod","in":"query","description":"Length of each period of the trend: day, week, month, quarter or year. The check only looks for one of these words anywhere in the value, in any case, and the value goes to the reporting data service as sent. Also read as trend_period.","schema":{"type":"string","default":"quarter"},"example":"month"},{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"The trend","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactPerformanceGrowthPoint"}}},"type":"object"},"example":{"data":[{"tag_id":12,"event_hour":"2026-10-01 00:00:00","total_contacts":250,"active_contacts":220,"inactive_contacts":30}]}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead. For trendPeriod, detail is \"trendPeriod must be either day, week, month, quarter, or year.\" when it is sent empty, and \"This value should satisfy at least one of the following constraints: [1] day [2] week [3] month [4] quarter [5] year\" when it contains none of those words. When the dates pass, an id that is not a whole number gives a different body: errors is one object, not a list, with status 422, title \"Invalid attribute\" and detail \"<name> must be an int\", such as \"listId must be an int\" or \"tagId must be an int\"."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/topListsGrowth":{"get":{"summary":"List the account's five largest lists and their growth","description":"The account's five largest lists by number of contacts, largest first, with each list's growth over a date range. Today is the server's date. When the range ends before today, the rows are the reporting data service's five largest lists for the range, as it sends them. When the range ends today or later, the five lists are picked by their current stored counts instead, and each row holds the account's ID, the list's ID and name, and its current counts; total_contact_growth_rate compares the current total_contacts with the service's count for that list at the start of the range, and first_total_contacts is not sent. If the account has no stored list counts, the rows are the service's own five largest lists, as on a past range. data is an empty array when there are no rows. Internal: backs the contacts overview report in the app.","operationId":"list-contact-performance-top-lists-growth","parameters":[{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"Up to five lists","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactPerformanceTopList"},"maxItems":5}},"type":"object"},"example":{"data":[{"account_id":1,"list_id":"3","inactive_contacts":"240","active_contacts":"1260","name":"Newsletter","total_contacts":"1500","total_contact_growth_rate":25}]}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead."}},"x-canonical-resource":"contact","x-internal":true}},"/contactPerformance/topTagsGrowth":{"get":{"summary":"List the account's five most used tags and their growth","description":"The account's five tags carried by the most contacts, most first, with each tag's growth over a date range. Today is the server's date. When the range ends before today, the rows are the reporting data service's five largest tags for the range, as it sends them. When the range ends today or later, the five tags are picked by counting the contacts who carry each tag now, and each row holds the account's ID, the tag's ID and name, and its current counts; total_contact_growth_rate compares the current total_contacts with the service's count for that tag at the start of the range, and first_total_contacts is not sent. If no contact carries a tag, the rows are the service's own five largest tags, as on a past range. data is an empty array when there are no rows. Internal: backs the contacts overview report in the app.","operationId":"list-contact-performance-top-tags-growth","parameters":[{"name":"startDate","in":"query","description":"First day of the range, as Y-m-d. Also read as start_date.","required":true,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"Last day of the range, as Y-m-d. May be the same day as startDate, not earlier. Also read as end_date.","required":true,"schema":{"type":"string"},"example":"2026-09-30"}],"responses":{"200":{"description":"Up to five tags","content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactPerformanceTopTag"},"maxItems":5}},"type":"object"},"example":{"data":[{"account_id":1,"tag_id":"7","inactive_contacts":"100","active_contacts":"700","tag_name":"customer","total_contacts":"800","total_contact_growth_rate":14.29}]}}}},"422":{"description":"A query parameter fails validation. Body: errors, a list with one item per failed check, each with status 422, title \"Invalid attribute\", detail, and source.pointer naming the parameter as /data/attributes/<name>. detail is \"startDate must be a date\" when startDate is missing, empty or not a real Y-m-d date, the same for endDate, and \"endDate must be after startDate\" when endDate is earlier than startDate. The two dates are compared as text, so an invalid startDate can also bring the endDate error. A parameter sent as an array (such as startDate[]=) gives detail \"Unexpected type\" instead."}},"x-canonical-resource":"contact","x-internal":true}},"/contactSettings/backfillPhoneOnly":{"post":{"summary":"Clean up the phone-only contacts setting","description":"A one-off clean-up of the account's phone-only contacts setting. First, when the sms entitlement turned the setting on, source_id becomes whatsapp-inbox. Nothing else about the setting changes. Then, when the account does not have the WhatsApp inbox entitlement and the setting is on with source_id whatsapp-inbox, the setting is turned off: enabled becomes false, source_type, source_id and enabled_timestamp become null, and updated_by and updated_timestamp are set to the calling user and now. Otherwise nothing changes. A setting a user turned on is never changed, and nothing is queued. The answer is the same whether or not anything changed. Any user on the account can call it. No request body is read.","operationId":"backfill-phone-only-contacts-setting","responses":{"200":{"description":"The clean-up ran.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Always Backfill completed.","type":"string","example":"Backfill completed"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true,"x-destructive":true,"x-bulk-operation":false}},"/contactSettings/enablePhoneOnly":{"put":{"summary":"Turn on phone-only contacts","description":"Turns on the account setting that lets contacts be created with a phone number and no email address, with the calling user as the source. This call only turns the setting on. When the setting is already on, nothing changes and the current setting comes back, whatever turned it on. Otherwise enabled becomes true, source_type becomes user and source_id the calling user's ID, and enabled_timestamp, updated_timestamp and updated_by are set to now and the calling user. When the account has never saved the setting, it is created, with the calling user as created_by. Nothing else changes and nothing is queued. Only the account's primary admin or a user in the default Admin group, with the admin permission, may call it. It does not check the account's entitlements. Creating a contact without an email also needs a feature flag on the account, which this call does not check or change. No request body is read.","operationId":"enable-phone-only-contacts","responses":{"200":{"description":"The setting after the call.","content":{"application/json":{"schema":{"required":["config"],"properties":{"config":{"required":["enabled","source_type","source_id","enabled_timestamp","created_timestamp","updated_timestamp","created_by","updated_by"],"properties":{"enabled":{"description":"Whether contacts can be created with a phone number and no email address.","type":"boolean","example":true},"source_type":{"description":"What turned the setting on: user for a user, entitlement for the account's WhatsApp inbox entitlement. null while the setting is off.","type":["string","null"],"enum":["user","entitlement",null],"example":"user"},"source_id":{"description":"For user, the ID of the user who turned the setting on. For entitlement, the entitlement code: whatsapp-inbox, or sms on older settings. null while the setting is off.","type":["string","null"],"example":"1"},"enabled_timestamp":{"description":"When the setting was turned on, as Y-m-d H:i:s. null while the setting is off.","type":["string","null"],"example":"2026-10-01 14:30:00"},"created_timestamp":{"description":"When the setting was first saved, as Y-m-d H:i:s.","type":"string","example":"2026-10-01 14:30:00"},"updated_timestamp":{"description":"When the setting last changed, as Y-m-d H:i:s.","type":"string","example":"2026-10-01 14:30:00"},"created_by":{"description":"ID of the user who first saved the setting. 0 when none was recorded.","type":"integer","example":1},"updated_by":{"description":"ID of the user who last changed the setting. 0 when none was recorded.","type":"integer","example":1}},"type":"object"}},"type":"object"},"example":{"config":{"enabled":true,"source_type":"user","source_id":"1","enabled_timestamp":"2026-10-01 14:30:00","created_timestamp":"2026-09-15 09:00:00","updated_timestamp":"2026-10-01 14:30:00","created_by":1,"updated_by":1}}}}},"403":{"description":"The caller is not the account's primary admin or a user in the default Admin group, with the admin permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to enable phone-only mode"}]}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true,"x-destructive":true,"x-bulk-operation":false}},"/contactSettings/phoneOnly":{"get":{"summary":"Retrieve the phone-only contacts setting","description":"Returns the account setting that lets contacts be created with a phone number and no email address, and what turned it on. When the account has never saved the setting, or the saved value cannot be read, the answer is a default that is off, with the calling user as created_by and updated_by and now as both timestamps. Nothing is saved. Creating a contact without an email also needs a feature flag on the account, which this call does not check. Any user on the account can call it.","operationId":"retrieve-phone-only-contacts-setting","responses":{"200":{"description":"The setting.","content":{"application/json":{"schema":{"required":["config"],"properties":{"config":{"required":["enabled","source_type","source_id","enabled_timestamp","created_timestamp","updated_timestamp","created_by","updated_by"],"properties":{"enabled":{"description":"Whether contacts can be created with a phone number and no email address.","type":"boolean","example":true},"source_type":{"description":"What turned the setting on: user for a user, entitlement for the account's WhatsApp inbox entitlement. null while the setting is off.","type":["string","null"],"enum":["user","entitlement",null],"example":"user"},"source_id":{"description":"For user, the ID of the user who turned the setting on. For entitlement, the entitlement code: whatsapp-inbox, or sms on older settings. null while the setting is off.","type":["string","null"],"example":"1"},"enabled_timestamp":{"description":"When the setting was turned on, as Y-m-d H:i:s. null while the setting is off.","type":["string","null"],"example":"2026-10-01 14:30:00"},"created_timestamp":{"description":"When the setting was first saved, as Y-m-d H:i:s.","type":"string","example":"2026-10-01 14:30:00"},"updated_timestamp":{"description":"When the setting last changed, as Y-m-d H:i:s.","type":"string","example":"2026-10-01 14:30:00"},"created_by":{"description":"ID of the user who first saved the setting. 0 when none was recorded.","type":"integer","example":1},"updated_by":{"description":"ID of the user who last changed the setting. 0 when none was recorded.","type":"integer","example":1}},"type":"object"}},"type":"object"},"example":{"config":{"enabled":false,"source_type":null,"source_id":null,"enabled_timestamp":null,"created_timestamp":"2026-10-01 14:30:00","updated_timestamp":"2026-10-01 14:30:00","created_by":1,"updated_by":1}}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/contactTags":{"post":{"summary":"Add a tag to contact","description":"Applies one existing tag to one contact. contact is a contact id and tag is a tag id; they are different id spaces, so the tag id must come from GET /tags or POST /tags, never from a contact record. The response's contactTag id is the association id used by DELETE /contactTags/{id}. A new association returns 201. The contact is included under contacts; the tag definition is included under tags when activity logging is enabled for the account, so do not rely on it and fetch the tag from GET /tags/{id} if needed. In the 201 body, contact and tag inside contactTag are numbers as sent, while every other response returns them as strings. If the tag is already applied, the request returns 200 with the existing association only, so it is safe to repeat. A tag name in the tag field fails with 400 (\"No tag id provided\"); to apply tags by name, or several tags at once, use POST /contacts/{id}/tags instead. Returns 404 if the contact does not exist or the tag does not exist or was deleted. Requires the contact edit permission; users outside the main user group can only tag contacts they have access to.","operationId":"create-contact-tag","x-canonical-resource":"contactTags","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contactTag":{"description":"The contact and the tag to apply to it.","properties":{"contact":{"type":"integer","description":"The contact id, from GET /contacts.","default":1,"format":"int32"},"tag":{"type":"integer","description":"The tag id, from GET /tags or POST /tags. Not the tag name, and not a contact id.","default":20,"format":"int32"}},"required":[],"type":"object"}}},"examples":{"Example 1":{"value":{"contactTag":{"contact":"1","tag":"20"}}}}}}},"responses":{"200":{"description":"The tag was already applied to this contact. The existing association is returned; nothing changed.","content":{"application/json":{"examples":{"Existing association":{"value":"{\"contactTag\":{\"contact\":\"5606\",\"tag\":\"166\",\"cdate\":\"2026-09-23T15:37:14-05:00\",\"created_timestamp\":\"2026-09-23 15:37:14\",\"updated_timestamp\":\"2026-09-23 15:37:14\",\"created_by\":null,\"updated_by\":null,\"links\":{\"tag\":\"https://:account.api-us1.com/api/3/contactTags/218953/tag\",\"contact\":\"https://:account.api-us1.com/api/3/contactTags/218953/contact\"},\"id\":\"218953\"}}"}},"schema":{"type":"object","properties":{"contactTag":{"description":"The existing association, with the same fields as GET /contactTags/{id}.","type":"object"}}}}}},"201":{"description":"The tag was applied. contacts holds the contact; tags holds the tag definition when activity logging is enabled for the account. contact and tag inside contactTag are numbers in this response only.","content":{"application/json":{"examples":{"Result":{"value":"{\"contactTag\":{\"contact\":5606,\"tag\":172,\"cdate\":\"2026-09-23T15:45:02-05:00\",\"links\":{\"tag\":\"https://:account.api-us1.com/api/3/contactTags/218956/tag\",\"contact\":\"https://:account.api-us1.com/api/3/contactTags/218956/contact\"},\"id\":\"218956\"},\"tags\":[{\"tagType\":\"contact\",\"tag\":\"newsletter\",\"description\":\"\",\"subscriber_count\":\"1\",\"cdate\":\"2026-09-23T15:44:53-05:00\",\"created_timestamp\":\"2026-09-23 15:44:53\",\"updated_timestamp\":\"2026-09-23 15:45:02\",\"created_by\":null,\"updated_by\":null,\"deleted\":\"0\",\"links\":{\"contactGoalTags\":\"https://:account.api-us1.com/api/3/tags/172/contactGoalTags\",\"templateTags\":\"https://:account.api-us1.com/api/3/tags/172/templateTags\"},\"id\":\"172\"}],\"contacts\":[{\"cdate\":\"2026-07-22T16:22:19-05:00\",\"email\":\"sam@example.com\",\"phone\":\"555-555-5555\",\"firstName\":\"Sam\",\"lastName\":\"Example\",\"hash\":\"0123456789abcdef0123456789abcdef\",\"id\":\"5606\",\"links\":{\"contactLists\":\"https://:account.api-us1.com/api/3/contacts/5606/contactLists\",\"contactTags\":\"https://:account.api-us1.com/api/3/contacts/5606/contactTags\",\"fieldValues\":\"https://:account.api-us1.com/api/3/contacts/5606/fieldValues\"}}]}"}},"schema":{"type":"object","properties":{"contactTag":{"type":"object","description":"The new association. contact and tag are numbers here, as sent; every other response returns them as strings.","properties":{"id":{"type":"string","example":"218956","description":"The association id, for DELETE /contactTags/{id}."},"contact":{"description":"Id of the contact the tag was applied to, as sent.","type":"integer","example":5606},"tag":{"description":"Id of the tag that was applied, as sent.","type":"integer","example":172},"cdate":{"description":"When the tag was applied, in ISO 8601.","type":"string","example":"2026-09-23T15:45:02-05:00"},"links":{"description":"URLs of the association's related reads.","type":"object","properties":{"tag":{"description":"URL that returns the tag definition, GET /contactTags/{id}/tag.","type":"string"},"contact":{"description":"URL that returns the contact, GET /contactTags/{id}/contact.","type":"string"}}}}},"tags":{"type":"array","items":{"type":"object"},"description":"The tag definition that was applied. Present when activity logging is enabled for the account."},"contacts":{"type":"array","items":{"type":"object"},"description":"The contact that was tagged."}}}}}},"400":{"description":"tag or contact is missing or is not a positive integer id, for example a tag name was sent in tag. The same body, with detail \"contactTag object already exists for that contact and tag\", is returned in the rare case where two requests apply the same tag at the same moment. A body that is a non-empty JSON list or a non-empty single value instead of an object is refused with 400 before any other check, with an errors entry that has status, title and detail instead. An empty body, an empty list, 0, false or an empty string is read as an empty object and gets \"No tag id provided\".","content":{"application/json":{"examples":{"Tag name instead of id":{"value":"{\"errors\":[{\"title\":\"Invalid value for query parameter contactTag.tag\",\"detail\":\"No tag id provided\",\"source\":{\"parameter\":\"contactTag.tag\"}}]}"}},"schema":{"type":"object","properties":{"errors":{"description":"One entry describing the problem.","type":"array","items":{"type":"object","properties":{"title":{"description":"Names the field, for example \"Invalid value for query parameter contactTag.tag\".","type":"string"},"detail":{"description":"\"No tag id provided\", \"No contact id provided\", or \"contactTag object already exists for that contact and tag\".","type":"string","example":"No tag id provided"},"source":{"description":"Which field was refused.","type":"object","properties":{"parameter":{"description":"contactTag.tag, contactTag.contact, or contactTag for a duplicate.","type":"string"}}}}}}}}}}},"403":{"description":"The API user does not have the contact edit permission, or cannot access this contact.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry, describing the refusal.","type":"array","items":{"type":"object","properties":{"status":{"description":"HTTP status code, always 403.","type":"integer","example":403},"title":{"description":"\"Forbidden\" in English; the title follows the API user's language.","type":"string"},"detail":{"description":"Says why: \"You do not have permission to edit contacts\" without the contact edit permission; \"You do not have permission to access this contact\" when the user is outside the main user group and the contact is on none of their lists.","type":"string"}}}}}}}}},"404":{"description":"The contact does not exist, or the tag does not exist, was deleted, or is a template tag. Only contact tags can be applied to contacts.","content":{"application/json":{"examples":{"Unknown tag":{"value":"{\"message\":\"Tag not found\"}"},"Unknown contact":{"value":"{\"message\":\"Contact not found\"}"}},"schema":{"type":"object","properties":{"message":{"description":"Tag not found or Contact not found.","type":"string"}}}}}}},"deprecated":false},"get":{"summary":"List all contact-tag associations","description":"List the tags applied to contacts. Each item is a single contact-to-tag association, and its `id` is the value to pass to `DELETE /contactTags/{id}` when removing a tag from a contact.\n\nFilter by contact, by tag, or by both to look up a specific association. Note that the filters use the underlying column names `subscriberid` and `tagid`, while the response returns the same values as `contact` and `tag` — `filters[contact]` and `filters[tag]` are not supported.\n\nUnrecognized filter and order parameters are silently ignored, so a request with a misspelled filter looks successful while returning the unfiltered set.\n\nAssociations whose tag has since been deleted are still listed here and counted in meta.total; GET /tags/{id} for such a tag returns 404. The contact's own listing, GET /contacts/{id}/contactTags, hides them.\n\nTo get the contacts that carry a tag, rather than the association rows, use GET /contacts with tagid, or filters[tagName] for a tag name.\n\nfilters[cdate] matches one exact timestamp, not a day or a range. To answer \"which contacts got tag X since a date\", filter by filters[tagid], order with orders[cdate]=desc and stop paging when cdate passes the date.\n\nNo permission beyond API access is checked, so any API user can list every association in the account, including contacts that are not on their lists. Associations whose contact no longer exists are left out.","operationId":"list-all-contact-tags","x-canonical-resource":"contactTags","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Filter by the id of the contact the tag is applied to. This is the same value the response returns as `contact`.","schema":{"type":"integer","format":"int32"}},{"name":"filters[tagid]","in":"query","description":"Filter by the id of the tag. This is the same value the response returns as `tag`.","schema":{"type":"integer","format":"int32"}},{"name":"filters[cdate]","in":"query","description":"Return only associations applied at exactly this date and time, written YYYY-MM-DD HH:MM:SS in the platform timezone, the one the response's other timestamps carry. This is an exact match: a date without a time matches nothing, and there is no range form. To find the tags applied since a date, filter by filters[tagid], order with orders[cdate]=desc and page until cdate passes the date. An operator suffix such as filters[cdate][gt] is applied as an exact match with that value, not as a range.","schema":{"type":"string","format":"date-time"}},{"name":"orders[cdate]","in":"query","description":"Order results by the date the tag was applied to the contact.","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[tagid]","in":"query","description":"Order results by tag id, ascending or descending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[subscriberid]","in":"query","description":"Order results by contact id, ascending or descending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"ids","in":"query","description":"Comma-separated list of contactTag association ids to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return for each call. Default is 20; maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"The associations that matched.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactTags\": [\n        {\n            \"contact\": \"1\",\n            \"tag\": \"20\",\n            \"cdate\": \"2017-06-08T16:11:53-05:00\",\n            \"links\": {\n                \"contact\": \"https://:account.api-us1.com/api/3/contactTags/1/contact\",\n                \"tag\": \"https://:account.api-us1.com/api/3/contactTags/1/tag\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"contact\": \"1\",\n            \"tag\": \"21\",\n            \"cdate\": \"2017-06-09T09:22:04-05:00\",\n            \"links\": {\n                \"contact\": \"https://:account.api-us1.com/api/3/contactTags/2/contact\",\n                \"tag\": \"https://:account.api-us1.com/api/3/contactTags/2/tag\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}},"schema":{"type":"object","properties":{"contactTags":{"description":"One entry per tag applied to a contact.","type":"array","items":{"type":"object","properties":{"contact":{"description":"Id of the contact the tag is applied to, as a string.","type":"string","example":"1"},"tag":{"description":"Id of the tag that is applied, as a string. Fetch the tag itself from GET /tags/{id}.","type":"string","example":"20"},"cdate":{"description":"When the tag was applied to the contact, in ISO 8601; null when not recorded.","type":["string","null"],"example":"2017-06-08T16:11:53-05:00"},"links":{"description":"URLs of the association's related reads.","type":"object","properties":{"contact":{"description":"URL that returns the contact, GET /contactTags/{id}/contact.","type":"string","example":"https://:account.api-us1.com/api/3/contactTags/1/contact"},"tag":{"description":"URL that returns the tag definition, GET /contactTags/{id}/tag.","type":"string","example":"https://:account.api-us1.com/api/3/contactTags/1/tag"}}},"id":{"description":"The association id. Pass it to DELETE /contactTags/{id} to take the tag off the contact. It is not the tag id.","type":"string","example":"1"},"created_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row was created, as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":["string","null"],"example":null,"description":"Id of the user who applied the tag. Usually null: it is not set when the tag is applied through this API."},"updated_by":{"type":["string","null"],"example":null,"description":"Id of the user who last changed the association. Usually null: it is not set when the tag is applied through this API."}}}},"meta":{"description":"Paging information.","type":"object","properties":{"total":{"description":"Number of associations that matched, ignoring limit and offset. When counting is slow it can come from a cache of up to five minutes.","type":"integer","example":2}}}}}}}},"403":{"description":"The request has no valid API token. The body is empty."}},"deprecated":false}},"/contactTags/{id}":{"get":{"summary":"Retrieve a contact tag","description":"Returns a single contact-to-tag association by its id. The contact and tag fields are ids; fetch the tag definition itself from GET /tags/{id}. Returns 404 if the association does not exist. No permission beyond API access is checked.","operationId":"retrieve-a-contact-tag","x-canonical-resource":"contactTags","parameters":[{"name":"id","in":"path","description":"ID of the contactTag association to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The association.","content":{"application/json":{"schema":{"type":"object","properties":{"contactTag":{"description":"The contact-to-tag association.","type":"object","properties":{"contact":{"description":"Id of the contact the tag is applied to, as a string.","type":"string","example":"113"},"tag":{"description":"Id of the tag that is applied, as a string. Fetch the tag itself from GET /tags/{id}.","type":"string","example":"20"},"cdate":{"description":"When the tag was applied to the contact, in ISO 8601; null when not recorded.","type":["string","null"],"example":"2026-09-18T10:52:26-05:00"},"links":{"description":"URLs of the association's related reads.","type":"object","properties":{"tag":{"description":"URL that returns the tag definition, GET /contactTags/{id}/tag.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/tag"},"contact":{"description":"URL that returns the contact, GET /contactTags/{id}/contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/contact"}}},"id":{"description":"The association id. Pass it to DELETE /contactTags/{id} to take the tag off the contact. It is not the tag id.","type":"string","example":"1553"},"created_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row was created, as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":["string","null"],"example":null,"description":"Id of the user who applied the tag. Usually null: it is not set when the tag is applied through this API."},"updated_by":{"type":["string","null"],"example":null,"description":"Id of the user who last changed the association. Usually null: it is not set when the tag is applied through this API."}}}}}}}},"404":{"description":"No association has this id, or its contact no longer exists.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for SubscriberTag with id 1\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says no association has this id."}}}}}}}},"put":{"summary":"Update a contact tag (internal)","description":"Changes an existing contact-to-tag association in place: contact moves the link to another contact and tag points it at another tag. PATCH /contactTags/{id} does the same thing. This is not the supported way to change a contact's tags: use DELETE /contactTags/{id} and then POST /contactTags. The call checks no contact edit permission, no list access, and nothing about the tag, not even that it exists or is a contact tag. The contact must exist: an unknown contact id fails with 500. It starts no tag-added or tag-removed automations and sends no contact_tag_added, contact_tag_removed or contact updated webhooks; the database still moves the tag's subscriber count. Besides contact and tag, the body can also set the raw subscriberid and tagid keys and the created_by, updated_by, created_timestamp and updated_timestamp columns. Any other key in contactTag is sent to the database as a column and fails with 500; id and cdate are ignored. A body that changes nothing, or whose contactTag is missing, null or a single value, returns 200 with nothing changed. Returns 200 with the association as sent; it is not read back.","operationId":"update-a-contact-tag","x-canonical-resource":"contactTags","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contactTag association to change","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactTag":{"type":"object","description":"The fields to change. Fields left out keep their current value.","properties":{"contact":{"description":"Id of the contact to move the link to.","type":["integer","string"],"example":113},"tag":{"description":"Id of the tag to point the link at. Not checked.","type":["integer","string"],"example":20}}}}},"examples":{"Request Example":{"value":{"contactTag":{"contact":113,"tag":20}}}}}}},"responses":{"200":{"description":"The update was saved, or there was nothing to change. contactTag holds the values as sent; contacts holds the contact when something changed.","content":{"application/json":{"schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"type":"object"},"description":"The contact the link now belongs to, in the same shape as the contacts array on POST /contactTags. Present only when the request changed something."},"contactTag":{"description":"The changed association, as sent.","type":"object","properties":{"contact":{"description":"Id of the contact the link now belongs to, echoed as sent (a number or a string).","type":["string","integer"],"example":"113"},"tag":{"description":"Id of the tag the link now points to, echoed as sent (a number or a string). It is not checked.","type":["string","integer"],"example":"20"},"cdate":{"description":"When the tag was applied to the contact, in ISO 8601; null when not recorded.","type":["string","null"],"example":"2026-09-18T10:52:26-05:00"},"links":{"description":"URLs of the association's related reads.","type":"object","properties":{"tag":{"description":"URL that returns the tag definition, GET /contactTags/{id}/tag.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/tag"},"contact":{"description":"URL that returns the contact, GET /contactTags/{id}/contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/contact"}}},"id":{"description":"The association id. Pass it to DELETE /contactTags/{id} to take the tag off the contact. It is not the tag id.","type":"string","example":"1553"},"created_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row was created, as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","example":"2026-09-23 15:37:14","description":"When the association row last changed before this request, as YYYY-MM-DD HH:MM:SS. The row is not read back, so this request's change is not reflected."},"created_by":{"type":["string","null"],"example":null,"description":"Id of the user who applied the tag. Usually null: it is not set when the tag is applied through this API."},"updated_by":{"type":["string","null"],"example":null,"description":"Id of the user who last changed the association. Usually null: it is not set when the tag is applied through this API."}}}}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else. An empty list, 0, false or null is read as an empty object instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"description":"HTTP status code."},"title":{"type":"string","example":"Bad Request","description":"Short name of the error."},"detail":{"type":"string","example":"Request body must be a JSON object, array given.","description":"What was wrong with the body."}}}}}}}}},"404":{"description":"No association has this id, or its contact no longer exists.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for SubscriberTag with id 1\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says no association has this id."}}}}}},"422":{"description":"The contact and tag pair is already linked by another association.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Could not process request","description":"Always \"Could not process request\"."},"error":{"type":"string","example":"Duplicate entry '113-20' for key 'em_subscriber_tag.subscriberid_tagid'","description":"The database's duplicate-entry message."}}}}}},"500":{"description":"The save failed: for example contact is not an existing contact id, or the body has a key that is not a column. Most failures return the body below; some return only {\"message\": \"Something went wrong on our end. Please try again later\"}.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Could not process request","description":"\"Could not process request\", or the generic \"Something went wrong on our end. Please try again later\"."},"error":{"type":"string","example":"Error while processing request","description":"\"Error while processing request\" when present."}}}}}}}},"delete":{"summary":"Remove a tag from a contact","description":"Removes a tag from a contact by the contactTag association id (returned by GET /contactTags, POST /contactTags, or POST /contacts/{id}/tags). This is not the tag id. The tag definition itself is not deleted. Returns 404 if the association does not exist. To remove a tag by contact id and tag id or name instead, use DELETE /contacts/{id}/tags/{tagId} or DELETE /contacts/{id}/tags with the tag query parameter. Removing the tag starts the automations that start when this tag is removed, and sends the contact_tag_removed and contact updated webhooks. Requires the contact edit permission; users outside the main user group can only remove tags from contacts on their lists.","operationId":"remove-a-contacts-tag","x-canonical-resource":"contactTags","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The contactTag id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The tag was taken off the contact. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The API user does not have the contact edit permission, or cannot access this contact.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry, describing the refusal.","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code, always 403."},"title":{"type":"string","description":"\"Forbidden\" in English; the title follows the API user's language."},"detail":{"type":"string","description":"Says why: \"You do not have permission to edit contacts\" or \"You do not have permission to access this contact\"."}}}}}}}}},"404":{"description":"No association has this id, or its contact no longer exists.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\":\"No Result found for SubscriberTag with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SubscriberTag with id 1","description":"Says no association has this id."}}}}}}},"deprecated":false}},"/contacts":{"post":{"summary":"Create a contact","description":"Create a brand-new contact. This endpoint fails with a 422 duplicate-email error when a contact with the same email address already exists; it never updates an existing contact. To add or import contacts that may already exist, use POST /contact/sync for one contact or POST /import/bulk_import for many (up to 250 per request) instead: both create or update by email, and the import can also set list subscriptions and tags per contact. The same request can also save custom field values (contact.fieldValues), add tags (contact.tags) and subscribe the contact to lists (contact.lists or contact.form). The user needs the add contacts permission.","operationId":"create-a-new-contact","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["contact"],"properties":{"contact":{"description":"The contact to create.","allOf":[{"$ref":"#/components/schemas/ContactWrite"},{"properties":{"disableAccountMatch":{"type":"boolean","description":"Set to true to skip automatic account matching for the new contact. Matching links a new contact to an account by its email domain. It only runs on ActiveCampaign's own internal account, so on other accounts this setting has no effect."}}}]},"useDefaults":{"type":"boolean"}}},"examples":{"Request Example":{"value":{"contact":{"email":"johndoe@example.com","firstName":"John","lastName":"Doe","phone":"7223224241","fieldValues":[{"field":"1","value":"The Value for First Field"},{"field":"6","value":"2008-01-20"}]}}}}}}},"responses":{"201":{"description":"The contact was created. The body has the new contact under contact and its custom field values under fieldValues.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"113\",\n            \"field\": \"1\",\n            \"value\": \"The Value for First Field\",\n            \"cdate\": \"2020-08-01T10:54:59-05:00\",\n            \"udate\": \"2020-08-01T14:13:34-05:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/11797/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/11797/field\"\n            },\n            \"id\": \"11797\",\n            \"owner\": \"113\"\n        },\n        {\n            \"contact\": \"113\",\n            \"field\": \"6\",\n            \"value\": \"2008-01-20\",\n            \"cdate\": \"2020-08-01T10:54:59-05:00\",\n            \"udate\": \"2020-08-01T14:13:34-05:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/11798/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/11798/field\"\n            },\n            \"id\": \"11798\",\n            \"owner\": \"113\"\n        }\n    ],\n    \"contact\": {\n        \"email\": \"johndoe@example.com\",\n        \"cdate\": \"2018-09-28T13:50:41-05:00\",\n        \"udate\": \"2018-09-28T13:50:41-05:00\",\n        \"orgid\": \"0\",\n        \"links\": {\n            \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/bounceLogs\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/113/contactAutomations\",\n            \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/113/contactData\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/113/contactGoals\",\n            \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/113/contactLists\",\n            \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/contactLogs\",\n            \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/113/contactTags\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/113/contactDeals\",\n            \"deals\": \"https://:account.api-us1.com/api/:version/contacts/113/deals\",\n            \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/113/fieldValues\",\n            \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/113/geoIps\",\n            \"notes\": \"https://:account.api-us1.com/api/:version/contacts/113/notes\",\n            \"organization\": \"https://:account.api-us1.com/api/:version/contacts/113/organization\",\n            \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/113/plusAppend\",\n            \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/trackingLogs\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/113/scoreValues\"\n        },\n        \"id\": \"113\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","items":{"$ref":"#/components/schemas/ContactFieldValue"},"description":"All of the contact's custom field values, read from the database after the save. Present when the request sent fieldValues or the older fields list."},"contact":{"description":"The new contact: the fields sent plus id, cdate, udate, links, orgid and organization. It is not read back after the save, so fields set by the database, such as hash, are absent.","allOf":[{"$ref":"#/components/schemas/Contact"}]}}}}}},"400":{"description":"The contact was not created: a list in contact.lists or contact.form is an email list and the contact has no email address, or an SMS list and the contact has no phone number. Tags and an account named in the request may already have been created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteForbidden"},"example":{"errors":[{"status":"400","detail":"You cannot subscribe a contact without an email address to an email list"}]}}}},"403":{"description":"The contact was not created. The user does not have the add contacts permission (detail \"Forbidden, the user doesn't have permission to add contacts.\"). Without the edit contacts permission, sending contact.lists, or a contact.form that has lists, also fails with 403 (detail \"Forbidden, the user doesn't have permission to subscribe contacts to lists.\"); tags and an account named in the request may already have been created by then. A refused account link also returns 403; see contact.account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteForbidden"}}}},"404":{"description":"The contact was not created: orgid or organization names an account id that does not exist. Body: message, \"No Result found for CustomerAccount with id\" followed by that id. Tags and an account named in the request may already have been created.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\":\"No Result found for CustomerAccount with id 12\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for CustomerAccount with id 12","description":"Says which record was not found and its id."}}}}}},"409":{"description":"The contact was not created: another contact already has this whatsapp_id. Tags and an account named in the request may already have been created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteConflict"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"A contact with this whatsapp_id already exists"}]}}}},"422":{"description":"Validation failed and the contact was not created. An account or tags named in the request may already have been created; see contact.account and contact.tags. When the email address already belongs to a contact, the error has code \"duplicate\", title \"Email address already exists in the system.\" and source.pointer \"/data/attributes/email\"; the existing contact is left unchanged. Other validation failures also return 422. A whatsapp_id that needs phone-only contacts uses this body too. The errors described on contact.tags, contact.lists, contact.form and contact.ip4 use the second body shape; see the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteValidationError"},"example":{"errors":[{"title":"Email address already exists in the system.","detail":"","code":"duplicate","error":"","source":{"pointer":"/data/attributes/email"}}]}}}}},"deprecated":false},"get":{"summary":"List, search, and filter contacts","description":"The read behind the Contacts page. It finds contacts by list (listid), tag (tagid, or filters[tagName] for a tag name), list status (status), text (search matches name, email, phone and account name), segment (segmentid), form (formid), automation (seriesid), or created and updated date (filters[created_after], filters[created_before], filters[updated_after], filters[updated_before]). Filters combine, except that while segmentid is set only status and search still apply and the other filters are ignored, and tagid and filters[tagName] cannot be sent together. GET /contactTags and GET /contactLists return association rows, not contacts. Use only the query parameters documented here: unsupported filter and order fields are silently ignored, so the response looks filtered but is not. The API spellings firstName, lastName and owner are accepted as filter keys, but order keys take only the column spellings: orders[lastName] is ignored, orders[last_name] works. Results are paginated: limit defaults to 20 and is capped at 100; page with offset, or walk a large set with id_greater. Results come back sorted by email ascending unless an orders[...] key says otherwise. To fetch one contact by id, use GET /contacts/{id}. To count the contacts a query matches without fetching records, send meta=only and read meta.total. There is no filter on when a contact's list status changed: filters[updated_after] and filters[updated_before] use the contact record's last-modified date (udate). That date moves on any save of the record, including a PUT /contacts/{id} that changes nothing, and, through database triggers, on list, tag, custom field, score, note and task changes, however they are made. A window on it counts every contact touched in that window, not the contacts whose status changed, so it over-counts new unsubscribes or bounces. A count filtered only by status on an account with millions of contacts scans every contact and can take longer than ten seconds. Archived contacts, the contacts that have been deleted, are never returned whatever the status value; list them with GET /contactArchives.","operationId":"list-all-contacts","x-canonical-resource":"contact","parameters":[{"name":"ids","in":"query","description":"Return only the contacts with these ids. Pass a comma-separated list (ids=1,2,42) or repeat the key (ids[]=1&ids[]=2). The response returns at most as many contacts as ids given.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of contacts to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of contacts to skip before returning results. Use with limit to page through contacts. For walking a large set, filtering with id_greater is more reliable than a growing offset.","schema":{"type":"integer","default":0}},{"name":"meta","in":"query","description":"Set to only to return just the metadata (such as the total count) with no contact records, or to omit to leave the metadata out of the response.","schema":{"type":"string","enum":["only","omit"]}},{"name":"email","in":"query","description":"Email address of the contact you want to get","schema":{"type":"string"}},{"name":"email_like","in":"query","description":"Filter contacts that contain the given value in the email address","schema":{"type":"string"}},{"name":"exclude","in":"query","description":"Exclude the contact with the given ID from the response. Can be repeated to exclude multiple IDs: exclude[]=1&exclude[]=2.","schema":{"type":"integer","format":"int32"}},{"name":"formid","in":"query","description":"Filter contacts associated with the given form","schema":{"type":"integer","format":"int32"}},{"name":"id_greater","in":"query","description":"Only include contacts with an ID greater than the given ID","schema":{"type":"integer","format":"int32"}},{"name":"id_less","in":"query","description":"Only include contacts with an ID less than the given ID","schema":{"type":"integer","format":"int32"}},{"name":"listid","in":"query","description":"Filter contacts associated with the given list","schema":{"type":"string"}},{"name":"phone","in":"query","description":"Filter contacts whose stored phone number starts with the given value, compared against the string exactly as stored, including country code, spaces, and punctuation (for example +1 555-555-5555). If the stored format is unknown, use search with one segment of the number (for example 5555) instead. A differently formatted phone value returns no matches, and search matches segments of the stored format (or a prefix of the last segment) but never a run of digits with the formatting stripped.","schema":{"type":"string"}},{"name":"organization","in":"query","description":"(Deprecated) Please use Account-Contact end points. Filter contacts associated with the given organization ID","schema":{"type":"integer","format":"int32"}},{"name":"customer_account","in":"query","description":"Filter contacts that belong to the given account, by account id. Equivalent to organization.","schema":{"type":"integer"}},{"name":"search","in":"query","description":"Search contacts. A full email address matches the contact's email exactly; any other value is matched against email, first name, last name, phone, and account name. q is accepted as an alias. When search is set it takes precedence over email_like and filters[email_hash].","schema":{"type":"string","default":"null"}},{"name":"segmentid","in":"query","description":"Return only contacts that match a list segment. The first API call within 1 hour or an API call with the param `forceQuery=1` will kick off an new segment request. When the segment results are ready, subsequent API calls without the `forceQuery` param will return contacts that match the segment - timeout 1hr)","schema":{"type":"integer","format":"int32"}},{"name":"seriesid","in":"query","description":"Filter contacts associated with the given automation","schema":{"type":"integer","format":"int32"}},{"name":"finishedAutomation","in":"query","description":"Only used together with seriesid. Set to 1 to return only contacts that finished the automation, or 0 for contacts that entered it but have not finished.","schema":{"type":"integer","enum":[0,1]}},{"name":"conversionid","in":"query","description":"Only used together with seriesid. Return only contacts that hit the given conversion while they were in the automation.","schema":{"type":"integer"}},{"name":"status","in":"query","description":"Filter contacts by list-membership status: -1 any (the default), 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced. Combine with listid to check the status on one list. Values above 3 match nothing and return an empty result with total 0 rather than an error; values below -1 behave as \"on at least one list, any status\" (or \"on the given listid, any status\" when listid is set); a non-numeric value is read as 0 (unconfirmed).","schema":{"type":"integer","format":"int32","default":-1,"enum":[-1,0,1,2,3]}},{"name":"tagid","in":"query","description":"Filter contacts associated with the given tag","schema":{"type":"integer","format":"int32"}},{"name":"filters[created_before]","in":"query","description":"Filter contacts that were created prior to this date","schema":{"type":"string","format":"date"}},{"name":"filters[created_after]","in":"query","description":"Filter contacts that were created after this date","schema":{"type":"string","format":"date"}},{"name":"filters[updated_before]","in":"query","description":"Contacts whose record was last modified before this date. The last-modified date moves on any save of the contact record and, through database triggers, on list, tag, custom field, score, note and task changes however they are made, so it is not the date a list status changed and a window on it includes every contact touched for any reason. The time a contact left a list is udate on its list membership (GET /contacts/{id}/contactLists), which cannot be filtered on.","schema":{"type":"string","format":"date"}},{"name":"filters[updated_after]","in":"query","description":"Contacts whose record was last modified after this date. The last-modified date moves on any save of the contact record and, through database triggers, on list, tag, custom field, score, note and task changes however they are made, so it is not the date a list status changed: a window on it includes every contact touched in that window for any reason. There is no filter for when a contact unsubscribed or bounced; that time is udate on the contact's list membership (GET /contacts/{id}/contactLists), which cannot be filtered on.","schema":{"type":"string","format":"date"}},{"name":"filters[id]","in":"query","description":"Filter by exact contact id. To fetch several known contacts at once, prefer the ids parameter.","schema":{"type":"string"}},{"name":"filters[email]","in":"query","description":"Filter by exact email address. Equivalent to the email parameter.","schema":{"type":"string"}},{"name":"filters[cdate]","in":"query","description":"Filter contacts created at exactly the given date and time. For a range, use filters[created_before] and filters[created_after].","schema":{"type":"string"}},{"name":"filters[udate]","in":"query","description":"Filter contacts last updated at exactly the given date and time. For a range, use filters[updated_before] and filters[updated_after].","schema":{"type":"string"}},{"name":"filters[email_hash]","in":"query","description":"Filter contacts by the hash of their email address (the hash field returned on the contact). The top-level email_hash parameter is a deprecated alias. Ignored when search is supplied.","schema":{"type":"string"}},{"name":"filters[tagName]","in":"query","description":"Filter contacts by tag name instead of tag id. Accepts one tag name or a list (filters[tagName][]=a&filters[tagName][]=b); a contact matches if it has any of the tags. Cannot be combined with tagid. Unknown tag names are rejected with a 400 error.","schema":{"type":"string"}},{"name":"filters[fields][{fieldId}]","in":"query","description":"Filter contacts by custom field value, for example filters[fields][5]=blue. Repeat with different field ids to require all of them at once. On single-value fields the value matches from the start of the stored value; on multi-select fields (listbox, checkbox) it matches anywhere. An empty value matches contacts with a blank or missing value. Unknown field ids are rejected with a 400 error.","schema":{"type":"string"}},{"name":"filters[first_name]","in":"query","description":"Filter contacts whose first name is exactly the given value. Also accepted as filters[firstName].","schema":{"type":"string"}},{"name":"filters[last_name]","in":"query","description":"Filter contacts whose last name is exactly the given value. Also accepted as filters[lastName].","schema":{"type":"string"}},{"name":"filters[userid]","in":"query","description":"Filter contacts owned by the given user, by user id. Also accepted as filters[owner].","schema":{"type":"string"}},{"name":"filters[orgname]","in":"query","description":"Filter contacts whose account (organization) name is exactly the given value. Also accepted as filters[customer_acct_name].","schema":{"type":"string"}},{"name":"waitid","in":"query","description":"Filter by contacts in the wait queue of an automation block","schema":{"type":"integer","format":"int32"}},{"name":"orders[id]","in":"query","description":"Order contacts by unique ID","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"orders[cdate]","in":"query","description":"Order contacts by creation date","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[udate]","in":"query","description":"Order contacts by last-updated date","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"orders[email]","in":"query","description":"Order contacts by email","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"orders[first_name]","in":"query","description":"Order contacts by first name","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[last_name]","in":"query","description":"Order contacts by last name","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[name]","in":"query","description":"Order contacts by full name. Applied as first name then last name, both in the given direction.","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[score]","in":"query","description":"Order contacts by score. Send the score id in sortId: each contact is then ranked by its highest value for that score, and contacts without one come last. sortId is not enforced. Without it the query joins every score value a contact has, which is slow on large accounts, drops contacts that have no score value, and can list a contact once per score value. orders[contactScoreValue] and orders[score_recent] are not order keys and are silently ignored.","schema":{"type":"string","enum":["desc","asc"]}},{"name":"orders[userid]","in":"query","description":"Order contacts by contact owner (user id)","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"orders[orgname]","in":"query","description":"Order contacts by the name of the account they belong to","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"orders[field]","in":"query","description":"Order contacts by the value of a custom field. Use asc or desc and pass the custom field id in the sortId parameter.","schema":{"type":"string","default":"asc","enum":["desc","asc"]}},{"name":"in_group_lists","in":"query","description":"Set this to \"true\" in order to return only contacts that the current user has permissions to see.","schema":{"type":"string"}},{"in":"query","name":"forceQuery","schema":{"type":"number","default":0,"enum":[0,1]},"description":"If present and equal to 1, a new segment request is kicked off which will return an updated result set. Otherwise, a segmented API request with a consistent sorting will return the same results for 1 hour. Note that re-ordering the results will also cause an updated result set to be returned."},{"in":"query","name":"sortId","schema":{"type":"number"},"description":"Id of the score (with orders[score]) or custom field (with orders[field]) to sort by. orders[field] is ignored without it; orders[score] still runs without it, see that parameter."},{"name":"q","in":"query","description":"Alias for search; prefer search. When both are sent, q is used for the text search. Only search switches off email_like and filters[email_hash], and only search is applied inside a segment (segmentid) query; q is not.","schema":{"type":"string"}},{"name":"sort","in":"query","description":"Shortcut for ordering by full name: sort=name orders contacts by first name, then last name, both ascending. Ignored when any orders[...] parameter is sent. For every other ordering, and for descending order, use the orders[...] parameters.","schema":{"type":"string","enum":["name"]}},{"name":"name","in":"query","description":"Used only together with email_like, and only when search is empty; on its own it does nothing. A contact then matches when its email contains the part of email_like before the @, or when its first and last name equal the first two words of name (name=Sam Example matches first name Sam and last name Example).","schema":{"type":"string"}},{"name":"nameOrEmailLike","in":"query","description":"Older quick search kept for existing callers; prefer search. Matches contacts whose full name (first and last name joined by a space) or email contains the value anywhere. Applied even when search is also sent.","schema":{"type":"string"}},{"name":"nameOrEmailOrPhoneLike","in":"query","description":"Like nameOrEmailLike, and also matches when the phone number contains the value anywhere. Prefer search.","schema":{"type":"string"}}],"responses":{"200":{"description":"The matching contacts under contacts, the score values of those contacts under scoreValues, and the count and paging details under meta.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"scoreValues\": [],\n    \"contacts\": [\n        {\n            \"cdate\": \"2024-03-05T10:15:00-06:00\",\n            \"email\": \"sam1@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"Sam\",\n            \"lastName\": \"Example\",\n            \"orgid\": \"0\",\n            \"orgname\": \"\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": null,\n            \"hash\": \"6ad5ccd080166d3812abcc4bd499154d\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"example.com\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": \"2024-03-05T10:15:00-06:00\",\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2024-03-05 10:15:00\",\n            \"updated_utc_timestamp\": \"2024-03-05 10:15:00\",\n            \"created_timestamp\": \"2024-03-05 10:15:00\",\n            \"updated_timestamp\": \"2024-03-05 10:15:00\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"mpp_tracking\": \"0\",\n            \"last_click_date\": null,\n            \"last_open_date\": null,\n            \"last_mpp_open_date\": null,\n            \"best_send_hour\": null,\n            \"sms_consent\": null,\n            \"sms_consent_updated_at\": null,\n            \"whatsapp_id\": null,\n            \"whatsapp_username\": null,\n            \"scoreValues\": [],\n            \"accountContacts\": [],\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/1/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/1/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC\",\n                \"contactData\": \"https://:account.api-us1.com/api/3/contacts/1/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/1/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/1/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/1/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/1/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/1/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/3/contacts/1/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/1/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/1/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/3/contacts/1/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/3/contacts/1/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/1/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/1/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/1/scoreValues\",\n                \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/1/automationEntryCounts\"\n            },\n            \"id\": \"1\",\n            \"organization\": null\n        },\n        {\n            \"cdate\": \"2024-03-06T09:01:12-06:00\",\n            \"email\": \"sam2@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"Sam\",\n            \"lastName\": \"Example\",\n            \"orgid\": \"0\",\n            \"orgname\": \"\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": null,\n            \"hash\": \"1a94db3f156834eee63256a6c6282c2f\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"example.com\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": \"2024-03-06T09:01:12-06:00\",\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2024-03-06 09:01:12\",\n            \"updated_utc_timestamp\": \"2024-03-06 09:01:12\",\n            \"created_timestamp\": \"2024-03-06 09:01:12\",\n            \"updated_timestamp\": \"2024-03-06 09:01:12\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"mpp_tracking\": \"0\",\n            \"last_click_date\": null,\n            \"last_open_date\": null,\n            \"last_mpp_open_date\": null,\n            \"best_send_hour\": null,\n            \"sms_consent\": null,\n            \"sms_consent_updated_at\": null,\n            \"whatsapp_id\": null,\n            \"whatsapp_username\": null,\n            \"scoreValues\": [],\n            \"accountContacts\": [],\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/2/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/2/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC\",\n                \"contactData\": \"https://:account.api-us1.com/api/3/contacts/2/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/2/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/2/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/2/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/2/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/2/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/3/contacts/2/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/2/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/2/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/3/contacts/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/3/contacts/2/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/2/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/2/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/2/scoreValues\",\n                \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/2/automationEntryCounts\"\n            },\n            \"id\": \"2\",\n            \"organization\": null\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\",\n        \"sortable\": true,\n        \"page_input\": {\n            \"segmentid\": null,\n            \"formid\": 0,\n            \"listid\": 0,\n            \"tagid\": 0,\n            \"limit\": 20,\n            \"offset\": 0,\n            \"search\": null,\n            \"sort\": null,\n            \"seriesid\": 0,\n            \"waitid\": 0,\n            \"status\": -1,\n            \"forceQuery\": 0,\n            \"cacheid\": \"522b5224f2007dca7483e08e7ebf5005\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"scoreValues":{"type":"array","description":"The score values of the contacts on this page: one row per contact score, plus one row per deal for each deal score. Present only when contacts is not empty. Rows for deleted scores are left out.","items":{"$ref":"#/components/schemas/ContactScoreValue"}},"contacts":{"type":"array","description":"The contacts on this page. Empty with meta=only, and while a segment is still being processed.","items":{"description":"The contact record, plus the ids of its score values and account links.","allOf":[{"$ref":"#/components/schemas/Contact"},{"type":"object","properties":{"scoreValues":{"type":"array","description":"Ids of the contact's score values. The rows themselves are in the top-level scoreValues array. Rows for deleted scores are left out.","items":{"type":"string"}},"accountContacts":{"type":"array","description":"Ids of the account links for this contact. Empty when the account does not have the Accounts feature.","items":{"type":"string"}},"sdate":{"type":["string","null"],"description":"Present only with segmentid. The contact's creation date again, the same moment as cdate, in ISO 8601 with the account's UTC offset."},"status":{"type":["string","null"],"description":"Present only with segmentid. A list status for the contact: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced. With status set it is that value. With listid it is the status on that list. Otherwise it is the status on one of the contact's lists, with no rule for which. Null when there is no such list membership."},"ip4_last":{"type":["string","null"],"description":"Present only with segmentid. The IP address recorded on the last subscription change, from one of the contact's list memberships, as a whole number. \"0\" when none was recorded. Null when the contact is on no list."},"sorted_score":{"type":["string","null"],"description":"Present only with orders[score] and sortId. The contact's highest value for that score. Null when the contact has no value for it."},"fieldVal":{"type":["string","null"],"description":"The contact's value for the custom field named by sortId. Present only with orders[field] and sortId, and only when the request also sends segmentid, orders[score] or orders[orgname]. Null when the contact has no value for the field."}}}]}},"meta":{"type":"object","description":"Counts and paging details. Left out when the request sends meta=omit, except with a segmentid that names a segment, where meta is normally returned.","properties":{"total":{"type":["string","integer"],"description":"Number of contacts that match the query, across all pages. A string, except with a segmentid that names a segment, where it is a number. With a segment it can still be growing while the segment is processed."},"sortable":{"type":"boolean","description":"True when no more than 500,000 contacts match, so the result set can be sorted by a custom field or score."},"page_input":{"type":"object","description":"The paging and filter inputs, read back from the query string the way the web app reads them. The values are normalized and are not always what the query used. Do not rely on them to page.","properties":{"segmentid":{"type":["integer","string","null"],"description":"The segmentid sent, as a number or as the text sent. Null when none was sent."},"formid":{"type":"integer","description":"The formid sent, or 0."},"listid":{"type":"integer","description":"The listid sent, or 0."},"tagid":{"type":"integer","description":"The tagid sent, or 0."},"limit":{"type":"integer","description":"The page size. A request can ask for 1 to 100; larger values are capped at 100. This field only reports 5, 10, 20, 50 or 100: any other limit sent is reported as 20, even though the query uses the limit sent.","minimum":1,"maximum":100},"offset":{"type":"integer","description":"The offset sent, or 0."},"search":{"type":["string","null"],"description":"The search sent, trimmed. Also set from q. Null when neither was sent."},"sort":{"type":["string","null"],"description":"The sort sent. Null when none was sent."},"seriesid":{"type":"integer","description":"The seriesid sent, or 0."},"waitid":{"type":"integer","description":"The waitid sent, or 0."},"status":{"type":"integer","description":"The status sent, or -1."},"forceQuery":{"type":["integer","boolean"],"description":"1 when forceQuery was sent, otherwise 0. true when a forced segment run is already in progress for this session."},"cacheid":{"type":"string","description":"A random id for this read."},"email_like":{"type":"string","description":"The email_like sent. Present only when it was sent."},"email":{"type":"string","description":"The email sent. Present only when it was sent."},"customer_account":{"type":"string","description":"The organization or account parameter sent. Present only when one was sent."}}},"waiting":{"type":"boolean","description":"Present only with segmentid. True while the segment is still being processed. contacts is then empty; repeat the request to get the matches."},"segment":{"type":["object","null"],"description":"Present only with segmentid. The segment record the server loaded. Its contents are internal."},"segment_conds":{"type":"integer","description":"Present only with segmentid. Number of conditions in the segment."},"time_since_updated":{"type":"integer","description":"Present only with segmentid. Seconds since the current segment processing run started."},"partialOnly":{"type":"boolean","description":"Present only with segmentid, on some responses. Always false."},"run_id":{"type":["string","null"],"description":"Present only with segmentid, on some responses. Id of the segment processing run."},"start_time":{"type":["integer","string","null"],"description":"Present only with segmentid, on some responses. When the segment processing run started, as a Unix timestamp."},"mysql":{"description":"Present only with segmentid, on some responses. Internal processing state."},"debugging":{"type":"object","description":"Present only with segmentid, while the segment is incomplete or when forceQuery is set. Internal processing state.","properties":{"query_begun":{"type":"boolean","description":"True once processing of the segment has started."},"query_done":{"type":["boolean","null"],"description":"True once processing of the segment has finished."}}}}}}}}}},"400":{"description":"A query parameter is invalid. Body: errors, a list with one item whose status is the string \"400\" and whose detail says why: limit is not a positive whole number (\"limit must be a positive integer\"); filters[created_before], filters[created_after], filters[updated_before] or filters[updated_after] is blank or not a date (\"Invalid date format provided: ...\"); tagid and filters[tagName] are both sent; filters[tagName] holds no usable tag name; or a name in filters[tagName] matches no tag (\"Tag not found: \" followed by the names).","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item describing the problem.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string.","example":"400"},"detail":{"type":"string","description":"What was wrong with the request.","example":"limit must be a positive integer"}}}}}},"example":{"errors":[{"status":"400","detail":"limit must be a positive integer"}]}}}}},"deprecated":false}},"/contacts/bulk-edits":{"get":{"summary":"List the account's contact bulk edits (alias of GET /contacts/bulkEdit)","description":"The same list as GET /contacts/bulkEdit, served at a second path. It is not meant for API clients.","operationId":"list-all-contact-bulk-edits-alias","parameters":[{"name":"limit","in":"query","description":"Number of bulk edits to return, from 1 to 100.","schema":{"type":"integer","default":20}},{"name":"offset","in":"query","description":"Where the page starts. It is rounded down to a multiple of limit: offset=25 with limit=20 starts at the 21st bulk edit, and offset=5 at the first.","schema":{"type":"integer","default":0}},{"name":"orders[]","in":"query","description":"Sort order, keyed by column: orders[cdate]=DESC. Columns: cdate, ldate, status, total, completed, percentage; direction ASC or DESC. Only the first valid column is used; the default is cdate DESC.","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"The page of bulk edits under bulkEdit. meta.total is the number of bulk edits on the account, and meta.page_input holds the limit and offset used (20 and 0 when omitted)."},"422":{"description":"limit, offset or orders is out of range or of the wrong type."}},"x-canonical-resource":"contact","x-internal":true}},"/contacts/bulkEdit":{"get":{"summary":"List the account's contact bulk edits","description":"One page of the bulk edits run on this account, newest first by default, with each edit's settings, status and progress. It serves the bulk edit screen in the app and is not meant for API clients.","operationId":"list-all-contact-bulk-edits","parameters":[{"name":"limit","in":"query","description":"Number of bulk edits to return, from 1 to 100.","schema":{"type":"integer","default":20}},{"name":"offset","in":"query","description":"Where the page starts. It is rounded down to a multiple of limit: offset=25 with limit=20 starts at the 21st bulk edit, and offset=5 at the first.","schema":{"type":"integer","default":0}},{"name":"orders[]","in":"query","description":"Sort order, keyed by column: orders[cdate]=DESC. Columns: cdate, ldate, status, total, completed, percentage; direction ASC or DESC. Only the first valid column is used; the default is cdate DESC.","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"The page of bulk edits under bulkEdit. meta.total is the number of bulk edits on the account, and meta.page_input holds the limit and offset used (20 and 0 when omitted)."},"422":{"description":"limit, offset or orders is out of range or of the wrong type."}},"x-canonical-resource":"contact","x-internal":true}},"/contacts/bulk_delete":{"delete":{"summary":"Delete multiple contacts","description":"Deletes several contacts in one call. This is the v3 equivalent of the v1 `contact_delete_list` action.\n\nThe body selects what to delete, in one of two shapes:\n\n- `{\"ids\": [1, 2]}` deletes the given contacts.\n- `{\"deleteAll\": true}` deletes every contact that is actively subscribed to a list the caller can access.\n\n`ids` and `deleteAll` are mutually exclusive. Either shape may add `listids` to limit the delete to those lists. The accessible lists are the lists the API user's group may manage; `listids` is narrowed to them.\n\nA contact is removed from each affected list. A contact removed from its last list is deleted from the account and moved to the contact archive, where it is kept for 360 days and may be restored (see GET /contactArchives). A contact on no list is deleted from the account directly, and archived the same way. Removing a contact from a list it stays on is not archived. A contact on only one list is deleted from the account even when that list is not in `listids`.\n\nThere is no cap on the number of ids per request, but deletion runs synchronously one contact at a time, so very large requests may time out. The account also has a delete allowance per billing period, set by its plan; when it is used up the run stops.\n\nDeletion is not transactional: contacts are removed one at a time, so a call can partially succeed. `deleted` and `failed` report the outcome per contact id. With `deleteAll`, a contact gone since the ids were collected is skipped silently.\n\nRequires permission to delete contacts. Any method other than DELETE answers 405.","operationId":"bulk-delete-contacts","requestBody":{"description":"Which contacts to delete: an explicit `ids` list or `deleteAll`, optionally narrowed by `listids`.","required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"By id","description":"Delete the listed contacts.","required":["ids"],"properties":{"ids":{"description":"Ids of the contacts to delete. Positive integers; numeric strings are accepted and duplicates are ignored. `\"_all\"` is not accepted here; use `deleteAll` instead.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]},"minItems":1},"listids":{"description":"Only remove the contacts from these lists. Positive integers; numeric strings are accepted. Omit to remove them from every accessible list.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]},"minItems":1},"deleteAll":{"description":"Not allowed together with `ids`; a body with both keys is rejected with 400. It is listed here so that such a body matches both shapes and fails the `oneOf` check.","type":"boolean","enum":[true]}},"type":"object"},{"title":"All contacts","description":"Delete every contact actively subscribed to the accessible lists, or to `listids` when given.","required":["deleteAll"],"properties":{"deleteAll":{"description":"Must be `true`.","type":"boolean","enum":[true]},"listids":{"description":"Only remove the contacts from these lists. Positive integers; numeric strings are accepted. Omit to remove them from every accessible list.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]},"minItems":1},"ids":{"description":"Not allowed together with `deleteAll`; a body with both keys is rejected with 400. It is listed here so that such a body matches both shapes and fails the `oneOf` check.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]},"minItems":1}},"type":"object"}]},"examples":{"By id":{"summary":"Delete two contacts from every accessible list","value":{"ids":[1,2]}},"All contacts on two lists":{"summary":"Remove every contact from lists 3 and 4","value":{"deleteAll":true,"listids":[3,4]}}}}}},"responses":{"200":{"description":"The request was processed. `deleted` lists the contacts removed from the targeted lists, and from the account when that left them on no list; `failed` lists any requested ids that did not exist. With `deleteAll`, finding nothing to delete also answers 200 with empty lists, `succeeded` 1 and the message \"Contacts deleted\".","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkDeleteResult"},"example":{"succeeded":1,"message":"Contacts deleted","deleted":[1,2],"failed":[{"id":3,"reason":"Contact not found."}]}}}},"400":{"description":"The body is not valid and nothing was deleted. `message` is one of:\n\n- Bad request. Body must be an object with \"ids\" or \"deleteAll\": true, and optionally \"listids\".\n- Bad request. \"ids\" and \"deleteAll\" are mutually exclusive.\n- Bad request. Contact ids must be non-empty.\n- Bad request. Contact ids must be positive integers.\n- Bad request. \"_all\" is not supported in \"ids\"; use \"deleteAll\": true.\n- Bad request. \"deleteAll\" must be true.\n- Bad request. \"listids\" must be a non-empty array of positive integers.","content":{"application/json":{"schema":{"required":["succeeded","message"],"properties":{"succeeded":{"description":"Always 0.","type":"integer"},"message":{"description":"Which rule the body broke.","type":"string"}},"type":"object"},"example":{"succeeded":0,"message":"Bad request. \"ids\" and \"deleteAll\" are mutually exclusive."}}}},"403":{"description":"Nothing was deleted. Either the API user may not delete contacts, or no list is accessible: the requested `listids` name none of the API user's lists, or no `listids` were sent and the user's group has no lists (`message` is \"None of the requested lists are accessible.\"). `deleted` and `failed` are empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkDeleteResult"}}}},"404":{"description":"None of the requested ids exists. Nothing was deleted; `message` is \"Contact not found.\" and every id is listed in `failed` with that same reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkDeleteResult"}}}},"405":{"description":"The request used a method other than DELETE. Nothing was deleted. The body is always `{\"succeeded\": 0, \"message\": \"Method not supported. Only DELETE supported.\"}`.","content":{"application/json":{"example":{"succeeded":0,"message":"Method not supported. Only DELETE supported."}}}},"422":{"description":"The account's delete allowance for this billing period is used up. `deleted` lists the ids removed before the stop, `failed` the rest with that reason (in `ids` mode it may also hold earlier \"Contact not found.\" entries), and `pastlimit` is 1.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkDeleteResult"},"example":{"succeeded":0,"message":"You cannot delete any more contacts in this billing period","deleted":[1],"failed":[{"id":2,"reason":"You cannot delete any more contacts in this billing period"}],"pastlimit":1}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true}},"/contacts/getDefaultContactOwner":{"get":{"summary":"Retrieve the default contact owner","description":"Returns the account's default contact owner setting: the ID of the user that a new contact gets as its owner when none is given. When val is empty, or the user no longer exists, new contacts are owned by the main admin user (ID 1). Set it with PUT /contacts/setDefaultContactOwner. It returns the account-wide setting, or a per-user copy of it left by older code. Only GET is answered; other methods get an empty response.","operationId":"retrieve-default-contact-owner","x-canonical-resource":"contact","responses":{"200":{"description":"The setting under val.","content":{"application/json":{"schema":{"type":"object","properties":{"val":{"type":"string","description":"ID of the default owner, as a string. An empty string when no default owner has been set."}}},"example":{"val":"5"}}}}},"x-internal":true}},"/contacts/setDefaultContactOwner":{"put":{"summary":"Set the default contact owner","description":"Sets the user that a new contact gets as its owner when none is given. Pass the user ID as the val query parameter; a request body is not read. The setting is stored once for the whole account: any per-user copies of it are deleted first, and an existing setting is overwritten. Read it with GET /contacts/getDefaultContactOwner. Only PUT is answered; other methods get an empty response and change nothing.","operationId":"set-default-contact-owner","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"val","in":"query","required":true,"description":"ID of the user to make the default owner. A value that starts with a number is cut to that number, so 5abc is read as 5 and 1e3 as 1000. Only a value that becomes 0 (missing, 0 or not starting with a number) answers 422; a negative value answers 404.","schema":{"type":"integer"},"example":5}],"responses":{"200":{"description":"The setting was saved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true."}}},"example":{"success":true}}}},"404":{"description":"No user has that ID, including any negative value.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"No Result found for User with id 12"}}}},"422":{"description":"val is missing or becomes 0, for example abc.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"detail":{"type":"string"}}}}}},"example":{"errors":[{"status":"422","detail":"Invalid user id was provided."}]}}}}},"x-internal":true}},"/contacts/top":{"get":{"summary":"List the top contacts","description":"Lists up to 20 contacts with the highest rating, highest first, for the overview widget. The rating counts the contact's email opens and clicks. A user outside the main user group only sees contacts with an active subscription to a list their groups can access. There are no parameters or paging. The route does not check the method; the app uses GET, and other methods behave the same.","operationId":"list-top-contacts","x-canonical-resource":"contact","responses":{"200":{"description":"A JSON array of contacts, not wrapped in an object. An empty array when there are none.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the contact."},"email":{"type":["string","null"],"description":"Email address of the contact; null for a contact with no email."},"firstName":{"type":"string","description":"First name; an empty string when not set."},"lastName":{"type":"string","description":"Last name; an empty string when not set."},"rating":{"type":"string","description":"The rating, as a whole number in a string."},"listsCount":{"type":"integer","description":"Number of lists the contact is actively subscribed to."}}}},"example":[{"id":"12","email":"sam@example.com","firstName":"Sam","lastName":"Example","rating":"42","listsCount":2}]}}}},"x-internal":true}},"/contacts/{contactId}/notes":{"get":{"summary":"Retrieve a contact's notes","description":"The notes attached to one contact. Each note carries its text, the account user who wrote it (userid), and when it was created and last changed (cdate, mdate). Every note comes back in one response, drafts included (is_draft): limit, offset, filters and orders are ignored on this path, and no order is guaranteed, so sort on cdate yourself if order matters. To add a note to a contact, use POST /contacts/{contactId}/notes (create-a-contact-note). Returns 404 if the contact does not exist.","operationId":"retrieve-contact-notes","x-canonical-resource":"contact","parameters":[{"name":"contactId","in":"path","description":"ID of the contact whose notes are returned","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's notes under notes; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"notes\": [\n        {\n            \"relid\": \"7\",\n            \"reltype\": \"Subscriber\",\n            \"userid\": \"1\",\n            \"is_draft\": \"0\",\n            \"cdate\": \"2022-02-04T14:21:28-06:00\",\n            \"mdate\": \"2022-02-04T14:21:28-06:00\",\n            \"note\": \"Here is a note!\",\n            \"links\": {\n                \"activities\": \"https://:account.api-us1.com/api/3/notes/1/activities\",\n                \"user\": \"https://:account.api-us1.com/api/3/notes/1/user\",\n                \"mentions\": \"https://:account.api-us1.com/api/3/notes/1/mentions\",\n                \"notes\": \"https://:account.api-us1.com/api/3/notes/1/notes\",\n                \"owner\": \"https://:account.api-us1.com/api/3/notes/1/owner\"\n            },\n            \"id\": \"1\",\n            \"user\": \"1\",\n            \"owner\": {\n                \"type\": \"contact\",\n                \"id\": \"7\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"notes":{"type":"array","description":"One entry per note attached to the contact.","items":{"type":"object","properties":{"relid":{"type":"string","description":"ID of the record the note is attached to; the contact id here.","example":"7"},"reltype":{"type":"string","description":"Type of record the note is attached to; always Subscriber here.","example":"Subscriber"},"userid":{"type":"string","description":"ID of the account user who wrote the note.","example":"1"},"is_draft":{"type":"string","description":"1 while the note is a draft, 0 once published.","example":"0"},"cdate":{"type":["string","null"],"description":"When the note was created.","example":"2022-02-04T14:21:28-06:00"},"mdate":{"type":["string","null"],"description":"When the note was last changed.","example":"2022-02-04T14:21:28-06:00"},"note":{"type":["string","null"],"description":"The text of the note.","example":"Here is a note!"},"links":{"type":"object","description":"URLs of the records related to this note.","properties":{"activities":{"type":"string","description":"URL of the activity entries for this note.","example":"https://:account.api-us1.com/api/3/notes/1/activities"},"user":{"type":"string","description":"URL of the account user who wrote the note.","example":"https://:account.api-us1.com/api/3/notes/1/user"},"mentions":{"type":"string","description":"URL of the mention records for this note.","example":"https://:account.api-us1.com/api/3/notes/1/mentions"},"notes":{"type":"string","description":"URL of the notes attached to this note.","example":"https://:account.api-us1.com/api/3/notes/1/notes"},"owner":{"type":"string","description":"URL of the record the note is attached to.","example":"https://:account.api-us1.com/api/3/notes/1/owner"}}},"id":{"type":"string","description":"ID of the note.","example":"1"},"user":{"type":"string","description":"ID of the account user who wrote the note, the same as userid.","example":"1"},"owner":{"type":"object","description":"The record the note is attached to.","properties":{"type":{"type":"string","description":"Type of the owning record; contact here.","example":"contact"},"id":{"type":"string","description":"ID of the owning record; the contact id here.","example":"7"}}}}}}}}}}},"404":{"description":"No contact with that id.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Subscriber with id 999999999\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id."}}}}}}},"deprecated":false},"post":{"summary":"Create a note on a contact","description":"Adds a note to the contact named in the path. The path says which contact owns the note, so the body does not name one: owner and ownerType are dropped, and reltype and relid are replaced with the contact from the path. The author is the authenticated API user. Unless the note is a draft, the contact note webhook fires. Returns 404 when the contact does not exist, 422 when the body has no note object or its note text is missing or blank, 400 when listId is not a whole number of 0 or more, and 403 when the API user may not edit contacts.","operationId":"create-a-contact-note","parameters":[{"name":"contactId","in":"path","description":"ID of the contact the note is created on","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["note"],"properties":{"note":{"description":"The note to create.","required":["note"],"properties":{"note":{"description":"The text of the note. Emoji are removed and HTML characters are escaped before it is saved.","type":"string"},"is_draft":{"description":"0 or 1. 1 saves the note as a draft: the note webhook does not fire. Defaults to 0.","type":"integer"},"mentionStrings":{"description":"Usernames to mention, each written as @username. Every matching user who is not already mentioned on this note gets a mention record and a notification. Not returned on the note.","type":"array","items":{"type":"string"}},"listId":{"description":"Id of the list whose contact-note webhooks fire for this note; 0, the default, fires the webhooks of every list. Not stored on the note. 400 when it is not a whole number of 0 or more.","type":"integer","format":"int32"}},"type":"object"}},"type":"object"},"example":{"note":{"note":"Called about the renewal.","is_draft":0,"mentionStrings":["@sam.example"],"listId":0}}}}},"responses":{"201":{"description":"The created note, under note. The contact it belongs to comes along under contacts.","content":{"application/json":{"schema":{"properties":{"contacts":{"description":"The contact the note was created on, as the only item, in the shape GET /contacts/{id} returns.","type":"array","items":{"type":"object"}},"note":{"description":"The created note.","properties":{"relid":{"description":"Id of the contact the note belongs to, taken from the path.","type":"integer","example":2},"reltype":{"description":"The kind of record the note belongs to. Always Subscriber here, which is a contact.","type":"string","example":"Subscriber"},"userid":{"description":"Id of the account user who wrote the note: the authenticated API user.","type":"string","example":"1"},"is_draft":{"description":"1 while the note is a draft, 0 once published.","type":"string","example":"0"},"cdate":{"description":"When the note was created, as a date and time with UTC offset.","type":"string","example":"2018-09-28T17:45:11-05:00"},"mdate":{"description":"When the note was last changed, as a date and time with UTC offset. Equal to cdate on a new note.","type":"string","example":"2018-09-28T17:45:11-05:00"},"note":{"description":"The text of the note as saved.","type":"string","example":"Called about the renewal."},"links":{"description":"URLs of the records related to the note.","properties":{"activities":{"description":"URL of the activities that reference the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/activities"},"user":{"description":"URL of the account user who wrote the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/user"},"mentions":{"description":"URL of the mentions on the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/mentions"},"notes":{"description":"URL of the notes attached to this note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/notes"},"owner":{"description":"URL of the contact the note belongs to.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/owner"}},"type":"object"},"owner":{"description":"The record the note belongs to.","properties":{"type":{"description":"The API type of the owning record. Always contact here.","type":"string","example":"contact"},"id":{"description":"Id of the contact.","type":"integer","example":2}},"type":"object"},"id":{"description":"Id of the note.","type":"string","example":"2"},"user":{"description":"Id of the account user who wrote the note. The same value as userid.","type":"string","example":"1"}},"type":"object"}},"type":"object"}}}},"400":{"description":"listId is not a whole number of 0 or more. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The API user may not edit contacts. Body: errors, a list with one item carrying status, title and detail."},"404":{"description":"No contact with that id. Body: message, a sentence naming the id."},"422":{"description":"The body has no note object, or its note text is missing or blank. A body that is not a JSON object, or a note member that is not an object, is treated as an empty note. Body: errors, a list with one item carrying title, detail, code (field_missing), error and source.pointer (/data/attributes/note)."}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false}},"/contacts/{contactId}/notes/{noteId}":{"delete":{"summary":"Delete a note from a contact","description":"Deletes one of the contact's own notes. The note must belong to the contact in the path: a note on another contact, on a deal or on an account is a 404 here. Only the user who wrote the note, or an admin user, may delete it. Returns 404 when the contact does not exist, the note is not one of its notes, or the API user may not edit contacts; and 403 when the API user is neither the author nor an admin user, or the delete fails. The response body is an empty object.","operationId":"delete-a-contact-note","parameters":[{"name":"contactId","in":"path","description":"ID of the contact the note belongs to","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"noteId","in":"path","description":"ID of the note to delete","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The note was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The API user is neither the author of the note nor an admin user, or the delete failed. Body: a plain-text sentence, not JSON."},"404":{"description":"No contact with that id: body message, a sentence naming the contact id. The API user may not edit contacts: body message, a sentence naming the note id. Or the note is not one of this contact's notes: body errors, a list with one item carrying status, title and detail."}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false},"put":{"summary":"Update a note on a contact","description":"Changes one of the contact's own notes. PATCH on this path does the same. The note must belong to the contact in the path: a note on another contact, on a deal or on an account is a 404 here. Only the user who wrote the note may change it. Fields left out of the body keep their values, and mdate is set to now. When is_draft goes from 1 to 0, the draft is published and the contact note webhook fires for every list. Returns 404 when the contact does not exist, the note is not one of its notes, or the API user may not edit contacts; 403 when the API user did not write the note; and 422 when the note text is set to blank.","operationId":"update-a-contact-note","parameters":[{"name":"contactId","in":"path","description":"ID of the contact the note belongs to","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"noteId","in":"path","description":"ID of the note to update","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"note":{"description":"The changes to make. Every member is optional. A body that is not a JSON object, or a note member that is not an object, is treated as an empty note: only mdate changes.","properties":{"note":{"description":"The new text of the note. Emoji are removed, HTML characters are escaped and surrounding spaces are trimmed before it is saved. 422 when it is blank or null.","type":"string"},"is_draft":{"description":"0 or 1. 1 keeps the note as a draft. Setting 0 on a draft publishes it, and the contact note webhook fires.","type":"integer"},"mentionStrings":{"description":"Usernames to mention, each written as @username. Every matching user who is not already mentioned on this note gets a mention record and a notification. Existing mentions are kept. Not returned on the note.","type":"array","items":{"type":"string"}}},"type":"object"}},"type":"object"},"example":{"note":{"note":"Called again about the renewal.","is_draft":0,"mentionStrings":["@sam.example"]}}}}},"responses":{"200":{"description":"The updated note, under note.","content":{"application/json":{"schema":{"properties":{"note":{"description":"The updated note.","properties":{"relid":{"description":"Id of the contact the note belongs to.","type":"string","example":"2"},"reltype":{"description":"The kind of record the note belongs to. Always Subscriber here, which is a contact.","type":"string","example":"Subscriber"},"userid":{"description":"Id of the account user who wrote the note.","type":"string","example":"1"},"is_draft":{"description":"1 while the note is a draft, 0 once published. When the body sets is_draft, the value comes back as sent; true and false come back as 1 and 0.","type":["string","integer"],"example":0},"cdate":{"description":"When the note was created, as a date and time with UTC offset.","type":"string","example":"2018-09-28T17:45:11-05:00"},"mdate":{"description":"When the note was last changed, as a date and time with UTC offset. Set to now by this request.","type":"string","example":"2018-10-02T09:12:40-05:00"},"note":{"description":"The text of the note as saved.","type":"string","example":"Called again about the renewal."},"links":{"description":"URLs of the records related to the note.","properties":{"activities":{"description":"URL of the activities that reference the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/activities"},"user":{"description":"URL of the account user who wrote the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/user"},"mentions":{"description":"URL of the mentions on the note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/mentions"},"notes":{"description":"URL of the notes attached to this note.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/notes"},"owner":{"description":"URL of the contact the note belongs to.","type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/owner"}},"type":"object"},"owner":{"description":"The record the note belongs to.","properties":{"type":{"description":"The API type of the owning record. Always contact here.","type":"string","example":"contact"},"id":{"description":"Id of the contact.","type":"string","example":"2"}},"type":"object"},"id":{"description":"Id of the note.","type":"string","example":"2"},"user":{"description":"Id of the account user who wrote the note. The same value as userid.","type":"string","example":"1"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The API user did not write the note. Body: a plain-text sentence, not JSON."},"404":{"description":"No contact with that id: body message, a sentence naming the contact id. The API user may not edit contacts: body message, a sentence naming the note id. Or the note is not one of this contact's notes: body errors, a list with one item carrying status, title and detail."},"422":{"description":"The body sets the note text to blank or null. Body: errors, a list with one item carrying title, detail, code (field_missing), error and source.pointer (/data/attributes/note)."}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false}},"/contacts/{contactId}/smsConfirmation/resend":{"post":{"summary":"Resend the SMS confirmation text to a contact","description":"Texts the SMS double opt-in confirmation message again to a contact whose subscription to an SMS list is still Unconfirmed. The message is the confirmation text of the form the contact subscribed through, sent to the phone number on the contact. Nothing is sent, and the call answers 404, when the contact has no Unconfirmed subscription to that SMS list, the subscription did not come from a form (a keyword subscription, for example), the contact has no phone number, the form no longer exists or has no confirmation text. On an account that uses granular SMS permissions, a user without the campaigns.send SMS permission gets 403, before any problem with the body is reported; users in the main user group can always resend. Only POST is allowed.","operationId":"resend-a-contact-sms-confirmation","parameters":[{"name":"contactId","in":"path","description":"ID of the contact","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"description":"The SMS list whose confirmation to resend, as a JSON object.","required":true,"content":{"application/json":{"schema":{"required":["listId"],"properties":{"listId":{"description":"ID of the SMS list the contact is waiting to confirm. Send it as a JSON number.","type":"integer","minimum":1}},"type":"object"},"example":{"listId":3}}}},"responses":{"200":{"description":"The confirmation text was queued for sending.","content":{"application/json":{"schema":{"properties":{"smsConfirmation":{"properties":{"contactId":{"description":"ID of the contact, from the path.","type":"integer"},"listId":{"description":"ID of the SMS list, from the body.","type":"integer"},"resent":{"description":"Always true.","type":"boolean"}},"type":"object"}},"type":"object"},"example":{"smsConfirmation":{"contactId":12,"listId":3,"resent":true}}}}},"400":{"description":"The body is empty, is not valid JSON, or is a JSON scalar such as a number or a string. detail is \"Request body is empty.\", \"Could not decode request body.\" or a message that the JSON did not decode to an array. A JSON array is read like an object and answers 422 for the missing listId.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"string"},"detail":{"type":"string"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The account enforces granular SMS permissions and the user does not have the campaigns.send SMS permission.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer"},"title":{"type":"string"},"detail":{"type":"string"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Missing SMS permission: campaigns.send"}]}}}},"404":{"description":"There was nothing to resend; see the description for every case. An unknown contact or list also answers 404.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer"},"title":{"type":"string"},"detail":{"type":"string"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"No unconfirmed SMS subscription to resend"}]}}}},"422":{"description":"listId is missing, including when the body is a JSON array (\"This value should not be blank.\"), is not a positive number (\"This value should be positive.\"), or is not a JSON integer, for example a string or null (\"Unexpected type\").","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"type":"integer"},"title":{"type":"string"},"detail":{"type":"string"},"source":{"properties":{"pointer":{"description":"The field, as /data/attributes/listId.","type":"string"}},"type":"object"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/listId"}}]}}}}},"x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/contacts/{contactId}/tags":{"delete":{"summary":"Remove a tag from a contact by tag name","description":"Removes one tag from a contact, addressed by contact id and tag name, without needing the contactTag association id that DELETE /contactTags/{id} requires. Pass the tag name in the tag query parameter. To remove by tag id instead, use DELETE /contacts/{contactId}/tags/{tagId}; exactly one of the two must be used per request. The tag definition itself is not deleted. Returns 404 if the contact does not exist, the tag name does not exist, or the tag is not applied to that contact. Names containing commas or line breaks fail with 400.","operationId":"remove-a-tag-from-a-contact-by-name","parameters":[{"name":"contactId","in":"path","description":"ID of the contact","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"tag","in":"query","description":"Name of the tag to remove from the contact.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The tag was removed from the contact. The body is an empty object.","content":{"application/json":{"schema":{"description":"Empty object","type":"object"},"example":{}}}},"400":{"description":"The tag query parameter is missing, is blank, or contains a comma or a line break.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong. One of: \"No tag id or tag name provided\", \"No tag name provided\", \"Tag name cannot contain commas or line breaks\".","type":"string","example":"Tag name cannot contain commas or line breaks"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Tag name cannot contain commas or line breaks"}]}}}},"404":{"description":"The contact does not exist, the tag name does not exist, or the tag is not applied to that contact.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":404},"title":{"description":"Short name of the HTTP status","type":"string","example":"Not Found"},"detail":{"description":"What went wrong. One of: \"Contact not found\", \"Tag not found\", \"Tag is not applied to that contact\".","type":"string","example":"Tag is not applied to that contact"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Tag is not applied to that contact"}]}}}}},"x-canonical-resource":"contactTags","x-destructive":true,"x-bulk-operation":false},"post":{"summary":"Apply tags to a contact","description":"Applies up to 100 tags to one contact in a single request, by tag name, tag id, or both. Tag names that do not exist yet are created automatically unless createMissing is false; tag ids must refer to existing tags. This replaces the per-tag sequence of GET /tags, POST /tags, and POST /contactTags with one call. Returns 201 with every requested association, including ones that already existed, so the request is safe to repeat. Send at least one entry in tags or tagIds. Tag names are matched case-insensitively, and are trimmed and stripped of HTML markup before matching and creation. Returns 404 if the contact does not exist. Fails with 400 for an unknown tag id, an unknown name when createMissing is false, a name held by a deleted tag, a name containing commas, line breaks, emoji, or other 4-byte characters, or a request addressing more than 100 tags. createMissing is true by default: a name in tags that matches no existing tag creates a new tag definition for the whole account, the same as POST /tags does, and then applies it. Creating a tag needs the tag management permission (`pg_tag_manage`), the same permission POST /tags requires; users in the main user group always have it. A user who may edit contacts but not manage tags gets 403 when a request would create a tag, and nothing is created or applied. Applying tags that already exist needs only the contact edit permission. An integration that should only apply tags, never create them, sends tagIds, or sends tags with createMissing set to false; an unknown name then fails with 400 and no tag is created. Users outside the main user group can only tag contacts they have access to. A request may contain at most 200 entries across tags and tagIds, counted after repeated entries within each array are dropped (names compared exactly, after trimming spaces), and may address at most 100 distinct tags once names are resolved. The 201 body differs between a first apply and a repeat: when at least one association is newly created, the body also carries tags (the tag definitions involved) and contacts (the contact) beside contactTags; when every association already existed, only contactTags is returned.","operationId":"apply-tags-to-a-contact","parameters":[{"name":"contactId","in":"path","description":"ID of the contact","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"description":"The tags to apply, by name, by id, or both. At least one entry in tags or tagIds is required.","required":true,"content":{"application/json":{"schema":{"properties":{"tags":{"description":"Tag names to apply. A name that does not exist yet is created, unless createMissing is false. Emoji and other 4-byte characters are not supported.","type":"array","items":{"type":"string"}},"tagIds":{"description":"Ids of existing tags to apply, as positive integers or numeric strings. An unknown id fails the request with 400.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]}},"createMissing":{"description":"Whether to create tags for names that do not exist yet. Only applies to tags; unknown tagIds always fail. Set it to false to apply existing tags only.","type":"boolean","default":true}},"type":"object"},"examples":{"Request Example":{"summary":"Two names and one id","value":{"tags":["Customer","VIP"],"tagIds":[20],"createMissing":true}}}}}},"responses":{"201":{"description":"Every association the request addressed, the ones just applied and the ones that already existed. When at least one was newly created, the tag definitions and the contact are included beside them.","content":{"application/json":{"schema":{"properties":{"contactTags":{"description":"One contact-to-tag association per tag the request addressed.","type":"array","items":{"properties":{"contact":{"description":"The contact id.","type":"string","example":"113"},"tag":{"description":"The tag id. Fetch the name with GET /tags/{id}, or several at once with GET /tags?ids=1,2","type":"string","example":"20"},"cdate":{"description":"When the tag was applied. An association that already existed keeps its original time.","type":"string","example":"2026-09-18T10:52:26-05:00"},"created_timestamp":{"description":"When the row was created, as YYYY-MM-DD HH:MM:SS with no time zone offset (unlike cdate, which is ISO 8601).","type":"string","example":"2026-09-18 10:52:26"},"updated_timestamp":{"description":"When the row was last changed, as YYYY-MM-DD HH:MM:SS with no time zone offset (unlike cdate, which is ISO 8601).","type":"string","example":"2026-09-18 10:52:26"},"created_by":{"description":"Id of the user recorded as creating the association, or null when none was recorded.","type":["string","null"]},"updated_by":{"description":"Id of the user recorded as last changing the association, or null when none was recorded.","type":["string","null"]},"links":{"description":"URLs of the tag and the contact this association joins.","properties":{"tag":{"description":"URL of the tag definition.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/tag"},"contact":{"description":"URL of the contact.","type":"string","example":"https://:account.api-us1.com/api/:version/contactTags/1553/contact"}},"type":"object"},"id":{"description":"The association id. Pass it to DELETE /contactTags/{id} to remove the tag from the contact.","type":"string","example":"1553"}},"type":"object"}},"tags":{"description":"Present only when at least one association was newly created: the full tag definitions involved, including subscriber_count.","type":"array","items":{"type":"object"}},"contacts":{"description":"Present only when at least one association was newly created: the full record of the contact the tags were applied to.","type":"array","items":{"type":"object"}}},"type":"object"}}}},"400":{"description":"The request was rejected; detail is one of: \"Provide at least one tag name in tags or one tag id in tagIds\" (empty body, empty arrays, or a JSON list), \"Request body must be a JSON object with tags and/or tagIds\" (a scalar body), \"tags must be an array of tag names\", \"tags must contain tag names as strings; pass tag ids in tagIds\", \"tags cannot contain an empty tag name\", \"Tag name cannot contain commas or line breaks\", \"Tag name contains invalid characters\" (emoji or other 4-byte characters), \"tagIds must be an array of tag ids\", \"tagIds must contain tag ids as integers; pass tag names in tags\", \"tagIds must contain positive tag ids\", \"createMissing must be true or false\", \"A request cannot contain more than 200 tag references\", \"Unknown tag id {id}\", \"Unknown tag \\\"{name}\\\"\" (createMissing is false), \"Tag \\\"{name}\\\" has been deleted\", \"Tag names cannot be empty, got \\\"{name}\\\"\" (a name that is only markup), or \"A request cannot address more than 100 tags\". The body is validated before the contact is looked up, so an unknown contact with an invalid body gets 400, not 404; an unknown name with createMissing false is reported before the 100-tag limit.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing what was rejected.","type":"array","items":{"properties":{"status":{"description":"The HTTP status code.","type":"integer","example":400},"title":{"description":"The HTTP status text.","type":"string","example":"Bad Request"},"detail":{"description":"What was rejected, naming the tag id or tag name when one is at fault.","type":"string","example":"Unknown tag id 999999999"}},"type":"object"}}},"type":"object"},"examples":{"Unknown tag id":{"summary":"A tag id that does not exist","value":{"errors":[{"status":400,"title":"Bad Request","detail":"Unknown tag id 999999999"}]}},"Unknown tag name with createMissing false":{"summary":"A name that does not exist while createMissing is false","value":{"errors":[{"status":400,"title":"Bad Request","detail":"Unknown tag \"Prospect\""}]}}}}}},"404":{"description":"The contact does not exist.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing what was not found.","type":"array","items":{"properties":{"status":{"description":"The HTTP status code.","type":"integer","example":404},"title":{"description":"The HTTP status text.","type":"string","example":"Not Found"},"detail":{"description":"What was not found.","type":"string","example":"Contact not found"}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The contact does not exist","value":{"errors":[{"status":404,"title":"Not Found","detail":"Contact not found"}]}}}}}}},"x-canonical-resource":"contactTags","x-destructive":false,"x-bulk-operation":true}},"/contacts/{contactId}/tags/{tagId}":{"delete":{"summary":"Remove a tag from a contact by tag id","description":"Removes one tag from a contact, addressed by contact id and tag id, without needing the contactTag association id that DELETE /contactTags/{id} requires. To remove by tag name instead, use DELETE /contacts/{contactId}/tags with the tag query parameter. The tag definition itself is not deleted. Returns 404 if the contact does not exist, the tag does not exist, or the tag is not applied to that contact. A tag id that is not a positive integer, or a request that also passes the tag query parameter, fails with 400.","operationId":"remove-a-tag-from-a-contact-by-id","parameters":[{"name":"contactId","in":"path","description":"ID of the contact","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"tagId","in":"path","description":"ID of the tag to remove from the contact","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The tag was removed from the contact. The body is an empty object.","content":{"application/json":{"schema":{"description":"Empty object","type":"object"},"example":{}}}},"400":{"description":"The tag id is not a positive integer, or the tag query parameter was passed as well.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong. One of: \"Tag id must be a positive integer; pass a tag name in the tag query parameter instead\", \"Provide either a tag id in the path or a tag name in the tag query parameter, not both\".","type":"string","example":"Tag id must be a positive integer; pass a tag name in the tag query parameter instead"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Tag id must be a positive integer; pass a tag name in the tag query parameter instead"}]}}}},"404":{"description":"The contact does not exist, the tag does not exist, or the tag is not applied to that contact.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":404},"title":{"description":"Short name of the HTTP status","type":"string","example":"Not Found"},"detail":{"description":"What went wrong. One of: \"Contact not found\", \"Tag not found\", \"Tag is not applied to that contact\".","type":"string","example":"Tag is not applied to that contact"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Tag is not applied to that contact"}]}}}}},"x-canonical-resource":"contactTags","x-destructive":true,"x-bulk-operation":false}},"/contacts/{id}":{"get":{"summary":"Retrieve a contact","description":"Retrieve an existing contact. The response embeds, as top-level arrays beside contact, the contact's contactLists (each with its channel), contactData, fieldValues, geoIps with their geoAddresses, deals (with exclude[]=deals the contact's deals are not loaded and deals comes back as an empty array), accountContacts with their accounts when the Accounts feature is enabled, and contactAutomations only when automations=true. The embedded arrays are fixed. For other relationships use the sub-resource reads, for example GET /contacts/{id}/contactTags.","operationId":"get-contact","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true},{"name":"automations","in":"query","description":"Set to true to also embed the contact's contactAutomations. They are left out otherwise.","schema":{"type":"string","enum":["true"]}},{"name":"exclude[]","in":"query","description":"Set to deals (exclude[]=deals) so the contact's deals are not loaded; deals then comes back as an empty array. Only the array form is read; exclude=deals does nothing.","schema":{"type":"string","enum":["deals"]}}],"responses":{"200":{"description":"The contact under contact, with its related records as top-level arrays beside it, as listed above.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomations\": [\n        {\n            \"contact\": \"1\",\n            \"seriesid\": \"1\",\n            \"startid\": \"0\",\n            \"status\": \"1\",\n            \"adddate\": \"1976-10-16T23:23:09-05:00\",\n            \"remdate\": null,\n            \"timespan\": null,\n            \"lastblock\": \"0\",\n            \"lastdate\": \"1984-08-15T08:13:44-05:00\",\n            \"completedElements\": 0,\n            \"totalElements\": 0,\n            \"completed\": 0,\n            \"completeValue\": 100,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contactAutomations/1/contactGoals\"\n            },\n            \"id\": \"1\",\n            \"automation\": \"1\"\n        }\n    ],\n    \"contactLists\": [\n        {\n            \"contact\": \"1\",\n            \"list\": \"1\",\n            \"form\": null,\n            \"seriesid\": \"0\",\n            \"sdate\": null,\n            \"udate\": null,\n            \"status\": \"1\",\n            \"responder\": \"1\",\n            \"sync\": \"0\",\n            \"unsubreason\": null,\n            \"campaign\": null,\n            \"message\": null,\n            \"first_name\": \"John\",\n            \"last_name\": \"Doe\",\n            \"ip4Sub\": \"0\",\n            \"sourceid\": \"0\",\n            \"autosyncLog\": null,\n            \"ip4_last\": \"0\",\n            \"ip4Unsub\": \"0\",\n            \"unsubscribeAutomation\": null,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/:version/contactLists/1/automation\",\n                \"list\": \"https://:account.api-us1.com/api/:version/contactLists/1/list\",\n                \"contact\": \"https://:account.api-us1.com/api/:version/contactLists/1/contact\",\n                \"form\": \"https://:account.api-us1.com/api/:version/contactLists/1/form\",\n                \"autosyncLog\": \"https://:account.api-us1.com/api/:version/contactLists/1/autosyncLog\",\n                \"campaign\": \"https://:account.api-us1.com/api/:version/contactLists/1/campaign\",\n                \"unsubscribeAutomation\": \"https://:account.api-us1.com/api/:version/contactLists/1/unsubscribeAutomation\",\n                \"message\": \"https://:account.api-us1.com/api/:version/contactLists/1/message\"\n            },\n            \"id\": \"1\",\n            \"automation\": null\n        }\n    ],\n    \"deals\": [\n        {\n            \"owner\": \"1\",\n            \"contact\": \"1\",\n            \"organization\": null,\n            \"group\": \"1\",\n            \"title\": \"Consectetur omnis quo inventore molestiae ratione amet.\",\n            \"nexttaskid\": \"0\",\n            \"currency\": \"usd\",\n            \"status\": \"0\",\n            \"links\": {\n                \"contact\": \"https://:account.api-us1.com/api/:version/deals/1/contact\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/deals/1/contactDeals\",\n                \"group\": \"https://:account.api-us1.com/api/:version/deals/1/group\",\n                \"nextTask\": \"https://:account.api-us1.com/api/:version/deals/1/nextTask\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/deals/1/notes\",\n                \"account\": \"https://:account.api-us1.com/api/:version/deals/1/account\",\n                \"customerAccount\": \"https://:account.api-us1.com/api/:version/deals/1/customerAccount\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/deals/1/organization\",\n                \"owner\": \"https://:account.api-us1.com/api/:version/deals/1/owner\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/deals/1/scoreValues\",\n                \"stage\": \"https://:account.api-us1.com/api/:version/deals/1/stage\",\n                \"tasks\": \"https://:account.api-us1.com/api/:version/deals/1/tasks\",\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/deals/1/dealCustomFieldData\",\n                \"dealActivities\": \"https://:account.api-us1.com/api/:version/deals/1/dealActivities\"\n            },\n            \"id\": \"1\",\n            \"nextTask\": null\n        }\n    ],\n    \"fieldValues\": [\n        {\n            \"contact\": \"1\",\n            \"field\": \"1\",\n            \"value\": \"\",\n            \"cdate\": \"1981-05-16T19:02:29-05:00\",\n            \"udate\": \"1975-11-08T10:31:45-06:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/:version/fieldValues/1/owner\",\n                \"field\": \"https://:account.api-us1.com/api/:version/fieldValues/1/field\"\n            },\n            \"id\": \"1\",\n            \"owner\": \"1\"\n        }\n    ],\n    \"geoAddresses\": [\n        {\n            \"ip4\": \"823\",\n            \"country2\": \"AS\",\n            \"country\": \"Suriname\",\n            \"state\": \"KY\",\n            \"city\": \"North Arnoldomouth\",\n            \"zip\": \"38704-6592\",\n            \"area\": \"0\",\n            \"lat\": \"-70.160407\",\n            \"lon\": \"-102.229406\",\n            \"tz\": \"Europe/Chisinau\",\n            \"tstamp\": \"1972-03-16T07:26:58-06:00\",\n            \"links\": [],\n            \"id\": \"1\"\n        }\n    ],\n    \"geoIps\": [\n        {\n            \"contact\": \"1\",\n            \"campaignid\": \"1\",\n            \"messageid\": \"1\",\n            \"geoaddrid\": \"1\",\n            \"ip4\": \"0\",\n            \"tstamp\": \"1988-08-05T11:50:51-05:00\",\n            \"geoAddress\": \"1\",\n            \"links\": {\n                \"geoAddress\": \"https://:account.api-us1.com/api/:version/geoIps/1/geoAddress\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"contact\": {\n        \"cdate\": \"2007-05-05T12:49:09-05:00\",\n        \"email\": \"selmer.koss@example.com\",\n        \"phone\": \"\",\n        \"firstName\": \"Charles\",\n        \"lastName\": \"Reynolds\",\n        \"orgid\": \"0\",\n        \"orgname\": \"\",\n        \"segmentio_id\": \"\",\n        \"bounced_hard\": \"0\",\n        \"bounced_soft\": \"0\",\n        \"bounced_date\": null,\n        \"ip\": \"0\",\n        \"ua\": null,\n        \"hash\": \"\",\n        \"socialdata_lastcheck\": null,\n        \"email_local\": \"\",\n        \"email_domain\": \"\",\n        \"sentcnt\": \"0\",\n        \"rating_tstamp\": null,\n        \"gravatar\": \"0\",\n        \"deleted\": \"0\",\n        \"anonymized\": \"0\",\n        \"adate\": null,\n        \"udate\": null,\n        \"edate\": null,\n        \"deleted_at\": null,\n        \"created_utc_timestamp\": \"2007-05-05 12:49:09\",\n        \"updated_utc_timestamp\": \"2007-05-05 12:49:09\",\n        \"created_timestamp\": \"2007-05-05 12:49:09\",\n        \"updated_timestamp\": \"2007-05-05 12:49:09\",\n        \"created_by\": null,\n        \"updated_by\": null,\n        \"mpp_tracking\": \"0\",\n        \"last_click_date\": null,\n        \"last_open_date\": null,\n        \"last_mpp_open_date\": null,\n        \"best_send_hour\": null,\n        \"sms_consent\": null,\n        \"sms_consent_updated_at\": null,\n        \"whatsapp_id\": null,\n        \"whatsapp_username\": null,\n        \"contactAutomations\": [\n            \"1\"\n        ],\n        \"contactLists\": [\n            \"1\"\n        ],\n        \"fieldValues\": [\n            \"1\"\n        ],\n        \"geoIps\": [\n            \"1\"\n        ],\n        \"deals\": [\n            \"1\"\n        ],\n        \"accountContacts\": [\n            \"1\"\n        ],\n        \"links\": {\n            \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/1/bounceLogs\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/1/contactAutomations?limit=2500&orders%5Blastdate%5D=DESC\",\n            \"contactData\": \"https://:account.api-us1.com/api/3/contacts/1/contactData\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/1/contactGoals\",\n            \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/1/contactLists\",\n            \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/1/contactLogs\",\n            \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/1/contactTags\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/1/contactDeals\",\n            \"deals\": \"https://:account.api-us1.com/api/3/contacts/1/deals\",\n            \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/1/fieldValues\",\n            \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/1/geoIps\",\n            \"notes\": \"https://:account.api-us1.com/api/3/contacts/1/notes\",\n            \"organization\": \"https://:account.api-us1.com/api/3/contacts/1/organization\",\n            \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/1/plusAppend\",\n            \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/1/trackingLogs\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/1/scoreValues\",\n            \"accountContacts\": \"https://:account.api-us1.com/api/3/contacts/1/accountContacts\",\n            \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/1/automationEntryCounts\"\n        },\n        \"id\": \"1\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contactAutomations":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"1","description":"ID of the contact."},"seriesid":{"type":"string","example":"1","description":"ID of the automation."},"startid":{"type":"string","example":"0","description":"ID of the start trigger that began this run."},"status":{"type":"string","example":"1","description":"Where the run stands: 1 the contact is still moving through the automation, 2 the run has ended."},"adddate":{"type":["string","null"],"example":"1976-10-16T23:23:09-05:00","description":"When the contact entered the automation."},"remdate":{"description":"When the run ended. Null while it is still running or waiting.","type":["string","null"]},"timespan":{"description":"Seconds between adddate and remdate. Null while the run has not ended.","type":["string","null"]},"lastblock":{"type":"string","example":"0","description":"ID of the most recent automation block the contact completed."},"lastdate":{"type":["string","null"],"example":"1984-08-15T08:13:44-05:00","description":"When something last happened to the contact in this run."},"completedElements":{"type":"integer","example":0,"description":"Number of automation blocks the contact has completed in this run."},"totalElements":{"type":"integer","example":0,"description":"Number of blocks in the automation."},"completed":{"type":"integer","example":0,"default":0,"description":"1 when the run has ended (status 2), otherwise 0."},"completeValue":{"type":"number","example":100,"default":0,"description":"Percentage of blocks completed, rounded to a whole number. 100 once the run has ended."},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/automation","description":"URL of the automation."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/contact","description":"URL of the contact."},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactAutomations/1/contactGoals","description":"URL of the goals the contact reached in this run."}},"description":"URLs of the records related to this run."},"id":{"type":"string","example":"1","description":"ID of the run. This is the contactAutomation id other resources refer to."},"automation":{"type":"string","example":"1","description":"ID of the automation, the same as seriesid."}}},"description":"The contact's automation runs. Present only with automations=true."},"contactLists":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"1","description":"Id of the contact."},"list":{"type":"string","example":"1","description":"Id of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form.","type":["string","null"]},"seriesid":{"type":"string","example":"0","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation."},"sdate":{"description":"When the contact was last subscribed to the list. Reset when a contact resubscribes.","type":["string","null"]},"udate":{"description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate.","type":["string","null"]},"status":{"type":"string","example":"1","description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","example":"1","description":"1 (the default) lets the list's later, scheduled autoresponders go to this contact; 0 stops them for this membership. The instant subscribe autoresponder does not check it."},"sync":{"type":"string","example":"0","description":"ID of the import or sync process that created the membership; 0 when it was not created by one."},"unsubreason":{"description":"The reason recorded with an unsubscribe. Null or empty when none was given.","type":["string","null"]},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise.","type":["string","null"]},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise.","type":["string","null"]},"first_name":{"type":"string","example":"John","description":"The contact's first name at the time of the request."},"last_name":{"type":"string","example":"Doe","description":"The contact's last name at the time of the request."},"ip4Sub":{"type":"string","example":"0","description":"The IP address recorded when the contact subscribed. 0 when there is none."},"sourceid":{"type":"string","example":"0","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise.","type":["string","null"]},"ip4_last":{"type":"string","example":"0","description":"The IP address recorded on the last subscription change. 0 when there is none."},"ip4Unsub":{"type":"string","example":"0","description":"The IP address recorded when the contact unsubscribed online. 0 when there is none."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise.","type":["string","null"]},"links":{"type":"object","properties":{"automation":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/automation","description":"URL of the automation that subscribed the contact."},"list":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/list","description":"URL of the list."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/contact","description":"URL of the contact."},"form":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/form","description":"URL of the form the subscription came from."},"autosyncLog":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/autosyncLog","description":"URL of the sync run that created the membership."},"campaign":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/campaign","description":"URL of the campaign the contact unsubscribed from."},"unsubscribeAutomation":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/unsubscribeAutomation","description":"URL of the automation that unsubscribed the contact."},"message":{"type":"string","example":"https://:account.api-us1.com/api/:version/contactLists/1/message","description":"URL of the message the contact unsubscribed from."}},"description":"URLs of the records related to this membership."},"id":{"type":"string","example":"1","description":"ID of the membership record."},"automation":{"description":"The automation that subscribed the contact, the same value as seriesid. Null when seriesid is 0.","type":["string","null"]}}},"description":"The contact's list memberships, one per list."},"deals":{"type":"array","items":{"type":"object","properties":{"owner":{"type":["string","null"],"example":"1","description":"Deal's owner id. Null when the deal has no owner."},"contact":{"type":"string","example":"1","description":"Deal's primary contact id. On this path it is always the contact in the URL."},"organization":{"description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount.","type":["string","null"]},"group":{"description":"Deal's pipeline id. Null when the deal has no pipeline.","type":["string","null"]},"title":{"type":"string","example":"Consectetur omnis quo inventore molestiae ratione amet.","description":"Deal's title."},"nexttaskid":{"type":["string","null"],"example":"0","description":"Id of the deal's next open task. Null (0 on older deals) when there is none."},"currency":{"type":"string","example":"usd","description":"Deal's currency in 3-digit ISO format, lowercased."},"status":{"type":"string","example":"0","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")."},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/dealActivities","description":"URL to list the deal's activities."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contact","description":"URL to the deal's primary contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contactDeals","description":"URL to list the links between the deal and its contacts."},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/group","description":"URL to the deal's pipeline."},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/nextTask","description":"URL to the deal's next open task."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/notes","description":"URL to list the deal's notes."},"account":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/account","description":"URL to the deal's account."},"customerAccount":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/customerAccount","description":"URL to the deal's account (same as account)."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/organization","description":"URL to the deal's account (same as account)."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/owner","description":"URL to the deal's owner."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/scoreValues","description":"URL to list the deal's score values."},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/stage","description":"URL to the deal's stage."},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/tasks","description":"URL to list the deal's tasks."},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/dealCustomFieldData","description":"URL to list the deal's custom field values."}},"description":"URLs of the deal's related resources."},"id":{"type":"string","example":"1","description":"Id of the deal."},"nextTask":{"description":"Id of the deal's next open task, as a relationship key. Same as nexttaskid when there is one; null on older deals whose nexttaskid is 0; absent when nexttaskid is null.","type":["string","null"]}}},"description":"The deals where the contact is the primary contact, at most 100. Users without permission to see all deals get only the deals they own. An empty array with exclude[]=deals."},"fieldValues":{"type":"array","items":{"$ref":"#/components/schemas/ContactFieldValue"},"description":"The contact's custom field values, one per field that has a value."},"geoAddresses":{"type":"array","items":{"type":"object","properties":{"ip4":{"type":"string","example":"823","description":"The first IPv4 address that resolved to this location, as an unsigned integer in text form. Other addresses that resolve to the same coordinates share this record, so this is not every address seen there."},"country2":{"type":"string","example":"AS","description":"Two-letter ISO 3166-1 country code. Empty when the lookup returned no country."},"country":{"type":"string","example":"Suriname","description":"Country name in English. Empty when the lookup returned no country."},"state":{"type":"string","example":"KY","description":"Name of the region, such as a state or province. Empty when the lookup returned none; older locations may hold the legacy region name."},"city":{"type":"string","example":"North Arnoldomouth","description":"City name. Empty when the lookup returned no city."},"zip":{"type":"string","example":"38704-6592","description":"Postal code. Empty when the lookup returned none."},"area":{"type":"string","example":"0","description":"Telephone area code. \"0\" for every location recorded since 2018, because the current lookup does not provide one; older locations may hold a real code."},"lat":{"type":"string","example":"-70.160407","description":"Latitude in decimal degrees, with six decimal places."},"lon":{"type":"string","example":"-102.229406","description":"Longitude in decimal degrees, with six decimal places."},"tz":{"type":"string","example":"Europe/Chisinau","description":"Time zone of the location as an IANA name. Empty when the lookup returned none."},"tstamp":{"type":["string","null"],"example":"1972-03-16T07:26:58-06:00","description":"When this location was first recorded."},"links":{"type":"array","description":"Always empty. A location has no related records to link to."},"id":{"type":"string","example":"1","description":"ID of the location."}}},"description":"The locations of the geoIps entries, one per location."},"geoIps":{"type":"array","items":{"type":"object","properties":{"contact":{"type":"string","example":"1","description":"ID of the contact."},"campaignid":{"type":"string","example":"1","description":"ID of the campaign the address was seen on; 0 when none is recorded."},"messageid":{"type":"string","example":"1","description":"ID of the message the address was seen on; 0 when none is recorded."},"geoaddrid":{"type":"string","example":"1","description":"ID of the location the address resolved to."},"ip4":{"type":"string","example":"0","description":"The IPv4 address as an unsigned integer, returned as a string."},"tstamp":{"type":["string","null"],"example":"1988-08-05T11:50:51-05:00","description":"When the address was recorded."},"geoAddress":{"type":["string","null"],"example":"1","description":"ID of the location the address resolved to, the same as geoaddrid. Null when geoaddrid is 0."},"links":{"type":"object","properties":{"geoAddress":{"type":"string","example":"https://:account.api-us1.com/api/:version/geoIps/1/geoAddress","description":"URL of the location the address resolved to."}},"description":"URLs of the records related to this entry."},"id":{"type":"string","example":"1","description":"ID of the entry."}}},"description":"The IP addresses the contact was seen from, one per campaign and location, at most 100."},"contact":{"description":"The contact record, plus the ids of the related records this read loads.","allOf":[{"$ref":"#/components/schemas/Contact"},{"type":"object","properties":{"contactAutomations":{"type":"array","description":"Ids of the automation runs linked to this contact. Present only when the request sends automations=true.","items":{"type":"string"}},"contactLists":{"type":"array","description":"Ids of the list memberships linked to this contact.","items":{"type":"string"}},"contactData":{"type":"string","description":"Id of the engagement data record linked to this contact. Present only when the contact has one."},"geoIps":{"type":"array","description":"Ids of the IP address records linked to this contact.","items":{"type":"string"}},"deals":{"type":"array","description":"Ids of the deals linked to this contact. Empty when the request sends exclude[]=deals.","items":{"type":"string"}},"accountContacts":{"type":"array","description":"Ids of the account links for this contact. Empty when the account does not have the Accounts feature.","items":{"type":"string"}},"fieldValues":{"type":"array","description":"Ids of the custom field values linked to this contact.","items":{"type":"string"}}}}]}}}}}},"404":{"description":"No contact with this id is visible to the user. Either the id does not exist, or the contact is only on lists the user's group cannot access; contacts on no list are visible to everyone. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\":\"No Result found for Subscriber with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 1","description":"Says which record was not found and its id."}}}}}}},"deprecated":false},"put":{"summary":"Update a contact","description":"Update an existing contact. Fields you leave out keep their current values. Custom field values in contact.fieldValues are saved in the same request; fields you leave out are not changed. The user needs the edit contacts permission. PATCH on this path behaves exactly like PUT: both methods run the same action, with the same body and responses.","operationId":"update-a-contact-new","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the contact to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["contact"],"properties":{"contact":{"description":"The fields to change.","$ref":"#/components/schemas/ContactWrite"},"useDefaults":{"type":"boolean"}}},"examples":{"Request Example":{"value":{"contact":{"email":"johndoe@example.com","firstName":"John","lastName":"Doe","fieldValues":[{"field":"1","value":"The Value for First Field"},{"field":"6","value":"2008-01-20"}]}}}}}}},"responses":{"200":{"description":"The contact was updated. The body has the contact under contact and its custom field values under fieldValues.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"113\",\n            \"field\": \"1\",\n            \"value\": \"The Value for First Field\",\n            \"cdate\": \"2020-08-01T10:54:59-05:00\",\n            \"udate\": \"2020-08-01T14:13:34-05:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/11797/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/11797/field\"\n            },\n            \"id\": \"11797\",\n            \"owner\": \"113\"\n        },\n        {\n            \"contact\": \"113\",\n            \"field\": \"6\",\n            \"value\": \"2008-01-20\",\n            \"cdate\": \"2020-08-01T10:54:59-05:00\",\n            \"udate\": \"2020-08-01T14:13:34-05:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/11798/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/11798/field\"\n            },\n            \"id\": \"11798\",\n            \"owner\": \"113\"\n        }\n    ],\n    \"contact\": {\n        \"cdate\": \"2018-09-28T13:50:41-05:00\",\n        \"email\": \"johndoe@example.com\",\n        \"phone\": \"\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"orgid\": \"0\",\n        \"segmentio_id\": \"\",\n        \"bounced_hard\": \"0\",\n        \"bounced_soft\": \"0\",\n        \"bounced_date\": null,\n        \"ip\": \"0\",\n        \"ua\": null,\n        \"hash\": \"8309146b50af1ed5f9cb40c7465a0315\",\n        \"socialdata_lastcheck\": null,\n        \"email_local\": \"\",\n        \"email_domain\": \"\",\n        \"sentcnt\": \"0\",\n        \"rating_tstamp\": null,\n        \"gravatar\": \"0\",\n        \"deleted\": \"0\",\n        \"anonymized\": \"0\",\n        \"adate\": null,\n        \"udate\": \"2018-09-28T13:55:59-05:00\",\n        \"edate\": null,\n        \"deleted_at\": null,\n        \"created_utc_timestamp\": \"2018-09-28 13:50:41\",\n        \"updated_utc_timestamp\": \"2018-09-28 13:50:41\",\n        \"links\": {\n            \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/bounceLogs\",\n            \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/113/contactAutomations\",\n            \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/113/contactData\",\n            \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/113/contactGoals\",\n            \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/113/contactLists\",\n            \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/contactLogs\",\n            \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/113/contactTags\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/113/contactDeals\",\n            \"deals\": \"https://:account.api-us1.com/api/:version/contacts/113/deals\",\n            \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/113/fieldValues\",\n            \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/113/geoIps\",\n            \"notes\": \"https://:account.api-us1.com/api/:version/contacts/113/notes\",\n            \"organization\": \"https://:account.api-us1.com/api/:version/contacts/113/organization\",\n            \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/113/plusAppend\",\n            \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/113/trackingLogs\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/113/scoreValues\"\n        },\n        \"id\": \"113\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","items":{"$ref":"#/components/schemas/ContactFieldValue"},"description":"All of the contact's custom field values, read again after the save. Present only when the request sent fieldValues or the older fields list."},"contact":{"description":"The contact after the update: the stored record with the values sent applied. It is not read back after the save. Values the database changes during the save show their earlier value, such as hash and email_domain after an email change. Custom field, tag and list changes in the same request are saved after the contact, so the stored udate can be later than the one returned.","allOf":[{"$ref":"#/components/schemas/Contact"}]}}}}}},"400":{"description":"The contact was not changed: a list in contact.lists or contact.form is an email list and the contact has no email address, or an SMS list and the contact has no phone number. Tags and an account named in the request may already have been created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteForbidden"},"example":{"errors":[{"status":"400","detail":"You cannot subscribe a contact without an email address to an email list"}]}}}},"403":{"description":"Nothing was saved. The user does not have the edit contacts permission (detail \"Forbidden\"). A refused account link also returns 403; see contact.account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteForbidden"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"Nothing was saved. Either no contact has this id (message \"No Result found for Subscriber with id\" followed by the id), or orgid or organization names an account id that does not exist (message \"No Result found for CustomerAccount with id\" followed by that id). Tags and an account named in the request may already have been created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 1","description":"Says which record was not found and its id."}}}}}},"409":{"description":"The contact was not changed: another contact already has this whatsapp_id. Tags and an account named in the request may already have been created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteConflict"},"example":{"errors":[{"status":409,"title":"Conflict","detail":"A contact with this whatsapp_id already exists"}]}}}},"422":{"description":"Validation failed and the contact was not changed. An account or tags named in the request may already have been created; see contact.account and contact.tags. Changing the email address to one another contact already has gives code \"duplicate\" and title \"Email address already exists in the system.\". Other validation failures also return 422. A whatsapp_id that needs phone-only contacts uses this body too. The errors described on contact.tags, contact.lists, contact.form and contact.ip4 use the second body shape; see the schema. Refusing to resubscribe a contact who unsubscribed from a list returns the plain text \"Unsubscribed contact cannot be re-subscribed through API.\" instead of JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteValidationError"}}}}},"deprecated":false},"delete":{"summary":"Delete a contact","description":"Deletes one contact. The contact is removed from all of its lists and its tags are removed, and its email address is anonymized in the unsubscribe log and other related records. Its account link and its secondary-contact deal links are deleted. Each deal on which it is the primary contact moves to the deal's first secondary contact; a deal with no secondary contact but an account stays on that account with no contact; any other such deal is deleted, with its tasks. A copy of the contact record is kept in the contact archive for 360 days, where it can be restored once it is old enough; Admin users can see archived contacts with GET /contactArchives. The user needs permission to delete contacts, and the account's delete allowance for the current billing period must not be used up. The contact is found by id alone, so a contact on lists the user cannot access can still be deleted. To delete several contacts in one call, use DELETE /contacts/bulk_delete.","operationId":"delete-contact","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The contact id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The body is a plain sentence, not JSON, even though the response is labeled application/json. \"You do not have permission to delete contacts.\" means the user may not delete contacts, and \"You cannot delete any more contacts in this billing period.\" means the account's delete allowance is used up; in both cases nothing was deleted. \"Failed to delete contact\" means the delete stopped partway: depending on where it stopped, the contact may already be marked deleted, removed from its lists and tags, anonymized, or have its deals moved or deleted, without being archived.","content":{"application/json":{"schema":{"type":"string","description":"The message, as plain text.","example":"You do not have permission to delete contacts."}}}},"404":{"description":"No contact has this id. Nothing was deleted. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\":\"No Result found for Subscriber with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 1","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/accountContacts":{"get":{"summary":"Retrieve a contacts account contacts","description":"The link between this contact and its account (company): the account id, the contact's job title there, and when the link was created and last changed. A contact can be on one account at a time, so the list normally holds at most one row and is empty when the contact has no account. Everything comes back in one response: limit, offset, filters and orders are ignored on this path. To find links across contacts, use GET /accountContacts with filters[contact] or filters[account]. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-account-contacts","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's account links under accountContacts: at most one in normal use, or an empty list when the contact is on no account.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"accountContacts\": [\n        {\n            \"account\": \"9\",\n            \"contact\": \"7\",\n            \"jobTitle\": \"\",\n            \"createdTimestamp\": \"2021-05-21T16:30:23-05:00\",\n            \"updatedTimestamp\": \"2021-05-21T16:30:23-05:00\",\n            \"links\": {\n                \"account\": \"https://:account.api-us1.com/api/3/accountContacts/7/account\",\n                \"contact\": \"https://:account.api-us1.com/api/3/accountContacts/7/contact\"\n            },\n            \"id\": \"7\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"accountContacts":{"type":"array","items":{"type":"object","properties":{"account":{"type":"string","example":"9","description":"Id of the account (company) the contact is linked to. Use it with GET /accounts/{id}."},"contact":{"type":"string","example":"7","description":"Id of the contact. On this path it is always the contact in the URL."},"jobTitle":{"type":["string","null"],"example":"","description":"Job Title of the contact at the account. Null or empty when none was given."},"createdTimestamp":{"type":"string","example":"2021-05-21T16:30:23-05:00","description":"When the link was created."},"updatedTimestamp":{"type":"string","example":"2021-05-21T16:30:23-05:00","description":"When the link was last changed."},"links":{"type":"object","properties":{"account":{"type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/7/account","description":"URL to the linked account."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/accountContacts/7/contact","description":"URL to the contact."}},"description":"URLs of the link's related resources."},"id":{"type":"string","example":"7","description":"Id of the account-contact link. Use it with GET /accountContacts/{id}."}}},"description":"The contact's account links, normally at most one."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/automationEntryCounts":{"get":{"summary":"Retrieve a contacts automation entry counts","description":"For each automation this contact has entered, the number of times they entered it. Hidden automations (the ones the app creates to add form submitters to a list) are left out. Rows are ordered by automation id. Everything comes back in one response with no links or meta: limit and offset are ignored. Only GET is allowed. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-automation-entry-counts","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"One entry per automation the contact has entered, under automationEntryCounts; an empty list when there are none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"automationEntryCounts\": [\n        {\n            \"id\": \"2\",\n            \"name\": \"Pages: Lead Delivery\",\n            \"status\": \"1\",\n            \"hidden\": \"0\",\n            \"contactEntryCount\": \"1\"\n        },\n        {\n            \"id\": \"4\",\n            \"name\": \"Lead Scoring\",\n            \"status\": \"1\",\n            \"hidden\": \"0\",\n            \"contactEntryCount\": \"2\"\n        },\n        {\n            \"id\": \"7\",\n            \"name\": \"Foo: Bar Creation\",\n            \"status\": \"1\",\n            \"hidden\": \"0\",\n            \"contactEntryCount\": \"1\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"automationEntryCounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"2","description":"Id of the automation."},"name":{"type":"string","example":"Pages: Lead Delivery","description":"Name of the automation."},"status":{"type":"string","example":"1","description":"Automation status: 0 draft, 1 active, 2 inactive, 3 paused."},"hidden":{"type":"string","example":"0","description":"Whether the automation is hidden. Always 0 here, because hidden automations are left out."},"contactEntryCount":{"type":"string","example":"1","description":"Number of times this contact has entered the automation. Runs that finished or were ended still count; a run deleted through DELETE /contactAutomations/{id} no longer counts."}}},"description":"One row per automation the contact has entered."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/bounceLogs":{"get":{"summary":"Retrieve a contact's bounce logs","description":"The bounce log entries recorded for this contact, one per bounced message with its timestamp, bounce code and campaign. For every bounce log on the account, use GET /bounceLogs. Neither endpoint filters by a date range, so a bounce count for a period is not available in one request. Every entry comes back in one response: limit and offset are ignored on this path.","operationId":"retrieve-contact-bounce-logs","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's bounce log entries under bounceLogs; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"bounceLogs\": [\n        {\n            \"email\": \"uhOhBounced@example.com\",\n            \"subscriberid\": \"4\",\n            \"listid\": \"3\",\n            \"campaignid\": \"11\",\n            \"messageid\": \"12\",\n            \"tstamp\": \"2021-05-12T00:00:00-05:00\",\n            \"type\": \"hard\",\n            \"code\": \"5.1.1\",\n            \"counted\": \"1\",\n            \"source\": \"550 5.1.1 The email account that you tried to reach does not exist.\",\n            \"created_timestamp\": \"2021-05-12 11:30:06\",\n            \"updated_timestamp\": \"2021-05-12 11:30:06\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"email_source\": \"0\",\n            \"links\": {\n                \"contact\": \"https://:account.api-us1.com/api/3/bounceLogs/23/contact\",\n                \"campaign\": \"https://:account.api-us1.com/api/3/bounceLogs/23/campaign\",\n                \"message\": \"https://:account.api-us1.com/api/3/bounceLogs/23/message\"\n            },\n            \"id\": \"23\",\n            \"contact\": \"4\",\n            \"campaign\": \"11\",\n            \"message\": \"12\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"bounceLogs":{"type":"array","description":"One entry per bounced message for the contact.","items":{"type":"object","properties":{"tstamp":{"type":["string","null"],"description":"Date of the bounce. Only the day is stored, so the time part is always midnight.","example":"2021-05-12T00:00:00-05:00"},"subscriberid":{"type":"string","description":"ID of the contact.","example":"4"},"listid":{"type":"string","description":"ID of the list the message was sent to; 0 when none is recorded.","example":"3"},"campaignid":{"type":"string","description":"ID of the campaign the message belonged to; 0 when none is recorded.","example":"11"},"messageid":{"type":"string","description":"ID of the message that bounced; 0 when none is recorded.","example":"12"},"type":{"type":"string","description":"Kind of bounce: hard or soft.","example":"hard"},"counted":{"type":"string","description":"Whether the bounce counts toward the contact's bounce total. Nothing in the product sets it to 0, so it is always 1.","example":"1"},"email":{"type":"string","description":"The email address that bounced.","example":"uhOhBounced@example.com"},"source":{"type":["string","null"],"description":"The reason for the bounce, as reported by the receiving mail server. Null when none was recorded.","example":"550 5.1.1 The email account that you tried to reach does not exist."},"created_timestamp":{"type":"string","description":"When the entry was created, account local time.","example":"2021-05-12 11:30:06"},"updated_timestamp":{"type":"string","description":"When the entry was last changed, account local time.","example":"2021-05-12 11:30:06"},"created_by":{"description":"ID of the account user who created the entry; null when the system recorded it."},"updated_by":{"description":"ID of the account user who last changed the entry; null when the last change was not made by a user."},"email_source":{"type":"string","description":"Where the bounced email was sent from: 0 a campaign or automation email, 1 a one-to-one email.","example":"0"},"links":{"type":"object","description":"URLs of the records related to this entry.","properties":{"contact":{"type":"string","description":"URL of the contact.","example":"https://:account.api-us1.com/api/3/bounceLogs/23/contact"},"campaign":{"type":"string","description":"URL of the campaign.","example":"https://:account.api-us1.com/api/3/bounceLogs/23/campaign"},"message":{"type":"string","description":"URL of the message.","example":"https://:account.api-us1.com/api/3/bounceLogs/23/message"}}},"id":{"type":"string","description":"ID of the bounce log entry.","example":"23"},"contact":{"type":"string","description":"ID of the contact, the same as subscriberid.","example":"4"},"campaign":{"type":["string","null"],"description":"ID of the campaign, the same as campaignid. Null when campaignid is 0.","example":"11"},"message":{"type":["string","null"],"description":"ID of the message, the same as messageid. Null when messageid is 0.","example":"12"},"code":{"type":["string","null"],"description":"The bounce code matched for the bounce, for example 5.1.1. Null when none was matched.","example":"5.1.1"}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 100"}}}}}}},"deprecated":false}},"/contacts/{id}/contactAutomations":{"get":{"summary":"List all automations the contact is in","description":"The automation runs this contact has been in, one entry per time the contact entered an automation. status 1 means the contact is still moving through the automation; 2 means the run has ended. adddate is when the contact entered and remdate when the run ended. By default every run comes back in one response. Pass limit to page; offset then applies and defaults to 0. Without limit, offset is ignored. orders[lastdate]=ASC or DESC sorts by the last activity in the run; any other direction is rejected with 422. Returns 404 if the contact does not exist. To list runs across contacts, use GET /contactAutomations. The contactAutomations link on a contact sends limit=2500 and orders[lastdate]=DESC.","operationId":"list-all-contactautomations-for-contact","x-canonical-resource":"contactAutomations","parameters":[{"name":"id","in":"path","description":"ID of the contact to receive automations for","schema":{"type":"integer","format":"int32"},"required":true},{"name":"orders[lastdate]","in":"query","description":"Order the rows by lastdate, the most recent time something happened to the contact in that automation. Use asc or desc in any letter case (asc, ASC, desc, DESC, Desc are all accepted; the value is upper-cased before it is checked); any other value is rejected with a 422 error. Without it the order is not guaranteed.","schema":{"type":"string","pattern":"^(?:[aA][sS][cC]|[dD][eE][sS][cC])$"},"example":"DESC"}],"responses":{"200":{"description":"The contact's automation runs under contactAutomations; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactAutomations\": [\n        {\n            \"contact\": \"6\",\n            \"seriesid\": \"2\",\n            \"startid\": \"0\",\n            \"status\": \"2\",\n            \"batchid\": \"completed\",\n            \"adddate\": \"2022-03-01T08:51:57-06:00\",\n            \"remdate\": \"2022-03-01T08:51:58-06:00\",\n            \"timespan\": \"1\",\n            \"lastblock\": \"5\",\n            \"lastlogid\": \"0\",\n            \"lastdate\": \"2022-03-01T08:51:58-06:00\",\n            \"in_als\": \"3\",\n            \"completedElements\": 0,\n            \"totalElements\": 3,\n            \"completed\": 1,\n            \"completeValue\": 100,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/3/contactAutomations/6/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactAutomations/6/contact\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/contactAutomations/6/contactGoals\",\n                \"automationLogs\": \"https://:account.api-us1.com/api/3/contactAutomations/6/automationLogs\",\n                \"subscriberSeriesEnd\": \"https://:account.api-us1.com/api/3/contactAutomations/6/subscriberSeriesEnd\"\n            },\n            \"id\": \"6\",\n            \"automation\": \"2\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contactAutomations":{"type":"array","description":"One entry per automation run of the contact.","items":{"type":"object","properties":{"contact":{"type":"string","description":"ID of the contact.","example":"6"},"seriesid":{"type":"string","description":"ID of the automation.","example":"2"},"startid":{"type":"string","description":"ID of the start trigger that began this run.","example":"0"},"status":{"type":"string","description":"Where the run stands: 1 the contact is still moving through the automation, 2 the run has ended.","example":"2"},"batchid":{"type":["string","null"],"description":"Processing state of the run, or the id of the batch currently processing it. completed once the run has ended; queued, scheduled, paused or error while it is being handled; null while the contact waits at a block.","example":"completed"},"adddate":{"type":["string","null"],"description":"When the contact entered the automation.","example":"2022-03-01T08:51:57-06:00"},"remdate":{"type":["string","null"],"description":"When the run ended. Null while it is still running or waiting.","example":"2022-03-01T08:51:58-06:00"},"timespan":{"type":["string","null"],"description":"Seconds between adddate and remdate. Null while the run has not ended.","example":"1"},"lastblock":{"type":"string","description":"ID of the most recent automation block the contact completed.","example":"5"},"lastlogid":{"type":"string","description":"ID of the most recent log entry for this run.","example":"0"},"lastdate":{"type":["string","null"],"description":"When something last happened to the contact in this run.","example":"2022-03-01T08:51:58-06:00"},"in_als":{"type":["string","null"],"description":"Internal flag for where the run's log history is stored. 3 means it is in the automation log service.","example":"3"},"completedElements":{"type":"integer","description":"Number of automation blocks the contact has completed in this run.","example":0,"default":0},"totalElements":{"type":"integer","description":"Number of blocks in the automation.","example":3,"default":0},"completed":{"type":"integer","description":"1 when the run has ended (status 2), otherwise 0.","example":1,"default":0},"completeValue":{"type":"number","description":"Percentage of blocks completed, rounded to a whole number. 100 once the run has ended.","example":100,"default":0},"links":{"type":"object","description":"URLs of the records related to this run.","properties":{"automation":{"type":"string","description":"URL of the automation.","example":"https://:account.api-us1.com/api/3/contactAutomations/6/automation"},"contact":{"type":"string","description":"URL of the contact.","example":"https://:account.api-us1.com/api/3/contactAutomations/6/contact"},"contactGoals":{"type":"string","description":"URL of the goals the contact reached in this run.","example":"https://:account.api-us1.com/api/3/contactAutomations/6/contactGoals"},"automationLogs":{"type":"string","description":"URL of the log entries for this run.","example":"https://:account.api-us1.com/api/3/contactAutomations/6/automationLogs"},"subscriberSeriesEnd":{"type":"string","description":"URL of the record of how this run ended.","example":"https://:account.api-us1.com/api/3/contactAutomations/6/subscriberSeriesEnd"}}},"id":{"type":"string","description":"ID of the run. This is the contactAutomation id other resources refer to.","example":"6"},"automation":{"type":"string","description":"ID of the automation, the same as seriesid.","example":"2"}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 1"}}}}}},"422":{"description":"orders[lastdate] is neither asc nor desc","content":{"application/json":{"examples":{"Result":{"value":"{\"errors\":[{\"status\":\"422\",\"detail\":\"Invalid ordering direction: SIDEWAYS.\"}]}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry saying why the request was rejected. Each entry has only status and detail. There is no title, unlike the 400 and 404 bodies of the tag endpoints in this file: this error is built by the Symfony exception listener, not by the library's error formatter.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status as the string \"422\". The 400 and 404 bodies elsewhere in this file carry status as a number; here it is a string.","example":"422"},"detail":{"type":"string","description":"Why the request was rejected: the words Invalid ordering direction: followed by the value sent, upper-cased, and a full stop.","example":"Invalid ordering direction: SIDEWAYS."}}}}}}}}}},"deprecated":false}},"/contacts/{id}/contactData":{"get":{"summary":"Retrieve a contact's data","description":"The contact's data record: one row of extra information the application keeps about the contact, mostly where the contact appears to be located. The location fields (geoIp4, geoCountry2, geo_country, geoState, geoCity, geoZip, geoLat, geoLon, geoTz, geoTzOffset, geoTstamp) are filled by a MaxMind GeoIP lookup of an IP address recorded for the contact, for example when the contact subscribes, opens or clicks a tracked email, or is added through the v1 API with an ip4 value; contact enrichment can also fill the city, state, country, country code and zip when they are blank, and sets geoTstamp when it does. The ga_campaign_*, ga_first_visit, ga_times_visited, fb_id, fb_name and tw_id fields are legacy columns that the application no longer writes. A contact has at most one data record, so the response is a single contactDatum object, not a list: limit, offset, filters and orders are ignored on this path. The record is created on demand (for example the first time a location is stored, or when the contact is personalized for a send), so a contact that has none yet returns an empty object ({}) with status 200. Values come back as strings; tstamp, geoTstamp and ga_first_visit are ISO 8601 dates or null. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-data","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's data record under contactDatum, or an empty object ({}) when the contact has none yet.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactDatum\": {\n        \"contact\": \"4\",\n        \"tstamp\": \"2021-06-09T14:35:10-05:00\",\n        \"geoTstamp\": null,\n        \"geoIp4\": \"0\",\n        \"geoCountry2\": \"\",\n        \"geo_country\": \"\",\n        \"geoState\": \"\",\n        \"geoCity\": \"\",\n        \"geoZip\": \"\",\n        \"geoArea\": \"0\",\n        \"geoLat\": \"0.000000\",\n        \"geoLon\": \"0.000000\",\n        \"geoTz\": \"\",\n        \"geoTzOffset\": \"0.00\",\n        \"ga_campaign_source\": \"\",\n        \"ga_campaign_name\": \"\",\n        \"ga_campaign_medium\": \"\",\n        \"ga_campaign_term\": \"\",\n        \"ga_campaign_content\": \"\",\n        \"ga_campaign_customsegment\": \"\",\n        \"ga_first_visit\": null,\n        \"ga_times_visited\": \"0\",\n        \"fb_id\": \"0\",\n        \"fb_name\": \"\",\n        \"tw_id\": \"0\",\n        \"created_timestamp\": \"0000-00-00 00:00:00\",\n        \"updated_timestamp\": \"0000-00-00 00:00:00\",\n        \"created_by\": \"0\",\n        \"updated_by\": \"0\",\n        \"links\": [],\n        \"id\": \"12\"\n    }\n}"}},"schema":{"type":"object","properties":{"contactDatum":{"type":"object","properties":{"contact":{"type":"string","example":"4","description":"Id of the contact this record belongs to."},"tstamp":{"type":["string","null"],"example":"2021-06-09T14:35:10-05:00","description":"When this record was first created. ISO 8601 with a UTC offset, or null."},"geoTstamp":{"type":["string","null"],"description":"When the location fields were last updated. ISO 8601 with a UTC offset. Null if no location has been stored."},"geoIp4":{"type":["string","null"],"example":"0","description":"The IP address the location was worked out from, stored as a single number rather than dotted form. 0 or null when there is none."},"geoCountry2":{"type":["string","null"],"example":"","description":"Two-letter ISO country code from the location lookup. Empty or null when unknown."},"geo_country":{"type":"string","example":"","description":"Country name from the location lookup. Empty when unknown. This field keeps its snake_case name; there is no geoCountry."},"geoState":{"type":"string","example":"","description":"State, province or region name from the location lookup. Empty when unknown."},"geoCity":{"type":"string","example":"","description":"City name from the location lookup. Empty when unknown."},"geoZip":{"type":"string","example":"","description":"Postal code from the location lookup. Empty when unknown."},"geoArea":{"type":["string","null"],"example":"0","description":"Telephone area code. 0 or null; the location lookup no longer supplies one."},"geoLat":{"type":"string","example":"0.000000","description":"Latitude from the location lookup, to six decimal places. 0.000000 when unknown."},"geoLon":{"type":"string","example":"0.000000","description":"Longitude from the location lookup, to six decimal places. 0.000000 when unknown."},"geoTz":{"type":"string","example":"","description":"Time zone name for the location, such as America/Chicago. Used to run automation waits in the contact's local time. Empty when unknown."},"geoTzOffset":{"type":"string","example":"0.00","description":"Difference in hours between geoTz and the time zone the database server runs in. Normally 0.00 when geoTz is empty."},"ga_campaign_source":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_name":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_medium":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_term":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_content":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_campaign_customsegment":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"ga_first_visit":{"type":["string","null"],"description":"Legacy field. Nothing writes it today; expect null."},"ga_times_visited":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"fb_id":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"fb_name":{"type":"string","example":"","description":"Legacy field. Nothing writes it today; expect an empty string."},"tw_id":{"type":"string","example":"0","description":"Legacy field. Nothing writes it today; expect 0."},"created_timestamp":{"type":"string","example":"0000-00-00 00:00:00","description":"When the database row was created, as a plain date-time string (not ISO 8601). May be 0000-00-00 00:00:00 on older rows."},"updated_timestamp":{"type":"string","example":"0000-00-00 00:00:00","description":"When the database row was last changed, as a plain date-time string (not ISO 8601). May be 0000-00-00 00:00:00 on older rows."},"created_by":{"type":["string","null"],"example":"0","description":"Id of the account user who created the row, when one was recorded. Usually 0 or null."},"updated_by":{"type":["string","null"],"example":"0","description":"Id of the account user who last changed the row, when one was recorded. Usually 0 or null."},"links":{"type":"array","description":"Always an empty list. This record has no related resources of its own."},"id":{"type":"string","example":"12","description":"Id of this data record. Not the contact id; use contact for that."}},"description":"The contact's data record. Absent, and the whole body an empty object, when the contact has none yet."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 121\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 121","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/contactDeals":{"get":{"summary":"Retrieve a list of contact's deals","description":"The deals this contact is on as a secondary contact, as contact-to-deal links. Each link carries the deal id (deal), the contact id (contact), the contact's role on the deal (role, null when none) and when the link was made (cdate). Deals where this contact is the primary contact are not listed here; GET /contacts/{id}/deals returns those. Every link comes back in one response: limit and offset are ignored on this path, and no order is guaranteed. The linked deals are sideloaded in deals and their primary contacts in contacts. A user without the permission to list all deals sees only links to deals they own. Returns 404 if the contact does not exist. For deal links across contacts, or to page through them, use GET /contactDeals with filters[deal] and filters[contact].","operationId":"retrieve-contact-deals-list","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's secondary-contact deal links under contactDeals, with the linked deals under deals and their primary contacts under contacts.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2021-11-28T00:00:00-06:00\",\n            \"email\": \"john.doe@example.com\",\n            \"phone\": \"555-555-5555\",\n            \"firstName\": \"John\",\n            \"lastName\": \"Doe\",\n            \"orgid\": \"XX\",\n            \"orgname\": \"Opulence Time\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": \"0000-00-00\",\n            \"ip\": \"0\",\n            \"ua\": \"\",\n            \"hash\": \"43fa9ikvd23cbc59915f89asd234gsda27b33\",\n            \"socialdata_lastcheck\": \"0000-00-00 00:00:00\",\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": \"0000-00-00\",\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": \"2021-11-28T00:00:00-06:00\",\n            \"udate\": \"2021-11-28T00:00:00-06:00\",\n            \"edate\": \"2021-12-20T06:23:31-06:00\",\n            \"deleted_at\": \"0000-00-00 00:00:00\",\n            \"created_utc_timestamp\": \"2021-11-28 00:00:00\",\n            \"updated_utc_timestamp\": \"2022-01-25 16:26:37\",\n            \"created_timestamp\": \"2021-11-28 00:00:00\",\n            \"updated_timestamp\": \"2021-12-09 00:00:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"email_empty\": false,\n            \"mpp_tracking\": \"0\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/1107/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/1107/contactAutomations?limit=1000&orders%5Blastdate%5D=DESC\",\n                \"contactData\": \"https://:account.api-us1.com/api/3/contacts/1107/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/1107/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/1107/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/1107/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/1107/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/1107/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/3/contacts/1107/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/1107/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/1107/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/3/contacts/1107/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/3/contacts/1107/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/1107/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/1107/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/1107/scoreValues\",\n                \"accountContacts\": \"https://:account.api-us1.com/api/3/contacts/1107/accountContacts\",\n                \"automationEntryCounts\": \"https://:account.api-us1.com/api/3/contacts/1107/automationEntryCounts\"\n            },\n            \"id\": \"XXXX\",\n            \"organization\": \"XX\"\n        }\n    ],\n    \"deals\": [\n        {\n            \"hash\": \"dx60eh125\",\n            \"owner\": \"8\",\n            \"contact\": \"XXXX\",\n            \"organization\": \"31\",\n            \"group\": \"1\",\n            \"stage\": \"1\",\n            \"title\": \"Opulence Time\",\n            \"description\": \"\",\n            \"percent\": \"0\",\n            \"cdate\": \"2022-01-24T00:00:00-06:00\",\n            \"mdate\": \"2022-01-25T00:00:00-06:00\",\n            \"nextdate\": null,\n            \"nexttaskid\": \"0\",\n            \"value\": \"7320163\",\n            \"currency\": \"usd\",\n            \"winProbability\": null,\n            \"winProbabilityMdate\": null,\n            \"status\": \"0\",\n            \"activitycount\": \"24\",\n            \"nextdealid\": \"4218\",\n            \"edate\": \"2022-03-07 00:00:00\",\n            \"links\": {\n                \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/4228/dealActivities\",\n                \"contact\": \"https://:account.api-us1.com/api/3/deals/4228/contact\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/4228/contactDeals\",\n                \"group\": \"https://:account.api-us1.com/api/3/deals/4228/group\",\n                \"nextTask\": \"https://:account.api-us1.com/api/3/deals/4228/nextTask\",\n                \"notes\": \"https://:account.api-us1.com/api/3/deals/4228/notes\",\n                \"account\": \"https://:account.api-us1.com/api/3/deals/4228/account\",\n                \"customerAccount\": \"https://:account.api-us1.com/api/3/deals/4228/customerAccount\",\n                \"organization\": \"https://:account.api-us1.com/api/3/deals/4228/organization\",\n                \"owner\": \"https://:account.api-us1.com/api/3/deals/4228/owner\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/4228/scoreValues\",\n                \"stage\": \"https://:account.api-us1.com/api/3/deals/4228/stage\",\n                \"tasks\": \"https://:account.api-us1.com/api/3/deals/4228/tasks\",\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/4228/dealCustomFieldData\"\n            },\n            \"id\": \"4228\",\n            \"isDisabled\": false,\n            \"nextTask\": null,\n            \"account\": \"31\",\n            \"customerAccount\": \"31\"\n        }\n    ],\n    \"contactDeals\": [\n        {\n            \"deal\": \"4228\",\n            \"contact\": \"5\",\n            \"role\": null,\n            \"cdate\": \"2021-10-22T13:16:27-05:00\",\n            \"created_timestamp\": \"2021-10-22 13:16:27\",\n            \"updated_timestamp\": \"2021-10-22 13:16:27\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/3/contactDeals/4248/deal\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactDeals/4248/contact\",\n                \"role\": \"https://:account.api-us1.com/api/3/contactDeals/4248/role\"\n            },\n            \"id\": \"4248\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","description":"The primary contact of each linked deal, as a full contact record with the same fields as GET /contacts/{id}. These are the deals' primary contacts, not the contact in the path. Deals with no primary contact add nothing here.","items":{"$ref":"#/components/schemas/Contact"}},"deals":{"type":"array","description":"The deal behind each link, as a full deal record with the same fields as GET /deals/{id}.","items":{"type":"object","properties":{"hash":{"type":"string","example":"dx60eh125","description":"Random eight-character code given to the deal when it was created."},"owner":{"type":["string","null"],"example":"8","description":"Deal's owner id. Null when the deal has no owner."},"contact":{"type":["string","null"],"example":"XXXX","description":"Deal's primary contact id. Null when the deal has an account and no primary contact."},"organization":{"type":["string","null"],"example":"31","description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount."},"group":{"type":"string","example":"1","description":"Deal's pipeline id."},"stage":{"type":"string","example":"1","description":"Deal's stage id."},"title":{"type":"string","example":"Opulence Time","description":"Deal's title."},"description":{"type":"string","example":"","description":"Deal's description. Empty when none."},"percent":{"type":"string","example":"0","description":"Deal's percentage."},"cdate":{"type":"string","example":"2022-01-24T00:00:00-06:00","description":"When the deal was created."},"mdate":{"type":"string","example":"2022-01-25T00:00:00-06:00","description":"When the deal was last changed, including when an activity was added to it."},"nextdate":{"description":"Due date of the deal's next open task. Null when there is none.","type":["string","null"]},"nexttaskid":{"type":["string","null"],"example":"0","description":"Id of the deal's next open task. Null (0 on older deals) when there is none."},"value":{"type":"string","example":"7320163","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero."},"currency":{"type":"string","example":"usd","description":"Deal's currency in 3-digit ISO format, lowercased."},"winProbability":{"description":"Predicted chance of winning the deal, as a whole percentage rounded up. Returned as a number, not a string. Null when the account does not have win probability or it has not been calculated yet.","type":["number","null"]},"winProbabilityMdate":{"description":"When winProbability was last updated. Null when it has never been calculated or the account does not have win probability.","type":["string","null"]},"status":{"type":"string","example":"0","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")."},"activitycount":{"type":"string","example":"24","description":"Number of activities recorded on the deal."},"nextdealid":{"type":"string","example":"4218","description":"Internal pointer used to order the pipeline's open deals: the id of the deal that follows this one. 0 when there is none."},"edate":{"type":["string","null"],"example":"2022-03-07 00:00:00","description":"When email activity was last gathered for the deal. Null when it never was. Returned as YYYY-MM-DD HH:MM:SS, not in ISO 8601 format."},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/dealActivities","description":"URL to list the deal's activities."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/contact","description":"URL to the deal's primary contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/contactDeals","description":"URL to list the links between the deal and its contacts."},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/group","description":"URL to the deal's pipeline."},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/nextTask","description":"URL to the deal's next open task."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/notes","description":"URL to list the deal's notes."},"account":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/account","description":"URL to the deal's account."},"customerAccount":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/customerAccount","description":"URL to the deal's account (same as account)."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/organization","description":"URL to the deal's account (same as account)."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/owner","description":"URL to the deal's owner."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/scoreValues","description":"URL to list the deal's score values."},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/stage","description":"URL to the deal's stage."},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/tasks","description":"URL to list the deal's tasks."},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/4228/dealCustomFieldData","description":"URL to list the deal's custom field values."}},"description":"URLs of the deal's related resources."},"id":{"type":"string","example":"4228","description":"Id of the deal."},"isDisabled":{"type":"boolean","example":false,"default":true,"description":"True when the deal is in a pipeline the current user cannot see. Such a deal comes back with only id, title, status and isDisabled."},"nextTask":{"description":"Id of the deal's next open task, as a relationship key. Same as nexttaskid when there is one; null on older deals whose nexttaskid is 0; absent when nexttaskid is null.","type":["string","null"]},"account":{"type":["string","null"],"example":"31","description":"Deal's account id. Null when the deal has no account. Same value as customerAccount and organization."},"customerAccount":{"type":["string","null"],"example":"31","description":"Deal's account id, under another name. Null when the deal has no account. Same value as account and organization."}}}},"contactDeals":{"type":"array","description":"The contact's links to deals, one per deal the contact is a secondary contact on.","items":{"$ref":"#/components/schemas/ContactDeal"}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/contactGoals":{"get":{"summary":"Retrieve a contact's goals","description":"The automation goals this contact has reached, one entry per goal reached in one automation run. goal is the goal id, automation the automation id, and contactAutomation the id of the run (an entry of GET /contacts/{id}/contactAutomations). Every entry comes back in one response: limit and offset are ignored on this path. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-goals","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The goals the contact has reached under contactGoals; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactGoals\": [\n        {\n            \"goalid\": \"3\",\n            \"seriesid\": \"2\",\n            \"subscriberid\": \"5\",\n            \"subscriberseriesid\": \"83\",\n            \"timespan\": \"1\",\n            \"tstamp\": \"2021-05-12T14:55:19-05:00\",\n            \"links\": {\n                \"goal\": \"https://:account.api-us1.com/api/3/contactGoals/3/goal\",\n                \"automation\": \"https://:account.api-us1.com/api/3/contactGoals/3/automation\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactGoals/3/contact\",\n                \"contactAutomation\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactAutomation\",\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalLists\",\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalTags\"\n            },\n            \"id\": \"3\",\n            \"goal\": \"3\",\n            \"automation\": \"2\",\n            \"contact\": \"5\",\n            \"contactAutomation\": \"83\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contactGoals":{"type":"array","description":"One entry per goal the contact has reached.","items":{"type":"object","properties":{"goalid":{"type":"string","description":"ID of the goal.","example":"3"},"seriesid":{"type":"string","description":"ID of the automation the goal belongs to.","example":"2"},"subscriberid":{"type":"string","description":"ID of the contact.","example":"5"},"subscriberseriesid":{"type":"string","description":"ID of the automation run in which the goal was reached. Contacts can enter an automation more than once, so this tells the runs apart.","example":"83"},"timespan":{"type":"string","description":"Seconds between the contact entering the automation and reaching the goal.","example":"1"},"tstamp":{"type":"string","description":"When the contact reached the goal.","example":"2021-05-12T14:55:19-05:00"},"links":{"type":"object","description":"URLs of the records related to this entry.","properties":{"goal":{"type":"string","description":"URL of the goal.","example":"https://:account.api-us1.com/api/3/contactGoals/3/goal"},"automation":{"type":"string","description":"URL of the automation.","example":"https://:account.api-us1.com/api/3/contactGoals/3/automation"},"contact":{"type":"string","description":"URL of the contact.","example":"https://:account.api-us1.com/api/3/contactGoals/3/contact"},"contactAutomation":{"type":"string","description":"URL of the automation run.","example":"https://:account.api-us1.com/api/3/contactGoals/3/contactAutomation"},"contactGoalLists":{"type":"string","description":"URL of the lists the contact was on when the goal was reached.","example":"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalLists"},"contactGoalTags":{"type":"string","description":"URL of the tags the contact had when the goal was reached.","example":"https://:account.api-us1.com/api/3/contactGoals/3/contactGoalTags"}}},"id":{"type":"string","description":"ID of the entry.","example":"3"},"goal":{"type":"string","description":"ID of the goal, the same as goalid.","example":"3"},"automation":{"type":"string","description":"ID of the automation, the same as seriesid.","example":"2"},"contact":{"type":"string","description":"ID of the contact, the same as subscriberid.","example":"5"},"contactAutomation":{"type":"string","description":"ID of the automation run, the same as subscriberseriesid.","example":"83"}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 121\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 121"}}}}}}},"deprecated":false}},"/contacts/{id}/contactLists":{"get":{"summary":"Retrieve a contact's list memberships","description":"The lists this contact is on, one row per subscription with its status and dates. To answer how and when a contact left a list: status 2 is unsubscribed and 3 is bounced; udate is when the membership was unsubscribed or bounced and is null while it is active (a resubscribe clears it and resets sdate); unsubreason is the reason recorded with an unsubscribe, empty when none was given; sourceid says how the subscription was created (0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail). Every membership comes back in one response: limit and offset are ignored on this path.","operationId":"retrieve-contact-list-memberships","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's list subscriptions under contactLists; an empty list when it is on no list.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactLists\": [\n        {\n            \"contact\": \"19\",\n            \"list\": \"1\",\n            \"form\": null,\n            \"seriesid\": \"0\",\n            \"sdate\": \"2021-04-08T11:17:44-05:00\",\n            \"udate\": \"2021-05-12T11:10:06-05:00\",\n            \"status\": \"3\",\n            \"responder\": \"1\",\n            \"sync\": \"1\",\n            \"unsubreason\": null,\n            \"campaign\": null,\n            \"message\": null,\n            \"first_name\": \"John\",\n            \"last_name\": \"Doe\",\n            \"ip4Sub\": \"XXXXXXXXXX\",\n            \"sourceid\": \"1\",\n            \"autosyncLog\": null,\n            \"ip4_last\": \"0\",\n            \"ip4Unsub\": \"0\",\n            \"created_timestamp\": \"2021-04-08 11:17:44\",\n            \"updated_timestamp\": \"2021-05-12 11:10:06\",\n            \"created_by\": null,\n            \"updated_by\": null,\n            \"unsubscribeAutomation\": null,\n            \"links\": {\n                \"automation\": \"https://:account.api-us1.com/api/3/contactLists/19/automation\",\n                \"list\": \"https://:account.api-us1.com/api/3/contactLists/19/list\",\n                \"contact\": \"https://:account.api-us1.com/api/3/contactLists/19/contact\",\n                \"form\": \"https://:account.api-us1.com/api/3/contactLists/19/form\",\n                \"autosyncLog\": \"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog\",\n                \"campaign\": \"https://:account.api-us1.com/api/3/contactLists/19/campaign\",\n                \"unsubscribeAutomation\": \"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation\",\n                \"message\": \"https://:account.api-us1.com/api/3/contactLists/19/message\"\n            },\n            \"id\": \"19\",\n            \"automation\": null\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"contactLists":{"type":"array","description":"One entry per list membership of the contact.","items":{"type":"object","properties":{"contact":{"type":"string","example":"19","description":"Id of the contact."},"list":{"type":"string","example":"1","description":"Id of the list."},"form":{"description":"ID of the form that originally brought the contact onto the list. Kept when the contact resubscribes. Null when the subscription did not come from a form."},"seriesid":{"type":"string","description":"ID of the automation that subscribed the contact to the list; 0 when the subscription did not come from an automation.","example":"0"},"sdate":{"type":["string","null"],"example":"2021-04-08T11:17:44-05:00","description":"When the contact was last subscribed to the list. Reset when a contact resubscribes."},"udate":{"type":["string","null"],"example":"2021-05-12T11:10:06-05:00","description":"When the membership was unsubscribed or bounced. Null while it is active; a resubscribe clears it and resets sdate."},"status":{"type":"string","example":"3","description":"Subscription status on this list: 0 unconfirmed, 1 active, 2 unsubscribed, 3 bounced."},"responder":{"type":"string","description":"Whether list autoresponders are sent to this contact for this list: 1 yes (the default), 0 suppressed for this membership.","example":"1"},"sync":{"type":"string","description":"ID of the import or sync process that created the membership; 0 when it was not created by one.","example":"1"},"unsubreason":{"description":"The reason recorded with an unsubscribe. Empty when none was given."},"campaign":{"description":"ID of the campaign the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"message":{"description":"ID of the message the contact unsubscribed from, when the unsubscribe came from a campaign link. Null otherwise."},"first_name":{"type":"string","description":"The contact's first name at the time of the request.","example":"John"},"last_name":{"type":"string","description":"The contact's last name at the time of the request.","example":"Doe"},"ip4Sub":{"type":"string","description":"The IP address recorded when the contact subscribed. 0 when there is none.","example":"XXXXXXXXXX"},"sourceid":{"type":"string","example":"1","description":"How the subscription was created: 0 unknown, 1 import, 2 sync, 3 account user, 4 API, 5 form, 6 form opt-in, 7 trigger, 8 SMS, 9 automation, 10 bulk edit, 11 email, 12 Gmail."},"autosyncLog":{"description":"ID of the sync run that created the membership, for subscriptions created by an autosync. Null otherwise."},"ip4_last":{"type":"string","description":"The IP address recorded on the last subscription change. 0 when there is none.","example":"0"},"ip4Unsub":{"type":"string","example":"0","description":"The IP address recorded when the contact unsubscribed online. 0 when there is none."},"created_timestamp":{"type":"string","description":"When the membership record was created, account local time.","example":"2021-04-08 11:17:44"},"updated_timestamp":{"type":"string","description":"When the membership record was last changed, account local time.","example":"2021-05-12 11:10:06"},"created_by":{"description":"ID of the account user who created the membership; null when a contact, form, sync or automation created it."},"updated_by":{"description":"ID of the account user who last changed the membership; null when the last change was not made by a user."},"unsubscribeAutomation":{"description":"ID of the automation that unsubscribed the contact, when an automation did. Null otherwise."},"links":{"type":"object","description":"URLs of the records related to this membership.","properties":{"automation":{"type":"string","description":"URL of the automation that subscribed the contact.","example":"https://:account.api-us1.com/api/3/contactLists/19/automation"},"list":{"type":"string","description":"URL of the list.","example":"https://:account.api-us1.com/api/3/contactLists/19/list"},"contact":{"type":"string","description":"URL of the contact.","example":"https://:account.api-us1.com/api/3/contactLists/19/contact"},"form":{"type":"string","description":"URL of the form the subscription came from.","example":"https://:account.api-us1.com/api/3/contactLists/19/form"},"autosyncLog":{"type":"string","description":"URL of the sync run that created the membership.","example":"https://:account.api-us1.com/api/3/contactLists/19/autosyncLog"},"campaign":{"type":"string","description":"URL of the campaign the contact unsubscribed from.","example":"https://:account.api-us1.com/api/3/contactLists/19/campaign"},"unsubscribeAutomation":{"type":"string","description":"URL of the automation that unsubscribed the contact.","example":"https://:account.api-us1.com/api/3/contactLists/19/unsubscribeAutomation"},"message":{"type":"string","description":"URL of the message the contact unsubscribed from.","example":"https://:account.api-us1.com/api/3/contactLists/19/message"}}},"id":{"type":"string","description":"ID of the membership record.","example":"19"},"automation":{"description":"The automation that subscribed the contact, the same value as seriesid. Null when seriesid is 0."}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 121\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 121"}}}}}}},"deprecated":false}},"/contacts/{id}/contactLogs":{"get":{"summary":"Retrieve a contact's logs","description":"Log entries recorded against this contact. merge is the only action written today, recorded on the surviving contact, so most contacts have an empty list. Every entry comes back in one response: limit, offset, filters and orders are ignored on this path. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-logs","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's log entries under contactLogs; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contactLogs\": []\n}"}},"schema":{"type":"object","properties":{"contactLogs":{"type":"array","description":"The contact's log entries. Empty for most contacts; a merge records an entry on the surviving contact.","items":{"type":"object","properties":{"userid":{"type":["string","null"],"description":"Id of the account user who performed the merge. Same value as user."},"subscriberid":{"type":"string","description":"Id of the surviving contact. Same value as contact; on this path it is always the contact in the URL."},"name":{"type":["string","null"],"description":"Surviving contact's full name at the time of the merge."},"email":{"type":["string","null"],"description":"Surviving contact's email address at the time of the merge."},"action":{"type":"string","description":"What was logged. merge is the only action written today."},"params":{"type":["string","null"],"description":"JSON text with the source and destination contacts and the field and automation differences resolved by the merge."},"tstamp":{"type":["string","null"],"description":"When the entry was logged."},"created_timestamp":{"type":"string","description":"When the row was created, as YYYY-MM-DD HH:MM:SS."},"updated_timestamp":{"type":"string","description":"When the row was last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":["string","null"],"description":"Not set by the merge; null."},"updated_by":{"type":["string","null"],"description":"Not set by the merge; null."},"links":{"type":"object","description":"URLs of the entry's related resources.","properties":{"contact":{"type":"string","description":"URL to the contact."},"user":{"type":"string","description":"URL to the account user. Always present, even when userid is null."}}},"id":{"type":"string","description":"Id of the log entry."},"contact":{"type":"string","description":"Id of the contact. Same value as subscriberid."},"user":{"type":["string","null"],"description":"Id of the account user who performed the merge. Same value as userid. Absent (not null) when userid is null."}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/contactTags":{"get":{"summary":"List the tags applied to a contact","description":"List the tags applied to one contact, as contact-to-tag associations. Each item's tag is the tag id (fetch the name with GET /tags/{id}, or several at once with GET /tags?ids=1,2), and its id is the association id to pass to DELETE /contactTags/{id}. Returns every association the contact has: limit and offset are ignored. Associations whose tag has since been deleted are not shown. Returns 404 if the contact does not exist. GET /contactTags?filters[subscriberid]={id} returns the same associations with paging, plus any whose tag has been deleted. To apply tags use POST /contacts/{id}/tags; to remove one use DELETE /contacts/{id}/tags/{tagId}.","operationId":"retrieve-contact-tags","x-canonical-resource":"contactTags","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"The contact id."}],"responses":{"200":{"description":"Every tag association the contact has.","content":{"application/json":{"examples":{"Result":{"value":"{\"contactTags\":[{\"contact\":\"5606\",\"tag\":\"132\",\"cdate\":\"2026-07-22T16:22:19-05:00\",\"created_timestamp\":\"2026-07-22 16:22:19\",\"updated_timestamp\":\"2026-07-22 16:22:19\",\"created_by\":null,\"updated_by\":null,\"links\":{\"tag\":\"https://:account.api-us1.com/api/3/contactTags/208261/tag\",\"contact\":\"https://:account.api-us1.com/api/3/contactTags/208261/contact\"},\"id\":\"208261\"},{\"contact\":\"5606\",\"tag\":\"166\",\"cdate\":\"2026-09-23T15:37:14-05:00\",\"created_timestamp\":\"2026-09-23 15:37:14\",\"updated_timestamp\":\"2026-09-23 15:37:14\",\"created_by\":null,\"updated_by\":null,\"links\":{\"tag\":\"https://:account.api-us1.com/api/3/contactTags/218953/tag\",\"contact\":\"https://:account.api-us1.com/api/3/contactTags/218953/contact\"},\"id\":\"218953\"}]}"}},"schema":{"type":"object","properties":{"contactTags":{"type":"array","description":"One entry per tag applied to the contact.","items":{"type":"object","properties":{"id":{"type":"string","example":"218953","description":"The association id. Pass it to DELETE /contactTags/{id} to remove the tag from the contact."},"contact":{"type":"string","example":"5606","description":"The contact id."},"tag":{"type":"string","example":"166","description":"The tag id. Fetch the name with GET /tags/{id}, or several at once with GET /tags?ids=1,2"},"cdate":{"type":["string","null"],"example":"2026-09-23T15:37:14-05:00","description":"When the tag was applied."},"created_timestamp":{"type":"string","description":"When the association record was created, account local time.","example":"2026-09-23 15:37:14"},"updated_timestamp":{"type":"string","description":"When the association record was last changed, account local time.","example":"2026-09-23 15:37:14"},"created_by":{"type":["string","null"],"description":"ID of the account user who applied the tag; null when it was not applied by a user.","nullable":true},"updated_by":{"type":["string","null"],"description":"ID of the account user who last changed the association; null when the last change was not made by a user.","nullable":true},"links":{"type":"object","description":"URLs of the records related to this association.","properties":{"tag":{"type":"string","description":"URL of the tag."},"contact":{"type":"string","description":"URL of the contact."}}}}}}}}}}},"404":{"description":"No contact with that id.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Subscriber with id 999999999\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id."}}}}}}},"deprecated":false}},"/contacts/{id}/deals":{"get":{"summary":"Retrieve a contact's deals","description":"The deals on which this contact is the primary contact. Deals where the contact is only a secondary contact are not included; GET /contacts/{id}/contactDeals lists the contact's secondary-contact links. At most 100 deals come back and no order is guaranteed: limit, offset, filters and orders are ignored on this path, so a contact with more than 100 deals cannot be paged here. A user who is not allowed to see all deals gets only the deals they own. A deal in a pipeline the user cannot see comes back with isDisabled true and only its id, title and status. To find deals across contacts, use GET /deals, which supports filters such as filters[status], filters[stage], filters[group] and filters[owner] and orders such as orders[cdate] and orders[value]. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-deals","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The deals on which the contact is the primary contact, under deals; an empty list when there are none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"deals\": [\n        {\n            \"hash\": \"8be32as98\",\n            \"owner\": \"8\",\n            \"contact\": \"8\",\n            \"organization\": \"5\",\n            \"group\": \"1\",\n            \"stage\": \"4\",\n            \"title\": \"Acme Corp\",\n            \"description\": \"\",\n            \"percent\": \"0\",\n            \"cdate\": \"2021-06-30T15:27:44-05:00\",\n            \"mdate\": \"2021-06-30T15:27:44-05:00\",\n            \"nextdate\": null,\n            \"nexttaskid\": \"0\",\n            \"value\": \"494227\",\n            \"currency\": \"usd\",\n            \"winProbability\": null,\n            \"winProbabilityMdate\": null,\n            \"status\": \"2\",\n            \"activitycount\": \"1\",\n            \"nextdealid\": \"3060\",\n            \"edate\": null,\n            \"links\": {\n                \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/3057/dealActivities\",\n                \"contact\": \"https://:account.api-us1.com/api/3/deals/3057/contact\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/3057/contactDeals\",\n                \"group\": \"https://:account.api-us1.com/api/3/deals/3057/group\",\n                \"nextTask\": \"https://:account.api-us1.com/api/3/deals/3057/nextTask\",\n                \"notes\": \"https://:account.api-us1.com/api/3/deals/3057/notes\",\n                \"account\": \"https://:account.api-us1.com/api/3/deals/3057/account\",\n                \"customerAccount\": \"https://:account.api-us1.com/api/3/deals/3057/customerAccount\",\n                \"organization\": \"https://:account.api-us1.com/api/3/deals/3057/organization\",\n                \"owner\": \"https://:account.api-us1.com/api/3/deals/3057/owner\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/3057/scoreValues\",\n                \"stage\": \"https://:account.api-us1.com/api/3/deals/3057/stage\",\n                \"tasks\": \"https://:account.api-us1.com/api/3/deals/3057/tasks\",\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/3057/dealCustomFieldData\"\n            },\n            \"id\": \"3057\",\n            \"isDisabled\": false,\n            \"nextTask\": null,\n            \"account\": \"5\",\n            \"customerAccount\": \"5\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"hash":{"type":"string","example":"8be32as98","description":"Random eight-character code given to the deal when it was created."},"owner":{"type":["string","null"],"example":"8","description":"Deal's owner id. Null when the deal has no owner."},"contact":{"type":"string","example":"8","description":"Deal's primary contact id. On this path it is always the contact in the URL."},"organization":{"type":["string","null"],"example":"5","description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount."},"group":{"type":"string","example":"1","description":"Deal's pipeline id."},"stage":{"type":"string","example":"4","description":"Deal's stage id."},"title":{"type":"string","example":"Acme Corp","description":"Deal's title."},"description":{"type":"string","example":"","description":"Deal's description. Empty when none."},"percent":{"type":"string","example":"0","description":"Deal's percentage."},"cdate":{"type":"string","example":"2021-06-30T15:27:44-05:00","description":"When the deal was created."},"mdate":{"type":"string","example":"2021-06-30T15:27:44-05:00","description":"When the deal was last changed, including when an activity was added to it."},"nextdate":{"type":["string","null"],"description":"Due date of the deal's next open task. Null when there is none."},"nexttaskid":{"type":["string","null"],"description":"Id of the deal's next open task. Null (0 on older deals) when there is none."},"value":{"type":"string","example":"494227","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero."},"currency":{"type":"string","example":"usd","description":"Deal's currency in 3-digit ISO format, lowercased."},"winProbability":{"type":["number","null"],"description":"Predicted chance of winning the deal, as a whole percentage rounded up. Returned as a number, not a string. Null when the account does not have win probability or it has not been calculated yet."},"winProbabilityMdate":{"type":["string","null"],"description":"When winProbability was last updated. Null when it has never been calculated or the account does not have win probability."},"status":{"type":"string","example":"2","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")."},"activitycount":{"type":"string","example":"1","description":"Number of activities recorded on the deal."},"nextdealid":{"type":"string","example":"3060","description":"Internal pointer used to order the pipeline's open deals: the id of the deal that follows this one. 0 when there is none."},"edate":{"type":["string","null"],"description":"When email activity was last gathered for the deal. Null when it never was. Returned as YYYY-MM-DD HH:MM:SS, not in ISO 8601 format."},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/dealActivities","description":"URL to list the deal's activities."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/contact","description":"URL to the deal's primary contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/contactDeals","description":"URL to list the links between the deal and its contacts."},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/group","description":"URL to the deal's pipeline."},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/nextTask","description":"URL to the deal's next open task."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/notes","description":"URL to list the deal's notes."},"account":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/account","description":"URL to the deal's account."},"customerAccount":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/customerAccount","description":"URL to the deal's account (same as account)."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/organization","description":"URL to the deal's account (same as account)."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/owner","description":"URL to the deal's owner."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/scoreValues","description":"URL to list the deal's score values."},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/stage","description":"URL to the deal's stage."},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/tasks","description":"URL to list the deal's tasks."},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/dealCustomFieldData","description":"URL to list the deal's custom field values."}},"description":"URLs of the deal's related resources."},"id":{"type":"string","example":"3057","description":"Id of the deal."},"isDisabled":{"type":"boolean","example":false,"default":false,"description":"True when the deal is in a pipeline the current user cannot see. Such a deal comes back with only id, title, status and isDisabled."},"nextTask":{"type":["string","null"],"description":"Id of the deal's next open task, as a relationship key. Same as nexttaskid when there is one; null on older deals whose nexttaskid is 0; absent when nexttaskid is null."},"account":{"type":["string","null"],"example":"5","description":"Deal's account id. Null when the deal has no account. Same value as customerAccount and organization."},"customerAccount":{"type":["string","null"],"example":"5","description":"Deal's account id, under another name. Null when the deal has no account. Same value as account and organization."}}},"description":"The deals on which the contact is the primary contact, at most 100."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Why the request failed."}}}}}}},"deprecated":false}},"/contacts/{id}/fieldValues":{"get":{"summary":"Retrieve a contact's field values","description":"Returns every stored custom field value of one contact. The whole set is always returned: limit and offset are ignored on this endpoint. Each entry's field property is the custom field definition id; entries exist only for fields the contact has a stored value for. 404 if the contact does not exist.","operationId":"retrieve-contact-field-values","x-canonical-resource":"custom_field_value","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's custom field values under fieldValues; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"5\",\n            \"field\": \"1\",\n            \"value\": \"United States\",\n            \"cdate\": \"2021-05-12T14:19:38-05:00\",\n            \"udate\": \"2021-05-12T14:54:57-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/1/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/1/field\"\n            },\n            \"id\": \"1\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"5\",\n            \"field\": \"2\",\n            \"value\": \"Software\",\n            \"cdate\": \"2021-05-12T14:22:54-05:00\",\n            \"udate\": \"2021-05-12T14:54:57-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/2/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/2/field\"\n            },\n            \"id\": \"2\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"5\",\n            \"field\": \"3\",\n            \"value\": \"Yes\",\n            \"cdate\": \"2021-05-12T14:34:19-05:00\",\n            \"udate\": \"2021-05-12T14:54:57-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/3/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/3/field\"\n            },\n            \"id\": \"3\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"5\",\n            \"field\": \"4\",\n            \"value\": \"Landing Page\",\n            \"cdate\": \"2021-05-12T14:34:56-05:00\",\n            \"udate\": \"2021-05-12T14:54:57-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/4/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/4/field\"\n            },\n            \"id\": \"4\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"5\",\n            \"field\": \"5\",\n            \"value\": \"2021-05-02\",\n            \"cdate\": \"2021-05-12T14:36:26-05:00\",\n            \"udate\": \"2021-05-19T10:34:19-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/5/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/5/field\"\n            },\n            \"id\": \"5\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"5\",\n            \"field\": \"7\",\n            \"value\": \"Director\",\n            \"cdate\": \"2021-05-12T14:39:00-05:00\",\n            \"udate\": \"2021-05-12T14:54:57-05:00\",\n            \"created_by\": \"0\",\n            \"updated_by\": \"0\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/6/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/6/field\"\n            },\n            \"id\": \"6\",\n            \"owner\": \"5\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","description":"One entry per custom field the contact has a stored value for.","items":{"$ref":"#/components/schemas/ContactFieldValue"}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 100"}}}}}}},"deprecated":false}},"/contacts/{id}/geoIps":{"get":{"summary":"Retrieve a contacts list of geo-ips","description":"The IP addresses recorded for this contact, with the campaign and message they were seen on. Each entry carries the address as a number in text form (ip4) and the id of the location it resolved to (geoAddress); links.geoAddress leads to that location. At most 100 entries are returned, in no guaranteed order; limit and offset are ignored on this path. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-geo-ips","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's recorded IP addresses under geoIps; an empty list when there are none.","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"geoIps\": [{\n\t\t\"contact\": \"49\",\n\t\t\"campaignid\": \"11\",\n\t\t\"messageid\": \"12\",\n\t\t\"geoaddrid\": \"2\",\n\t\t\"ip4\": \"1123637995\",\n\t\t\"tstamp\": \"2021-05-12T11:10:06-05:00\",\n\t\t\"links\": {\n\t\t\t\"geoAddress\": \"https://:account.api-us1.com/api/3/geoIps/4/geoAddress\"\n\t\t},\n\t\t\"id\": \"4\",\n\t\t\"geoAddress\": \"2\"\n\t}]\n}"}},"schema":{"type":"object","properties":{"geoIps":{"type":"array","description":"Up to 100 IP address entries for the contact.","items":{"type":"object","properties":{"contact":{"type":"string","description":"ID of the contact.","example":"49"},"campaignid":{"type":"string","description":"ID of the campaign the address was seen on; 0 when none is recorded.","example":"11"},"messageid":{"type":"string","description":"ID of the message the address was seen on; 0 when none is recorded.","example":"12"},"geoaddrid":{"type":"string","description":"ID of the location the address resolved to.","example":"2"},"ip4":{"type":"string","description":"The IPv4 address as an unsigned integer, returned as a string.","example":"1123637995"},"tstamp":{"type":["string","null"],"description":"When the address was recorded.","example":"2021-05-12T11:10:06-05:00"},"links":{"type":"object","description":"URLs of the records related to this entry.","properties":{"geoAddress":{"type":"string","description":"URL of the location the address resolved to.","example":"https://:account.api-us1.com/api/3/geoIps/4/geoAddress"}}},"id":{"type":"string","description":"ID of the entry.","example":"4"},"geoAddress":{"type":["string","null"],"description":"ID of the location the address resolved to, the same as geoaddrid. Null when geoaddrid is 0.","example":"2"}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 100"}}}}}}},"deprecated":false}},"/contacts/{id}/organization":{"get":{"summary":"Retrieve a contacts organization","description":"The account (company) this contact belongs to, in the older organization shape: name, owner and dates. The account is found from the account id stored on the contact or, when that is not set, from the contact's account link. The response is an empty object {} when the contact has no account. This read is kept for compatibility; prefer GET /contacts/{id}/accountContacts and then GET /accounts/{id}, which also returns the account's website. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-organization","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's account under organization, or an empty object ({}) when the contact has no account.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"organization\": {\n        \"name\": \"M Corp\",\n        \"created_timestamp\": \"2021-05-21T16:15:47-05:00\",\n        \"updated_timestamp\": \"2021-08-24T06:28:56-05:00\",\n        \"userid\": \"1\",\n        \"id\": \"9\",\n        \"owner\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"organization":{"type":"object","properties":{"name":{"type":"string","example":"M Corp","description":"Account's name."},"created_timestamp":{"type":"string","example":"2021-05-21T16:15:47-05:00","description":"When the account was created."},"updated_timestamp":{"type":"string","example":"2021-08-24T06:28:56-05:00","description":"When the account was last changed."},"userid":{"type":"string","example":"1","description":"Id of the account user who owns the account. Same value as owner."},"id":{"type":"string","example":"9","description":"Id of the account. Use it with GET /accounts/{id}."},"owner":{"type":"string","example":"1","description":"Id of the account user who owns the account. Same value as userid."},"matching_enabled":{"type":["string","null"],"description":"Whether contacts are matched to this account by email domain: 1 yes, 0 no, null never set."}},"description":"The contact's account, in the older organization shape."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/plusAppend":{"get":{"summary":"Retrieve a contacts plus append","description":"Social profile details that contact enrichment has attached to this contact: a photo URL and Facebook, Twitter and LinkedIn profile URLs. This path serves a reduced copy of the record, so only those fields come back here; the last_updated dates and the other enrichment columns are not included. A contact has at most one such record, so limit and offset do not apply. The response is an empty object {} when the contact has none. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-plus-append","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's social profile record under plusAppend, or an empty object ({}) when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"plusAppend\": {\n        \"contact\": \"3\",\n        \"imageUrl\": \"https://img.fullcontact.com/static/ece148ad832u8f2c66f23442_3e5923f243234234cec57395be553465p96u9345u69u3456354345634\",\n        \"membershipsFacebook\": \"\",\n        \"membershipsTwitter\": \"https://twitter.com/twitterHandleHere\",\n        \"membershipsLinkedin\": \"\",\n        \"links\": {\n            \"contact\": \"https://:account.api-us1.com/api/3/plusAppends/2/contact\"\n        },\n        \"id\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"plusAppend":{"type":"object","properties":{"contact":{"type":"string","example":"3","description":"Id of the contact. On this path it is always the contact in the URL."},"imageUrl":{"type":"string","example":"https://img.fullcontact.com/static/ece148ad832u8f2c66f23442_3e5923f243234234cec57395be553465p96u9345u69u3456354345634","description":"URL of a photo of the contact found by enrichment. Empty when none."},"membershipsFacebook":{"type":"string","example":"","description":"URL of the contact's Facebook profile. Empty when none."},"membershipsTwitter":{"type":"string","example":"https://twitter.com/twitterHandleHere","description":"URL of the contact's Twitter/X profile. Empty when none."},"membershipsLinkedin":{"type":"string","example":"","description":"URL of the contact's LinkedIn profile. Empty when none."},"links":{"type":"object","properties":{"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/plusAppends/2/contact","description":"URL to the contact."}},"description":"URLs of the record's related resources."},"id":{"type":"string","example":"2","description":"Id of the enrichment record."}},"description":"The contact's enrichment record."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/scoreValues":{"get":{"summary":"Retrieve a contact's score value","description":"The contact's current point totals: one row per contact score, plus one row per deal for each deal score (deal is then that deal's id). score is the id of the score definition (see GET /scores), scoreValue is the points the contact holds for it, and deal is null for contact scores. Rows for scores that have since been deleted are left out. Every row comes back in one response and no order is guaranteed: limit, offset, filters and orders are ignored on this path. Returns 404 if the contact does not exist.","operationId":"retrieve-a-contacts-score-value","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"id of the Contact","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's score values under scoreValues; an empty list when it has none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"scoreValues\": [\n        {\n            \"score\": \"2\",\n            \"contact\": \"1\",\n            \"deal\": null,\n            \"cdate\": \"2018-03-08T14:01:16-06:00\",\n            \"mdate\": \"2018-10-22T20:15:28-05:00\",\n            \"scoreValue\": \"0\",\n            \"links\": {\n                \"score\": \"https://:account.api-us1.com/api/3/scoreValues/1/score\",\n                \"contact\": \"https://:account.api-us1.com/api/3/scoreValues/1/contact\",\n                \"deal\": \"https://:account.api-us1.com/api/3/scoreValues/1/deal\"\n            },\n            \"id\": \"1\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"scoreValues":{"type":"array","items":{"type":"object","properties":{"score":{"type":"string","example":"2","description":"Id of the score definition. See GET /scores."},"contact":{"type":"string","example":"1","description":"Id of the contact. On this path it is always the contact in the URL."},"deal":{"type":["string","null"],"description":"Id of the deal for a deal score. Null for contact scores."},"cdate":{"type":["string","null"],"example":"2018-03-08T14:01:16-06:00","description":"When the point total was first recorded."},"mdate":{"type":["string","null"],"example":"2018-10-22T20:15:28-05:00","description":"When the point total last changed."},"scoreValue":{"type":"string","example":"0","description":"The points the contact currently holds for this score."},"links":{"type":"object","properties":{"score":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/score","description":"URL to the score definition."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/contact","description":"URL to the contact."},"deal":{"type":"string","example":"https://:account.api-us1.com/api/3/scoreValues/1/deal","description":"URL to the deal. Only meaningful for deal scores."}},"description":"URLs of the row's related resources."},"id":{"type":"string","example":"1","description":"Id of the score value row."}}},"description":"The contact's score totals: one row per contact score, plus one row per deal for each deal score."}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Subscriber with id 100","description":"Says which record was not found and its id."}}}}}}},"deprecated":false}},"/contacts/{id}/trackingLogs":{"get":{"summary":"Retrieve a contacts tracking logs","description":"Returns every site-tracking and event-tracking log entry recorded for a contact. Each entry's id is the eventId that GET /trackingLogs/{eventId}/contact accepts; entry ids come from their own account-wide sequence and are unrelated to contact ids. The full list is returned in one response; limit and offset are ignored on this route (use GET /trackingLogs with filters[subscriberid] for a paginated listing). An entry's type is __pagevisit for a site-tracking page visit (value holds the page URL), __redir for a tracked link redirect (value holds the destination URL), or the name of an event-tracking event (value holds the event data). Entries are copied into this log when the contact's activity feed is refreshed, so events recorded moments ago may not appear yet. Returns 404 if the contact does not exist.","operationId":"retrieve-contact-tracking-logs","x-canonical-resource":"tracked_event","parameters":[{"name":"id","in":"path","description":"The contact's id (as returned by GET /contacts)","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The contact's site and event tracking entries under trackingLogs; an empty list when there are none.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"trackingLogs\": [\n        {\n            \"subscriberid\": \"112\",\n            \"type\": \"__pagevisit\",\n            \"value\": \"https://example.com/pricing\",\n            \"tstamp\": \"2026-09-18T12:20:52-05:00\",\n            \"hash\": \"d855fd4ecb9dd4a88c9b30cc857c765a913ebd69\",\n            \"links\": {\n                \"contact\": \"https://yourAccountName.api-us1.com/api/3/trackingLogs/1/contact\"\n            },\n            \"id\": \"1\",\n            \"contact\": \"112\"\n        },\n        {\n            \"subscriberid\": \"112\",\n            \"type\": \"Order Shipped\",\n            \"value\": \"order 1042\",\n            \"tstamp\": \"2026-09-18T12:25:52-05:00\",\n            \"hash\": \"b0390c0772f0b5393486e7c542b80bd4d41730e8\",\n            \"links\": {\n                \"contact\": \"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact\"\n            },\n            \"id\": \"2\",\n            \"contact\": \"112\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"trackingLogs":{"type":"array","description":"One entry per tracked page visit, link redirect or event for the contact.","items":{"type":"object","properties":{"subscriberid":{"type":"string","description":"ID of the contact.","example":"112"},"type":{"type":"string","description":"What was tracked: __pagevisit for a site-tracking page visit, __redir for a tracked link redirect, or the name of an event-tracking event.","example":"Order Shipped"},"value":{"type":"string","description":"The tracked data: the page URL for __pagevisit, the destination URL for __redir, or the event data for an event.","example":"order 1042"},"tstamp":{"type":"string","description":"When the event happened.","example":"2026-09-18T12:25:52-05:00"},"hash":{"type":"string","description":"SHA-1 of the contact id, type and timestamp. Unique per entry, so the same event is not stored twice.","example":"b0390c0772f0b5393486e7c542b80bd4d41730e8"},"links":{"type":"object","description":"URLs of the records related to this entry.","properties":{"contact":{"type":"string","description":"URL of the contact.","example":"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact"}}},"id":{"type":"string","description":"ID of the entry. Pass it as eventId to GET /trackingLogs/{eventId}/contact.","example":"2"},"contact":{"type":"string","description":"ID of the contact, the same as subscriberid.","example":"112"}}}}}}}}},"404":{"description":"No contact has this id. Body: message, \"No Result found for Subscriber with id\" followed by the id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no contact has that id.","example":"No Result found for Subscriber with id 100"}}}}}}},"deprecated":false}},"/content-proxy/files":{"get":{"summary":"Search the Content Manager for files","description":"Files stored in the account's Content Manager, found by title, keyword or alt text, one page at a time: 20 files by default and 40 at most, with fileCount giving how many match in all. Results are not only images: filter with mimeType or mimeTypes to keep one kind of file, or check each file's mimeType. Pass folderId to search one folder. Use sort=added,desc for newest first. Each file carries its storage key, and its address is built from baseUrl and that key together.","operationId":"search-content-manager-files","x-canonical-resource":"content_manager_file","tags":["Content Manager"],"parameters":[{"name":"name","in":"query","required":false,"schema":{"type":"string"},"description":"Search text. Matches part of a file's title, one of its keywords or its alt text."},{"name":"folderId","in":"query","required":false,"schema":{"type":"integer","format":"int64"},"description":"Only files directly in this folder."},{"name":"mimeType","in":"query","required":false,"schema":{"type":"string"},"description":"Only files of exactly this type, such as image/png. Matching is exact: image/* matches nothing."},{"name":"mimeTypes","in":"query","required":false,"schema":{"type":"string"},"description":"Only files of any of these types, separated by commas, such as image/jpeg,image/png,image/gif. Matching is exact."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Page number, starting at 0."},{"name":"size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":40,"default":20},"description":"How many files per page, from 1 to 40. A larger value is rejected with a 400."},{"name":"sort","in":"query","required":false,"schema":{"type":"string"},"description":"Order as property,direction: the property is name, size or added, the direction asc or desc. Any other property is ignored. Use added,desc for newest first. Without it the order is not defined."}],"responses":{"200":{"description":"Search the Content Manager for files","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the file.","format":"int64"},"userId":{"type":"integer","description":"ID of the user who uploaded the file.","format":"int32"},"name":{"type":"string","description":"The file's title."},"altText":{"type":"string","description":"Alt text of the file."},"mimeType":{"type":"string","description":"The file's type, such as image/png or application/pdf."},"size":{"type":"integer","description":"File size in bytes.","format":"int64"},"height":{"type":"integer","description":"Height in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"width":{"type":"integer","description":"Width in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"s3Key":{"type":"string","description":"Storage key of the file. Not an address: see baseUrl."},"thumbnailS3Key":{"type":"string","description":"Storage key of the file's thumbnail, empty when the type has none."},"campaignS3Key":{"type":"string","description":"Empty for every file type the Content Manager sets up today."},"added":{"type":"string","description":"When the file was uploaded, as an ISO 8601 timestamp.","format":"date-time"},"tags":{"type":"array","description":"The file's keywords.","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the keyword.","format":"int64"},"name":{"type":"string","description":"The keyword."}}}}}}},"baseUrl":{"type":"string","description":"Address the storage keys are resolved against. Not always a public address: see the s3Key caveat."},"fileCount":{"type":"integer","description":"How many files match in all, not how many this page holds.","format":"int64"}}}}}}}}},"/content-proxy/files/{id}":{"get":{"summary":"Retrieve a Content Manager file","description":"One file from the account's Content Manager by its ID: its title, alt text, type, size, dimensions, keywords and storage keys, and who last changed it and when. Answers 404 when the account has no such file. Unlike the search and the lists, retrieving by ID can still return a file that was deleted.","operationId":"retrieve-a-content-manager-file","x-canonical-resource":"content_manager_file","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the file."}],"responses":{"200":{"description":"Retrieve a Content Manager file","content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the file.","format":"int64"},"userId":{"type":"integer","description":"ID of the user who uploaded the file.","format":"int32"},"name":{"type":"string","description":"The file's title."},"altText":{"type":"string","description":"Alt text of the file."},"mimeType":{"type":"string","description":"The file's type, such as image/png or application/pdf."},"size":{"type":"integer","description":"File size in bytes.","format":"int64"},"height":{"type":"integer","description":"Height in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"width":{"type":"integer","description":"Width in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"s3Key":{"type":"string","description":"Storage key of the file. Not an address: see baseUrl."},"thumbnailS3Key":{"type":"string","description":"Storage key of the file's thumbnail, empty when the type has none."},"campaignS3Key":{"type":"string","description":"Empty for every file type the Content Manager sets up today."},"added":{"type":"string","description":"When the file was uploaded, as an ISO 8601 timestamp.","format":"date-time"},"tags":{"type":"array","description":"The file's keywords.","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the keyword.","format":"int64"},"name":{"type":"string","description":"The keyword."}}}},"updatedBy":{"type":"string","description":"Who last changed the file."},"updatedOn":{"type":"integer","description":"When the file was last changed, in epoch milliseconds.","format":"int64"}}},"baseUrl":{"type":"string","description":"Address the storage keys are resolved against. Not always a public address: see the s3Key caveat."}}}}}}}}},"/content-proxy/files/{id}/folders":{"get":{"summary":"Show which folders a Content Manager file is in","description":"Which custom folders of the Content Manager hold one file, given the file's ID.","operationId":"list-content-manager-file-folders","x-canonical-resource":"content_manager_folder","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the file."}],"responses":{"200":{"description":"Show which folders a Content Manager file is in","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the folder.","format":"int64"},"name":{"type":"string","description":"The folder's name."}}}}}}}}}},"/content-proxy/files/{id}/tags":{"get":{"summary":"List the keywords on a Content Manager file","description":"The keywords added to one file in the Content Manager. These are the words the search matches on besides the file's title.","operationId":"list-content-manager-file-keywords","x-canonical-resource":"content_manager_file","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the file."}],"responses":{"200":{"description":"List the keywords on a Content Manager file","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the keyword.","format":"int64"},"name":{"type":"string","description":"The keyword."}}}}}}}}}},"/content-proxy/folders":{"get":{"summary":"List all Content Manager folders","description":"Every custom folder in the account's Content Manager, with its ID and name. Deleting a folder leaves its files in the Content Manager.","operationId":"list-all-content-manager-folders","x-canonical-resource":"content_manager_folder","tags":["Content Manager"],"parameters":[],"responses":{"200":{"description":"List all Content Manager folders","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the folder.","format":"int64"},"name":{"type":"string","description":"The folder's name."}}}}}}}}}},"/content-proxy/folders/{id}":{"get":{"summary":"Retrieve a Content Manager folder","description":"One custom folder from the account's Content Manager by its ID.","operationId":"retrieve-a-content-manager-folder","x-canonical-resource":"content_manager_folder","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the folder."}],"responses":{"200":{"description":"Retrieve a Content Manager folder","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the folder.","format":"int64"},"name":{"type":"string","description":"The folder's name."}}}}}}}}},"/content-proxy/folders/{id}/files":{"get":{"summary":"List the files in a Content Manager folder","description":"The files in one custom folder of the account's Content Manager. The API does not page this list and limit and offset do nothing here: the catalog cuts the response at 100 files and its truncation note gives the full count. For a larger folder use the file search with folderId and page. Each file carries its storage key, and its address is built from baseUrl and that key together.","operationId":"list-content-manager-folder-files","x-canonical-resource":"content_manager_file","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the folder."}],"responses":{"200":{"description":"List the files in a Content Manager folder","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the file.","format":"int64"},"userId":{"type":"integer","description":"ID of the user who uploaded the file.","format":"int32"},"name":{"type":"string","description":"The file's title."},"altText":{"type":"string","description":"Alt text of the file."},"mimeType":{"type":"string","description":"The file's type, such as image/png or application/pdf."},"size":{"type":"integer","description":"File size in bytes.","format":"int64"},"height":{"type":"integer","description":"Height in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"width":{"type":"integer","description":"Width in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"s3Key":{"type":"string","description":"Storage key of the file. Not an address: see baseUrl."},"thumbnailS3Key":{"type":"string","description":"Storage key of the file's thumbnail, empty when the type has none."},"campaignS3Key":{"type":"string","description":"Empty for every file type the Content Manager sets up today."},"added":{"type":"string","description":"When the file was uploaded, as an ISO 8601 timestamp.","format":"date-time"}}}},"baseUrl":{"type":"string","description":"Address the storage keys are resolved against. Not always a public address: see the s3Key caveat."}}}}}}}}},"/content-proxy/tags/{id}/files":{"get":{"summary":"List the files with a keyword","description":"The files in the account's Content Manager that have one keyword. Find a keyword's ID from a file's keywords. The API does not page this list and limit and offset do nothing here: the catalog cuts the response at 100 files and its truncation note gives the full count. For a keyword with more files use the file search with name set to the keyword and page. Each file carries its storage key, and its address is built from baseUrl and that key together.","operationId":"list-content-manager-keyword-files","x-canonical-resource":"content_manager_file","tags":["Content Manager"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"},"description":"ID of the keyword."}],"responses":{"200":{"description":"List the files with a keyword","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the file.","format":"int64"},"userId":{"type":"integer","description":"ID of the user who uploaded the file.","format":"int32"},"name":{"type":"string","description":"The file's title."},"altText":{"type":"string","description":"Alt text of the file."},"mimeType":{"type":"string","description":"The file's type, such as image/png or application/pdf."},"size":{"type":"integer","description":"File size in bytes.","format":"int64"},"height":{"type":"integer","description":"Height in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"width":{"type":"integer","description":"Width in pixels, or -1 when it was not recorded, which is common.","format":"int32"},"s3Key":{"type":"string","description":"Storage key of the file. Not an address: see baseUrl."},"thumbnailS3Key":{"type":"string","description":"Storage key of the file's thumbnail, empty when the type has none."},"campaignS3Key":{"type":"string","description":"Empty for every file type the Content Manager sets up today."},"added":{"type":"string","description":"When the file was uploaded, as an ISO 8601 timestamp.","format":"date-time"}}}},"baseUrl":{"type":"string","description":"Address the storage keys are resolved against. Not always a public address: see the s3Key caveat."}}}}}}}}},"/content/autoSave":{"post":{"summary":"Autosave the designer markup of a campaign message","description":"Stores the HTML and CSS the campaign designer (Stripo) sends while a user edits a campaign message as that message's designer markup, and keeps the email that is sent in step with it. Before storing, javascript: prefixes are removed, script tags are escaped and event-handler attributes are renamed with an UNUSED_ prefix. Stripo compiles the markup into inlined email HTML (Hosted inlines the CSS itself when the Stripo call fails) and the result is written to the message on a best-effort basis: if that write fails the markup is still saved. The message's links are saved for tracking, link actions in the markup are reconciled with their automations, and the campaign's moderation status is reset. For a split campaign whose variants share one design, the markup of every message of the campaign is written. The save is skipped, and the call answers 200, when the user may not edit the campaign: it does not exist, it is sent to lists none of which are the user's and the user is not an admin, or it is sending, stopped, complete or awaiting approval and is not an automation or form campaign. The body is read without validation. Only POST is accepted; other verbs answer 405 with an Allow: POST header. Internal: the campaign designer's autosave.","operationId":"autosave-message-markup","x-canonical-resource":"content","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["campaignId","messageId","html","css"],"properties":{"campaignId":{"type":"integer","description":"ID of the campaign the message belongs to.","example":412},"messageId":{"type":"integer","description":"ID of the campaign message.","example":538},"html":{"type":"string","description":"The designer HTML of the message, as Stripo returns it.","example":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>"},"css":{"type":"string","description":"The designer CSS of the message, as Stripo returns it.","example":"p { color: #333333; }"}}},"example":{"campaignId":412,"messageId":538,"html":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>","css":"p { color: #333333; }"}}}},"responses":{"200":{"description":"The user may not edit the campaign, so nothing was saved. The body is the JSON literal null.","content":{"application/json":{"schema":{"type":"null","description":"Always the JSON literal null."}}}},"201":{"description":"The markup was saved. The body is the JSON literal null.","content":{"application/json":{"schema":{"type":"null","description":"Always the JSON literal null."}}}},"500":{"description":"Saving failed and was rolled back, or the body was not a JSON object. The body is empty."}},"deprecated":false,"x-internal":true}},"/content/campaignScreenshot":{"post":{"summary":"Request a screenshot of a campaign message","description":"Asks the screenshot service for a new screenshot of the message, unless the campaign already has a stored designer screenshot, in which case nothing is requested. For a split campaign whose variants share one design, every other message of the campaign is handled the same way. The body is read without validation. Only POST is accepted; other verbs answer 405 with an Allow: POST header. Internal: called by the campaign designer after it saves a message.","operationId":"request-campaign-screenshot","x-canonical-resource":"content","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["campaignId","messageId"],"properties":{"campaignId":{"type":"integer","description":"ID of the campaign the message belongs to.","example":412},"messageId":{"type":"integer","description":"ID of the campaign message.","example":538}}},"example":{"campaignId":412,"messageId":538}}}},"responses":{"200":{"description":"The screenshot was requested, or the campaign already had one. The body is the JSON literal null.","content":{"application/json":{"schema":{"type":"null","description":"Always the JSON literal null."}}}},"500":{"description":"A screenshot had to be requested and the message does not exist, the request to the screenshot service failed, or the body was not a JSON object. The body is empty."}},"deprecated":false,"x-internal":true}},"/content/compileInlineEmail":{"post":{"summary":"Compile a campaign message and save it as the email to send","description":"Turns a campaign message's designer markup into the email that is sent. When html and css are both sent and non-empty they are first stored as the message's designer markup, with a version-history entry when the message was built in the designer; otherwise the markup already stored for the message is used. Stripo compiles the markup into inlined email HTML, which is written to the message (with subject and preHeader when sent) after conditional syntax and editor-only attributes are removed and images are resized; the message's links are saved for tracking and a fresh screenshot is requested. For a split campaign whose variants share one design, every message of the campaign is written. When the campaign has been saved before, neither subject nor preHeader is sent and the compiled HTML equals what the message already stores, the message is left as it is. Saving the links can delete the automations of link actions whose links are no longer in the message, for a campaign that has not started sending, and a changed message must go through campaign approval again before it sends. Internal: used by the app's AI campaign-from-prompt flow and by services that edit campaign content.","operationId":"compile-and-save-inline-email","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InlineEmailRequest"},"example":{"campaignId":412,"messageId":538,"html":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>","css":"p { color: #333333; }","minimize":true,"subject":"Our spring collection is here"}}}},"responses":{"200":{"description":"The message was compiled and saved","content":{"application/json":{"schema":{"properties":{"compiledHtml":{"description":"The inlined email HTML Stripo compiled. The message stores it after conditional syntax and editor-only attributes are removed and images are resized.","type":"string","example":"<!DOCTYPE html><html><body><table class=\"es-wrapper\"><tr><td><p style=\"color:#333333\">Hello</p></td></tr></table></body></html>"},"patchId":{"description":"Stripo identifier of the version-history entry the save recorded, as a string. Null when no html and css were sent, the message was not built in the designer, or Stripo did not confirm the entry; the save still succeeded.","type":["string","null"]}},"type":"object"},"example":{"compiledHtml":"<!DOCTYPE html><html><body><table class=\"es-wrapper\"><tr><td><p style=\"color:#333333\">Hello</p></td></tr></table></body></html>","patchId":null}}}},"400":{"description":"The body is empty, is not valid JSON or is not a JSON object. Body: errors, a list with one item carrying status and detail."},"422":{"description":"campaignId or messageId is missing, is not an integer or names no campaign or message; the campaign is sending, stopped, complete or awaiting approval and is not an automation or form campaign; a field has the wrong JSON type; or subject, preHeader or versionLabel is empty or too long. Body: errors, one item per problem carrying status, title, detail and source.pointer.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One item per field that failed validation.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Short title of the error.","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the field.","type":"string","example":"subject must not be empty"},"source":{"description":"Where the error is.","properties":{"pointer":{"description":"The field, as /data/attributes/<field>.","type":"string","example":"/data/attributes/subject"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"Saving the markup, reading the stored markup, compiling or saving the email failed. Body: errors, a list with one item whose detail names the step: Unable to auto save inline email, Unable to find message markup, Unable to compile inline email or Unable to save inline email."}},"x-canonical-resource":"content","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/content/domainAuth":{"get":{"summary":"Check the email authentication of a From address domain","description":"Builds the email-authentication notice the campaign designer shows for a campaign's From address. Only the first domain in domains is checked. For a free-mail domain (gmail.com, googlemail.com or yahoo.com) the notice is always a warning, filled in with a substitute sending address built from fromEmail (its local part and domain joined with a dot, at <account ID>.emcampaign.com) and with replyEmail. For any other domain Hosted checks the domain's DKIM, DMARC and DNS records: the notice describes the first problem found, and when none is found appearance is success and title and description are empty. Texts are translated into the user's language, and isAdmin picks the admin wording and points the button at the advanced settings instead of a help article. Legacy endpoint with no method guard in the file; the controller itself answers anything but GET with 405 and a plain-text sentence. Internal: called by the campaign designer's From address modal.","operationId":"check-from-domain-authentication","x-canonical-resource":"content","parameters":[{"name":"domains","in":"query","description":"Domain of the From address to check. A comma-separated list is accepted, but only the first domain is checked.","required":true,"schema":{"type":"string"},"example":"example.com"},{"name":"fromEmail","in":"query","description":"The campaign's From address. Only used for a free-mail domain, to build the substitute sending address the notice names.","required":true,"schema":{"type":"string"},"example":"jane@example.com"},{"name":"replyEmail","in":"query","description":"The campaign's reply-to address. Only used for a free-mail domain, where the notice names it.","required":true,"schema":{"type":"string"},"example":"support@example.com"},{"name":"isAdmin","in":"query","description":"1 when the user is an admin. Any other value gives the non-admin wording and a help article link.","required":true,"schema":{"type":"string"},"example":"1"}],"responses":{"200":{"description":"The notice to show","content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Translated heading of the notice. Empty when no problem was found."},"description":{"type":"string","description":"Translated body of the notice. Empty when no problem was found."},"appearance":{"type":"string","enum":["success","warning","danger","error"],"description":"How the designer styles the notice: success when no problem was found; warning for a free-mail domain or a domain with only one of its two DKIM CNAME records; danger for a problematic DMARC policy or incomplete DNS setup; error for any other check result."},"buttonLink":{"type":["string","null"],"description":"Where the notice's button goes: /app/settings/advanced for an admin, otherwise a help article about the problem. Null for a non-admin when no problem was found."},"buttonLabel":{"type":"string","description":"Translated text of the button: the advanced settings label for an admin, a learn more label otherwise."},"isSmallSender":{"type":"boolean","description":"True when the small-sender email authentication flag is on for the account and it has fewer than 5,000 contacts. When it is true and appearance is not success, the designer shows the small-sender notice instead of this one."},"smallSenderTitle":{"type":"string","description":"Translated heading of the small-sender notice."},"smallSenderLabel":{"type":"string","description":"Translated text of the small-sender notice's link."},"smallSenderLink":{"type":"string","description":"Help article the small-sender notice links to.","example":"https://help.activecampaign.com/hc/en-us/articles/360015584680-Set-up-your-sending-domain"}}}}}},"400":{"description":"At least one of the four query parameters is missing. The body is a plain-text sentence naming them, for example: The following query parameters are required: fromEmail, replyEmail.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The authentication check failed. The body is the plain-text sentence Error trying to fetch domains.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/content/editorMarkup/{messageId}":{"get":{"summary":"Get Editor Markup","description":"The HTML and CSS the campaign designer (Stripo) stores for one campaign message: the editable design, not the compiled email. Unlike GET /content/messageMarkup/{messageId}, the strings are returned as stored, apart from three conditional-content comment markers (`<!-- %IF`, `% -->` and `<!-- %/IF% -->`) that are restored when they were saved HTML-escaped. A message with no stored designer markup, including an ID that names no message, answers 404.","operationId":"get-editor-markup","parameters":[{"name":"messageId","in":"path","description":"ID of the campaign message","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The stored designer markup","content":{"application/json":{"schema":{"properties":{"html":{"description":"The designer HTML of the message.","type":"string","example":"<p>Test html</p>"},"css":{"description":"The designer CSS of the message.","type":"string","example":"p { color: red; }"}},"type":"object"},"example":{"html":"<p>Test html</p>","css":"p { color: red; }"}}}},"404":{"description":"The message has no stored designer markup","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always No markup for message.","type":"string","example":"No markup for message"}},"type":"object"},"example":{"message":"No markup for message"}}}}},"x-canonical-resource":"content"}},"/content/inlineEmail":{"post":{"summary":"Save the compiled email HTML of a campaign message","description":"Stores the inlined email HTML the campaign designer (Stripo) compiled as the message's sendable body, in one transaction with the campaign's modified date, retried when the database reports a deadlock. Conditional syntax, the editor-only link-actions attribute and unwanted tags are removed and images are resized first; the plain-text version is regenerated unless the campaign manages its text separately, and an RSS campaign's feed details are refreshed. The message's links are saved for tracking, which can delete the automations of link actions whose links are no longer in the message when the campaign has not started sending, and the campaign must go through approval again before it sends. For a split campaign whose variants share one design, every message of the campaign is written and their links are saved too. The body is read without validation. Only POST is accepted; other verbs answer 405 with an Allow: POST header. Internal: called by the campaign designer when the user saves the message or leaves the editor.","operationId":"save-inline-email","x-canonical-resource":"content","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["campaignId","messageId","compiledHtml"],"properties":{"campaignId":{"type":"integer","description":"ID of the campaign the message belongs to.","example":412},"messageId":{"type":"integer","description":"ID of the campaign message.","example":538},"compiledHtml":{"type":"string","description":"The inlined email HTML Stripo compiled for the message.","example":"<!DOCTYPE html><html><body><table class=\"es-wrapper\"><tr><td><p style=\"color:#333333\">Hello</p></td></tr></table></body></html>"}}},"example":{"campaignId":412,"messageId":538,"compiledHtml":"<!DOCTYPE html><html><body><table class=\"es-wrapper\"><tr><td><p style=\"color:#333333\">Hello</p></td></tr></table></body></html>"}}}},"responses":{"201":{"description":"The HTML was saved. The body is the campaign the message belongs to, under campaign.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"object","description":"The campaign record as the campaign model serialises it: its fields, mostly as strings, and links to its related records."}}}}}},"500":{"description":"The campaign does not exist, saving failed and was rolled back, or the body was not a JSON object. The body is empty."}},"deprecated":false,"x-internal":true}},"/content/messageMarkup/{messageId}":{"get":{"summary":"Retrieve the designer markup of a campaign message","description":"The HTML and CSS the campaign designer (Stripo) stores for one campaign message: the editable design, not the compiled email. Both strings are cleaned before they are returned: javascript: prefixes are removed, script tags are escaped as text and event-handler attributes such as onclick are renamed with an UNUSED_ prefix; the editor-only link-actions attribute is also removed from the HTML. A message with no stored designer markup, including an ID that names no message, answers 200 with both strings empty. Internal: read by the app's AI campaign-from-prompt flow.","operationId":"retrieve-message-markup","parameters":[{"name":"messageId","in":"path","description":"ID of the campaign message","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The stored designer markup, or two empty strings when the message has none","content":{"application/json":{"schema":{"properties":{"html":{"description":"The designer HTML of the message, cleaned as described above. Empty when the message has no designer markup.","type":"string","example":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>"},"css":{"description":"The designer CSS of the message, cleaned the same way. Empty when the message has no designer markup.","type":"string","example":"p { color: #333333; }"}},"type":"object"},"example":{"html":"<table class=\"es-wrapper\"><tr><td><p>Hello</p></td></tr></table>","css":"p { color: #333333; }"}}}}},"x-canonical-resource":"content","x-internal":true}},"/content/setSeriesCampaignToScheduled":{"post":{"summary":"Mark an automation email as scheduled","description":"Moves an automation's email from draft to scheduled: when the campaign belongs to an automation, is a draft (status 0) and is not a split campaign, its status becomes scheduled (1). Any other campaign is left as it is, and the call still answers 200. The body is read without validation. Only POST is accepted; other verbs answer 405 with an Allow: POST header. Internal: called by the campaign designer's Save and exit button.","operationId":"schedule-automation-campaign","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["campaignId"],"properties":{"campaignId":{"type":"integer","description":"ID of the campaign the message belongs to.","example":412}}},"example":{"campaignId":412}}}},"responses":{"200":{"description":"The campaign was scheduled, or it did not qualify and was left as it is. The body is the JSON string \"\".","content":{"application/json":{"schema":{"type":"string","description":"Always an empty string.","example":""}}}},"500":{"description":"Updating the campaign failed. The body is empty."}},"deprecated":false,"x-internal":true}},"/conversion/code":{"get":{"summary":"Manual conversion tracking embed code","description":"Returns a <script> snippet customers paste into their site to fire a conversion client-side via the %CONVERSION_ID% placeholder. Not a JSON endpoint -- the response body is the raw script text, paired with GET /siteTracking/code for site-visit tracking.","operationId":"retrieve-conversion-tracking-code","x-canonical-resource":"conversion_trigger","responses":{"200":{"description":"200 -- raw <script> HTML, not JSON","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Manual conversion tracking embed code (POST)","description":"Same response as GET /conversion/code. api/3/conversion/code.php has no method guard and StandaloneFileMatcher imposes no method restriction on standalone files, so this method also returns the raw <script> snippet; nothing is created, changed, or deleted. Documented for compatibility with the deployed endpoint; prefer GET.","operationId":"retrieve-conversion-tracking-code-via-post","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"200 -- raw <script> HTML, not JSON","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Manual conversion tracking embed code (PUT)","description":"Same response as GET /conversion/code. api/3/conversion/code.php has no method guard and StandaloneFileMatcher imposes no method restriction on standalone files, so this method also returns the raw <script> snippet; nothing is created, changed, or deleted. Documented for compatibility with the deployed endpoint; prefer GET.","operationId":"retrieve-conversion-tracking-code-via-put","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"200 -- raw <script> HTML, not JSON","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"patch":{"summary":"Manual conversion tracking embed code (PATCH)","description":"Same response as GET /conversion/code. api/3/conversion/code.php has no method guard and StandaloneFileMatcher imposes no method restriction on standalone files, so this method also returns the raw <script> snippet; nothing is created, changed, or deleted. Documented for compatibility with the deployed endpoint; prefer GET.","operationId":"retrieve-conversion-tracking-code-via-patch","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"200 -- raw <script> HTML, not JSON","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"delete":{"summary":"Manual conversion tracking embed code (DELETE)","description":"Same response as GET /conversion/code. api/3/conversion/code.php has no method guard and StandaloneFileMatcher imposes no method restriction on standalone files, so this method also returns the raw <script> snippet; nothing is created, changed, or deleted. Documented for compatibility with the deployed endpoint; prefer GET.","operationId":"retrieve-conversion-tracking-code-via-delete","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"200 -- raw <script> HTML, not JSON","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/conversion/trigger_conversion":{"post":{"summary":"Trigger applicable conversions for a contact","description":"Internal: called by the queue-http-service relay (trackcmp/attribution worker), not meant for direct external use. Identifies the contact by email or phone, then triggers by conversion id, URL match, or named event -- exactly one of conversionId, url, or event must resolve. Returns 200 with a plain-text message even when no matching contact is found, since trackcmp forwards visitors regardless of whether they're a known contact.","operationId":"trigger-conversion-for-contact","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/SubscriberConversionTriggerMessage"}},"description":"Wrapped exactly as Conversion::queueTrigger() enqueues it via UsesSQSTrait::sqsEnqueue() -- {acctid, type, data: <SubscriberConversionSQSMessage>} -- and as trigger_conversion.php unwraps it (`if (in_array(\"data\", array_keys($body))) { $body = $body['data']; }`)."}}}},"responses":{"200":{"description":"200 -- plain text, not JSON (e.g. the contact-not-found case)","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Neither email nor phone provided"},"405":{"description":"Method other than POST"}},"deprecated":false,"x-internal":true}},"/conversionSegmentTrigger/contact":{"post":{"summary":"Trigger a segment-based conversion for a contact","description":"Internal: queue-http-service entry point for ConversionSegmentationWorker's async segment-trigger processing. Deduplicates against already-triggered contacts before firing.","operationId":"trigger-segment-conversion-for-contact","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"description":"SegmentConversionTriggerQueueService::handleQueueTriggerRequest() reads only the form-decoded body ($req->request->all()), never a JSON body, and accepts either shape: `$data = $request['data'] ?? $request;`. The queue-http-service relay sends the wrapped form as bracketed fields (data[triggerId], data[contactId], data[timestamp]); direct calls may send the flat form.","oneOf":[{"$ref":"#/components/schemas/SegmentConversionTriggerMessage"},{"required":["data"],"properties":{"data":{"$ref":"#/components/schemas/SegmentConversionTriggerMessage"}},"type":"object"}]}}}},"responses":{"200":{"description":"200 -- a plain JSON-encoded string message, not an object","content":{"application/json":{"schema":{"type":"string"}}}},"422":{"description":"triggerId or contactId not found -- a plain JSON-encoded string message"},"500":{"description":"Unexpected error -- a plain JSON-encoded string message"}},"x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/conversionTrigger/bulk":{"post":{"summary":"Bulk-create conversion triggers","description":"Body must be in Ember Data RESTSerializer format. All-or-nothing: the whole batch is rolled back if any item fails.","operationId":"bulk-create-conversion-triggers","x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conversionTriggers"],"properties":{"conversionTriggers":{"type":"array","items":{"$ref":"#/components/schemas/ConversionTriggerBulkWrite"}}},"additionalProperties":false}}}},"responses":{"201":{"description":"201","content":{"application/json":{"schema":{"type":"object","properties":{"conversionTriggers":{"type":"array","items":{"$ref":"#/components/schemas/ConversionTrigger"}}}}}}},"422":{"description":"422 -- api/3/conversionTrigger/bulk.php checks `!isset($body->conversionTriggers) || empty($body->conversionTriggers)` before calling the controller and throws ResultInvalidException on a missing or empty array, which api/3/index.php's dispatcher maps to 422, not 400."}},"deprecated":false,"x-internal":true},"put":{"summary":"Bulk-update conversion triggers","description":"Body must be in Ember Data RESTSerializer format, each item including its id. All-or-nothing: the whole batch is rolled back if any item fails.","operationId":"bulk-update-conversion-triggers","x-canonical-resource":"conversion_trigger","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conversionTriggers"],"properties":{"conversionTriggers":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/ConversionTriggerBulkWrite"},{"type":"object","required":["id"],"properties":{"id":{"type":"integer"}}}]}}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversionTriggers":{"type":"array","items":{"$ref":"#/components/schemas/ConversionTrigger"}}}}}}},"422":{"description":"422 -- api/3/conversionTrigger/bulk.php checks `!isset($body->conversionTriggers) || empty($body->conversionTriggers)` before calling the controller and throws ResultInvalidException on a missing or empty array, which api/3/index.php's dispatcher maps to 422, not 400."}},"deprecated":false,"x-internal":true}},"/conversionTriggers":{"get":{"summary":"List conversion triggers","description":"Lists the account's conversion triggers, 20 per page by default. The ConversionTrigger resource declares no filterable fields, so `filters[...]` and `orders[...]` parameters are ignored. Internal: not part of the public API.","operationId":"list-conversion-triggers","parameters":[{"name":"ids","in":"query","description":"Comma-separated list of conversion trigger ids to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return for each call. Default is 20; maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"A page of conversion triggers, with the total in meta.total","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggersListResponse"},"example":{"conversionTriggers":[{"id":12,"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you","dynamic":0,"retroactive":0,"segment_id":null,"meta":null,"cdate":"2026-10-01T09:15:00-05:00","udate":"2026-10-01T09:15:00-05:00"}],"meta":{"total":1}}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution, or the authenticated user cannot access the trigger."}},"x-canonical-resource":"conversion_trigger","x-internal":true},"post":{"summary":"Create a conversion trigger","description":"Creates a conversion trigger for an existing conversion. Retroactive processing starts after the save when `retroactive` is 1 (see the property), and creating a `segment` trigger schedules the cron that evaluates segment conversions. Internal: not part of the public API.","operationId":"create-a-conversion-trigger","requestBody":{"description":"A conversionTrigger object wrapping the trigger's fields.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerRequest"},"example":{"conversionTrigger":{"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you","dynamic":0,"retroactive":0}}}}},"responses":{"201":{"description":"The trigger was created and is returned with its new id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerResponse"},"example":{"conversionTrigger":{"id":12,"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you","dynamic":0,"retroactive":0,"segment_id":null,"meta":null,"cdate":"2026-10-01T09:15:00-05:00","udate":"2026-10-01T09:15:00-05:00"}}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution."}},"x-canonical-resource":"conversion_trigger","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/conversionTriggers/{id}":{"get":{"summary":"Retrieve a conversion trigger","description":"Retrieves one conversion trigger. Internal: not part of the public API.","operationId":"retrieve-a-conversion-trigger","parameters":[{"name":"id","in":"path","description":"Id of the conversion trigger.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The conversion trigger","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerResponse"},"example":{"conversionTrigger":{"id":12,"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you","dynamic":0,"retroactive":0,"segment_id":null,"meta":null,"cdate":"2026-10-01T09:15:00-05:00","udate":"2026-10-01T09:15:00-05:00"}}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution, or the authenticated user cannot access the trigger."},"404":{"description":"Not found. The trigger does not exist, or the conversion it belongs to is not visible."}},"x-canonical-resource":"conversion_trigger","x-internal":true},"put":{"summary":"Update a conversion trigger","description":"Updates a conversion trigger. PUT and PATCH behave the same: only the fields sent in the conversionTrigger object change, and the rest keep their values. Internal: not part of the public API.","operationId":"update-a-conversion-trigger","parameters":[{"name":"id","in":"path","description":"Id of the conversion trigger.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"A conversionTrigger object wrapping the fields to change.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerRequest"},"example":{"conversionTrigger":{"value":"/thank-you-2"}}}}},"responses":{"200":{"description":"The updated conversion trigger","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerResponse"},"example":{"conversionTrigger":{"id":12,"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you-2","dynamic":0,"retroactive":0,"segment_id":null,"meta":null,"cdate":"2026-10-01T09:15:00-05:00","udate":"2026-10-01T09:15:00-05:00"}}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution, or the authenticated user cannot access the trigger."},"404":{"description":"Not found. The trigger does not exist, or the conversion it belongs to is not visible."}},"x-canonical-resource":"conversion_trigger","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete a conversion trigger","description":"Deletes a conversion trigger. Deleting a `segment` trigger also removes its stored segment state and deletes its segment. Internal: not part of the public API.","operationId":"delete-a-conversion-trigger","parameters":[{"name":"id","in":"path","description":"Id of the conversion trigger.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The trigger was deleted. The body is an empty JSON object","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution, or the authenticated user cannot access the trigger."},"404":{"description":"Not found. The trigger does not exist, or the conversion it belongs to is not visible."}},"x-canonical-resource":"conversion_trigger","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Update a conversion trigger (PATCH)","description":"Updates a conversion trigger. PUT and PATCH behave the same: only the fields sent in the conversionTrigger object change, and the rest keep their values. Internal: not part of the public API.","operationId":"patch-a-conversion-trigger","parameters":[{"name":"id","in":"path","description":"Id of the conversion trigger.","required":true,"schema":{"type":"integer"}}],"requestBody":{"description":"A conversionTrigger object wrapping the fields to change.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerRequest"},"example":{"conversionTrigger":{"value":"/thank-you-2"}}}}},"responses":{"200":{"description":"The updated conversion trigger","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionTriggerResponse"},"example":{"conversionTrigger":{"id":12,"conversion":3,"triggerType":"url","modifier":"contains","value":"/thank-you-2","dynamic":0,"retroactive":0,"segment_id":null,"meta":null,"cdate":"2026-10-01T09:15:00-05:00","udate":"2026-10-01T09:15:00-05:00"}}}}},"403":{"description":"Forbidden. The account's plan does not include Attribution, or the authenticated user cannot access the trigger."},"404":{"description":"Not found. The trigger does not exist, or the conversion it belongs to is not visible."}},"x-canonical-resource":"conversion_trigger","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/conversions":{"get":{"summary":"List conversions","operationId":"list-conversions","x-canonical-resource":"conversion","parameters":[{"name":"search","in":"query","schema":{"type":"string"},"description":"Filters by conversion name, case-insensitive substring match."},{"name":"with_counts","in":"query","schema":{"type":"integer","enum":[0,1]},"description":"When 1, adds lifetime total/last-triggered counts to each conversion."},{"name":"is_required_by_goal","in":"query","schema":{"type":"integer","enum":[0,1]},"description":"When 1, adds is_required_by_goal and folder_ids to each conversion."}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversions":{"type":"array","items":{"$ref":"#/components/schemas/Conversion"}}}}}}}},"deprecated":false},"post":{"summary":"Create a conversion","operationId":"create-a-conversion","x-canonical-resource":"conversion","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conversion"],"properties":{"conversion":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Plain text only -- HTML tags are stripped server-side."},"value":{"type":"number","description":"Dollar value of a single conversion event. Stored as cents internally; this is the dollar amount."},"currency":{"type":"string"},"limit":{"type":"integer","description":"Max times a single contact may trigger this conversion. Only enforced when enforcelimit is 1."},"enforcelimit":{"type":"integer","enum":[0,1]},"value_option":{"type":"integer","description":"0 = no value, non-zero = has a dollar value option. Exact enum not fully confirmed."},"field_data":{"type":"string","nullable":true,"description":"Personalization-tag reference for a dynamic conversion value, format 'x::tagname'."}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversion":{"$ref":"#/components/schemas/Conversion"}}}}}}},"deprecated":false}},"/conversions/data":{"get":{"summary":"List conversion statistics","description":"Read-optimized conversion stats (counts, values, graph series), separate from GET /conversions. Backed by ConversionsService::fetchConversionData().","operationId":"list-conversions-data","x-canonical-resource":"conversion","parameters":[{"name":"ids","in":"query","schema":{"type":"string"},"description":"Comma-separated conversion IDs. Omit to return all conversions (paginated by limit/offset)."},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"}},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"}},{"name":"initiativeId","in":"query","schema":{"type":"integer"},"description":"Scopes backfill/goal/overlay data to this business goal. Required for include_backfill and include_graph_overlay to take effect."},{"name":"include_backfill","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"include_graph_overlay","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"include_total_and_avg","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"use_overview_config","in":"query","schema":{"type":"integer","enum":[0,1]},"description":"When 1, uses the account's saved Overview sort-order configuration instead of ids."},{"name":"limit","in":"query","schema":{"type":"integer","default":20}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"search","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversions":{"type":"array","items":{"$ref":"#/components/schemas/ConversionData"}}}}}}}},"deprecated":false}},"/conversions/labels":{"post":{"summary":"Create a conversion label","operationId":"create-a-conversion-label","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["conversionLabel"],"properties":{"conversionLabel":{"description":"The association to create.","required":["conversion","label"],"properties":{"conversion":{"description":"Conversion ID to associate.","type":"integer"},"label":{"description":"Folder (label) ID to associate.","type":"integer"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"Created, or the existing association if one for this conversion+label already exists","content":{"application/json":{"schema":{"oneOf":[{"properties":{"conversionLabel":{"$ref":"#/components/schemas/ConversionLabelEntry","description":"The conversion label association."}},"type":"object"},{"properties":{"message":{"description":"Says the conversion already carries the label; nothing was created.","type":"string","example":"ConversionFolder with conversion id 12 and folder id 3 already exists"}},"type":"object"}]}}}}},"deprecated":false,"x-canonical-resource":"conversion_label","x-destructive":false,"x-bulk-operation":false},"get":{"summary":"List conversion labels","description":"A 'conversion label' (ConversionFolder) is the association row between a conversion and a label/folder -- not the label itself.","operationId":"list-conversion-labels","parameters":[{"name":"include_conversions","in":"query","description":"1 adds the conversion's id, name, value and currency to each label (conversionId, conversionName, conversionValue, conversionCurrency).","required":false,"schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"conversionLabels":{"description":"The conversion label associations.","type":"array","items":{"$ref":"#/components/schemas/ConversionLabelEntry"}}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"conversion_label"}},"/conversions/labels/bulkCreate":{"post":{"summary":"Bulk-create conversion labels","operationId":"bulk-create-conversion-labels","requestBody":{"description":"A raw JSON array of conversion-label associations, not wrapped in a conversionLabels key. Full response shape not confirmed -- shares a generic bulkCreate() with other label-style resources in this codebase.","required":true,"content":{"application/json":{"schema":{"type":"array","items":{"required":["conversion","label"],"properties":{"conversion":{"description":"ID of the conversion to label.","type":"integer"},"label":{"description":"ID of the label (folder) to apply.","type":"integer"}},"type":"object"}}}}},"responses":{"200":{"description":"No labels were created -- the request was empty, or none of the supplied associations were valid","content":{"application/json":{"schema":{"required":["message","meta"],"properties":{"message":{"description":"What happened: No data provided for an empty body, or No valid labels provided when none of the associations could be created.","type":"string"},"errors":{"description":"Validation errors, if any; this field is omitted only for an empty request body.","type":"array","items":{"properties":{"index":{"description":"Position of the rejected association in the request array.","type":"integer"},"error":{"description":"Why the association was rejected.","type":"string"}},"type":"object"}},"meta":{"description":"Outcome of the request.","properties":{"success":{"description":"True when the body was empty or no association was rejected.","type":"boolean"}},"type":"object"}},"type":"object"}}}},"201":{"description":"Labels created successfully","content":{"application/json":{"schema":{"required":["message","added","errors","meta"],"properties":{"message":{"description":"Confirms the labels were created.","type":"string"},"added":{"description":"Number of associations created.","type":"integer"},"errors":{"description":"Associations that were rejected, one entry each; empty when all were valid.","type":"array","items":{"properties":{"index":{"description":"Position of the rejected association in the request array.","type":"integer"},"error":{"description":"Why the association was rejected.","type":"string"}},"type":"object"}},"meta":{"description":"Outcome of the request.","properties":{"success":{"description":"True when the labels were created.","type":"boolean"}},"type":"object"}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"conversion_label","x-destructive":false,"x-bulk-operation":true}},"/conversions/labels/bulkDelete":{"delete":{"summary":"Bulk-delete conversion labels","operationId":"bulk-delete-conversion-labels","parameters":[{"name":"ids","in":"query","description":"Comma-separated conversion-label (ConversionFolder) IDs.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"description":"Shape not fully confirmed -- shares a generic bulkDelete() with other label-style resources.","type":"object"}}}}},"deprecated":false,"x-canonical-resource":"conversion_label","x-destructive":true,"x-bulk-operation":true}},"/conversions/labels/target":{"put":{"summary":"Set a conversion's target for a business goal","operationId":"set-a-conversion-target","requestBody":{"content":{"application/json":{"schema":{"required":["conversionId","initiativeId"],"properties":{"conversionId":{"description":"ID of the conversion to set the target for.","type":"integer"},"initiativeId":{"description":"ID of the active business goal the target belongs to.","type":"integer"},"goalType":{"description":"1 = total conversion event count, 2 = total conversion revenue","type":"integer","enum":[1,2]},"goalValue":{"description":"Value of the target.","type":"integer"}},"type":"object"}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false}},"/conversions/labels/{id}":{"get":{"summary":"Retrieve a conversion label","operationId":"retrieve-a-conversion-label","parameters":[{"name":"id","in":"path","description":"ID of the conversion label association.","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"include_conversions","in":"query","description":"1 adds the conversion's id, name, value and currency to the label (conversionId, conversionName, conversionValue, conversionCurrency).","required":false,"schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"conversionLabel":{"$ref":"#/components/schemas/ConversionLabelEntry","description":"The conversion label association."}},"type":"object"}}}},"404":{"description":"Not found"}},"deprecated":false,"x-canonical-resource":"conversion_label"},"put":{"summary":"Update a conversion label","description":"The conversion and label association is immutable after creation -- only goalType, goalValue, and conversionTargetStatus may be updated. Attempting to change conversion or label returns 400.","operationId":"update-a-conversion-label","parameters":[{"name":"id","in":"path","description":"ID of the conversion label association to update.","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["conversionLabel"],"properties":{"conversionLabel":{"description":"The fields to change.","properties":{"goalType":{"description":"1 = total conversion event count, 2 = total conversion revenue","type":"integer","enum":[1,2]},"goalValue":{"description":"Value of the business-goal target.","type":"integer"},"conversionTargetStatus":{"description":"Progress of the target: 0 = not started, 1 = on track, 2 = needs attention, 3 = at risk.","type":"integer"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"conversionLabel":{"$ref":"#/components/schemas/ConversionLabelEntry","description":"The conversion label association."}},"type":"object"}}}},"400":{"description":"Attempted to change conversion or label"},"404":{"description":"Not found"}},"deprecated":false,"x-canonical-resource":"conversion_label","x-destructive":true,"x-bulk-operation":false},"delete":{"summary":"Delete a conversion label","operationId":"delete-a-conversion-label","parameters":[{"name":"id","in":"path","description":"ID of the conversion label association to delete.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Not found"}},"deprecated":false,"x-canonical-resource":"conversion_label","x-destructive":true,"x-bulk-operation":false}},"/conversions/labels/{id}/goal":{"delete":{"summary":"Disable a conversion label's business-goal target","description":"Same effect as DELETE /conversions/{conversionId}/goal/{initiativeId}/labels/target, addressed by conversion-label ID instead of the (conversionId, initiativeId) pair.","operationId":"disable-a-conversion-labels-target","parameters":[{"name":"id","in":"path","description":"ID of the conversion label association whose target to disable.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"message":{"description":"Confirms the target was deleted.","type":"string","example":"Conversion goal deleted successfully"}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false}},"/conversions/metrics":{"get":{"summary":"List conversion metrics","description":"Agent-oriented read: event count, unique contacts, and total value per conversion. Backed by ConversionAgentService::getConversionMetrics().","operationId":"list-conversion-metrics","parameters":[{"name":"date_from","in":"query","description":"First day of the period, YYYY-MM-DD. Send together with date_to; the range is at most 30 days.","schema":{"type":"string","format":"date"}},{"name":"date_to","in":"query","description":"date_from/date_to must both be provided for a custom range; max range 30 days.","schema":{"type":"string","format":"date"}},{"name":"search","in":"query","description":"Only conversions whose name contains this text.","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"conversions":{"description":"The metrics of each conversion.","type":"array","items":{"$ref":"#/components/schemas/ConversionMetricEntry"}}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"conversion"}},"/conversions/{conversionId}/goal/{initiativeId}/labels/target":{"delete":{"summary":"Disable a conversion's target for a business goal","operationId":"disable-a-conversion-target","parameters":[{"name":"conversionId","in":"path","description":"ID of the conversion whose target to disable.","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"initiativeId","in":"path","description":"ID of the business goal the target belongs to.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false}},"/conversions/{id}":{"get":{"summary":"Retrieve a conversion","operationId":"retrieve-a-conversion","x-canonical-resource":"conversion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversion":{"$ref":"#/components/schemas/Conversion"}}}}}},"404":{"description":"Not found"}},"deprecated":false},"put":{"summary":"Update a conversion","operationId":"update-a-conversion","x-canonical-resource":"conversion","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conversion"],"properties":{"conversion":{"type":"object","description":"All fields optional; only supplied fields are updated.","properties":{"name":{"type":"string"},"value":{"type":"number"},"currency":{"type":"string"},"limit":{"type":"integer"},"enforcelimit":{"type":"integer","enum":[0,1]},"value_option":{"type":"integer"},"field_data":{"type":"string","nullable":true}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversion":{"$ref":"#/components/schemas/Conversion"}}}}}},"404":{"description":"Not found"}},"deprecated":false},"delete":{"summary":"Delete a conversion","description":"Cascades: also deletes the conversion's triggers, contact-conversion records, and business-goal (ConversionFolder) associations.","operationId":"delete-a-conversion","x-canonical-resource":"conversion","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Not found"}},"deprecated":false},"patch":{"summary":"Update a conversion (PATCH)","operationId":"patch-a-conversion","x-canonical-resource":"conversion","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conversion"],"properties":{"conversion":{"type":"object","description":"All fields optional; only supplied fields are updated.","properties":{"name":{"type":"string"},"value":{"type":"number"},"currency":{"type":"string"},"limit":{"type":"integer"},"enforcelimit":{"type":"integer","enum":[0,1]},"value_option":{"type":"integer"},"field_data":{"type":"string","nullable":true}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversion":{"$ref":"#/components/schemas/Conversion"}}}}}},"404":{"description":"Not found"}},"deprecated":false,"description":"Identical to PUT /conversions/{id} -- ConversionController is routed for both PUT and PATCH to the same requestPut() handler."}},"/conversions/{id}/data":{"get":{"summary":"Retrieve a conversion's statistics","description":"Same shape as GET /conversions/data, scoped to a single conversion. Still returns the 'conversions' wrapper with a single-element array.","operationId":"retrieve-a-conversions-data","x-canonical-resource":"conversion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"}},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"}},{"name":"initiativeId","in":"query","schema":{"type":"integer"}},{"name":"include_backfill","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"include_graph_overlay","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"include_total_and_avg","in":"query","schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversions":{"type":"array","items":{"$ref":"#/components/schemas/ConversionData"}}}}}}},"404":{"description":"Not found"}},"deprecated":false}},"/conversions/{id}/metrics":{"get":{"summary":"Retrieve a conversion's metrics","operationId":"retrieve-a-conversions-metrics","x-canonical-resource":"conversion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"}},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"The metric object directly -- not wrapped in a 'conversion' or 'conversions' key. Returns {} if no data for the range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionMetric"}}}},"404":{"description":"Not found"}},"deprecated":false}},"/conversions/{id}/trends":{"get":{"summary":"Retrieve a conversion's daily trend data","description":"Daily time series of event count, unique contacts, and total value. Backed by ConversionAgentService::getConversionTrends().","operationId":"retrieve-a-conversions-trends","x-canonical-resource":"conversion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"date_from","in":"query","schema":{"type":"string","format":"date"},"description":"Optional; default window not fully confirmed. Max range 30 days."},{"name":"date_to","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"conversionId":{"type":"integer"},"conversionName":{"type":"string"},"dateFrom":{"type":"string","format":"date"},"dateTo":{"type":"string","format":"date"},"conversionValueOption":{"type":"string","enum":["count","revenue"]},"currency":{"type":"string","description":"Only present when conversionValueOption is 'revenue'."},"value":{"type":"number","description":"Only present when conversionValueOption is 'revenue'."},"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"eventCount":{"type":"integer"},"uniqueContacts":{"type":"integer"},"totalValue":{"type":"number","description":"Only present when conversionValueOption is 'revenue'."}}}}}}}}},"404":{"description":"Not found"}},"deprecated":false}},"/currencies":{"get":{"summary":"List currencies","description":"Every currency the app offers wherever an amount needs one, such as a deal value or a currency custom field, with its symbol and where the symbol goes. The list is fixed in the code and the same for every account; only the labels change, with the user's language. It is not paginated and takes no filters. The response carries `Cache-Control: max-age=86400, public`.","operationId":"list-all-currencies","responses":{"200":{"description":"All currencies, in the order the code lists them","content":{"application/json":{"schema":{"required":["currencies"],"properties":{"currencies":{"description":"The currencies","type":"array","items":{"$ref":"#/components/schemas/CurrencyResource"}}},"type":"object"},"example":{"currencies":[{"label":"US Dollar","symbol":"$","position":"f","sticky":true,"id":"usd"},{"label":"Euro","symbol":"€","position":"b","sticky":true,"id":"eur"}]}}}}},"x-canonical-resource":"currencies","x-internal":true}},"/currencies/{id}":{"get":{"summary":"Retrieve a currency","description":"One currency from GET /currencies, by its lowercase code. A code that is not in the list is not an error: the answer is still 200, with a `currency` that holds only the `id` that was asked for. The response carries `Cache-Control: max-age=86400, public`.","operationId":"get-currency","parameters":[{"name":"id","in":"path","description":"Lowercase three-letter ISO 4217 code, such as `usd`. Matching is case-sensitive: `USD` matches nothing.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The currency, or only its `id` when the code is not in the list","content":{"application/json":{"schema":{"required":["currency"],"properties":{"currency":{"$ref":"#/components/schemas/CurrencyResource"}},"type":"object"},"examples":{"known":{"summary":"A code in the list","value":{"currency":{"label":"US Dollar","symbol":"$","position":"f","sticky":true,"id":"usd"}}},"unknown":{"summary":"A code not in the list, here USD in upper case","value":{"currency":{"id":"USD"}}}}}}}},"x-canonical-resource":"currencies","x-internal":true}},"/customObjects/records/{schemaId}":{"get":{"summary":"List records by schema","description":"","operationId":"list-records-created-from-a-schema","x-canonical-resource":"custom_object_record","parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true},{"name":"limit","in":"query","description":"The number of records to return for each call. Maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return","schema":{"type":"integer","format":"int32","default":0}},{"name":"filters","in":"query","description":"Use ?filters[relationships.{your-contact-relationship}][eq]={contactId} to filter records to a specific contact.","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"200":{"value":"{\n  \"records\": [\n    {\n      \"id\": \"1fba439a-208e-48e6-bd23-f6c97c3e0519\",\n      \"externalId\": \"test-obj-1\",\n      \"schemaId\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n      \"fields\": [\n        {\n          \"id\": \"my-number-field\",\n          \"value\": 100\n        }\n      ],\n      \"relationships\": {\n        \"primary-contact\": [\n          \"14\"\n        ]\n      },\n      \"createdTimestamp\": \"2021-04-16T16:12:22.222685095Z\",\n      \"updatedTimestamp\": \"2021-04-16T16:13:12.022671090Z\"\n    }\n  ],\n  \"meta\": {\n    \"total\": 1,\n    \"count\": 1,\n    \"limit\": 20,\n    \"offset\": 0\n  }\n}\n"}},"schema":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"1fba439a-208e-48e6-bd23-f6c97c3e0519"},"externalId":{"type":"string","example":"test-obj-1"},"schemaId":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"value":{"type":"integer","example":100,"default":0}}}},"relationships":{"type":"object","properties":{"primary-contact":{"type":"array","items":{"type":"string","example":"14"}}}},"createdTimestamp":{"type":"string","example":"2021-04-16T16:12:22.222685095Z"},"updatedTimestamp":{"type":"string","example":"2021-04-16T16:13:12.022671090Z"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"default":0},"count":{"type":"integer","example":1,"default":0},"limit":{"type":"integer","example":20,"default":0},"offset":{"type":"integer","example":0,"default":0}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\":400,\n      \"title\":\"Bad Request\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"Not Found\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Not Found"}}}}}}},"deprecated":false},"post":{"summary":"Create or update record","description":"","operationId":"create-or-update-record","x-canonical-resource":"custom_object_record","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"record":{"properties":{"id":{"type":"string","description":"The Record's id"},"externalId":{"type":"string","description":"The Record's external id"},"fields":{"type":"array","items":{"properties":{"id":{"type":"string","description":"id of the field"},"value":{"type":["string","number","boolean","array"],"items":{"type":"string"},"description":"Value in the field's own type: a number for number and currency fields, a string for text and date fields, an array of strings for multiselect fields"}},"type":"object"}},"relationships":{"type":"object","description":"Related records, keyed by the relationship id defined in the schema (for example primary-contact, account or deal). Each value is a list of record IDs.","additionalProperties":{"type":"array","items":{"type":"integer","format":"int32"}},"properties":{"primary-contact":{"type":"array","description":"List of Contact integers","default":[],"items":{"type":"integer","format":"int32"}}}}},"required":[],"type":"object"}}},"examples":{"Create with Contact":{"value":{"record":{"schemaId":"6449c3f3-b68d-46d1-850b-c8aea998ce1b","id":"test-obj-1","externalId":"test-obj-1","fields":[{"id":"my-number-field","value":100}],"relationships":{"primary-contact":[14]}}}},"Create with Deal":{"value":{"record":{"schemaId":"6449c3f3-b68d-46d1-850b-c8aea998ce1b","id":"test-obj-1","externalId":"test-obj-1","fields":[{"id":"my-number-field","value":100}],"relationships":{"deal":[22]}}}},"Create with Account":{"value":{"record":{"schemaId":"6449c3f3-b68d-46d1-850b-c8aea998ce1b","id":"test-obj-1","externalId":"test-obj-1","fields":[{"id":"my-number-field","value":100}],"relationships":{"account":[123]}}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"record\": {\n    \t\"id\": \"test-obj-1\",\n    \t\"externalId\": \"test-obj-1\",\n        \"schemaId\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n        \"fields\": [\n            {\n                \"id\": \"my-number-field\",\n                \"value\": 100\n            }\n        ],\n        \"relationships\": {\n            \"account\": [123]\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"record":{"type":"object","properties":{"id":{"type":"string","example":"test-obj-1"},"externalId":{"type":"string","example":"test-obj-1"},"schemaId":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"value":{"type":"integer","example":100,"default":0}}}},"relationships":{"type":"object","properties":{"account":{"type":"array","items":{"type":"integer","example":123,"default":0}}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\"errors\":[{\"status\":400,\"title\":\"Bad Request\"}]}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}},"422":{"description":"422","content":{"text/plain":{"examples":{"invalid field value":{"value":"{\n  \"errors\": [\n    {\n      \"title\": \"Invalid value for field \\\"{field_name}\\\"\",\n      \"detail\": \"{field_name} cannot accept a value that is not defined in the schema.\",\n      \"source\": {\n        \"type\": \"pointer\",\n        \"value\": \"/data/attributes/{field_name}\"\n      }\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"Invalid value for field \"{field_name}\""},"detail":{"type":"string","example":"{field_name} cannot accept a value that is not defined in the schema."},"source":{"type":"object","properties":{"type":{"type":"string","example":"pointer"},"value":{"type":"string","example":"/data/attributes/{field_name}"}}}}}}}}}}}},"deprecated":false}},"/customObjects/records/{schemaId}/external/{externalId}":{"delete":{"summary":"Delete a record by external ID","description":"","operationId":"delete-a-record-by-external-id","x-canonical-resource":"custom_object_record","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true},{"name":"externalId","in":"path","description":"External ID of record","schema":{"type":"string"},"required":true}],"responses":{"202":{"description":"202","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\":400,\n      \"title\":\"Bad Request\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}}},"deprecated":false},"get":{"summary":"Get a record by external id","description":"","operationId":"get-a-single-record-using-external-id","x-canonical-resource":"custom_object_record","parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true},{"name":"externalId","in":"path","description":"External ID for record","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"record\": {\n        \"id\": \"1fba439a-208e-48e6-bd23-f6c97c3e0519\",\n        \"externalId\": \"test-obj-1\",\n        \"schemaId\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n        \"fields\": [\n            {\n                \"id\": \"my-number-field\",\n                \"value\": 100\n            }\n        ],\n        \"relationships\": {\n            \"primary-contact\": [\n                \"14\"\n            ]\n        },\n        \"createdTimestamp\": \"2021-04-16T16:12:22.222685095Z\",\n        \"updatedTimestamp\": \"2021-04-16T16:13:12.022671090Z\"\n    }\n}"}},"schema":{"type":"object","properties":{"record":{"type":"object","properties":{"id":{"type":"string","example":"1fba439a-208e-48e6-bd23-f6c97c3e0519"},"externalId":{"type":"string","example":"test-obj-1"},"schemaId":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"value":{"type":"integer","example":100,"default":0}}}},"relationships":{"type":"object","properties":{"primary-contact":{"type":"array","items":{"type":"string","example":"14"}}}},"createdTimestamp":{"type":"string","example":"2021-04-16T16:12:22.222685095Z"},"updatedTimestamp":{"type":"string","example":"2021-04-16T16:13:12.022671090Z"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\":400,\n      \"title\":\"Bad Request\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}}},"deprecated":false}},"/customObjects/records/{schemaId}/{recordId}":{"get":{"summary":"Get a record by id","description":"","operationId":"get-a-single-record","x-canonical-resource":"custom_object_record","parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true},{"name":"recordId","in":"path","description":"ID of record","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Success":{"value":"{\n    \"record\": {\n        \"id\": \"1fba439a-208e-48e6-bd23-f6c97c3e0519\",\n        \"externalId\": \"test-obj-1\",\n        \"schemaId\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n        \"fields\": [\n            {\n                \"id\": \"my-number-field\",\n                \"value\": 100\n            }\n        ],\n        \"relationships\": {\n            \"primary-contact\": [\n                \"14\"\n            ]\n        },\n        \"createdTimestamp\": \"2021-04-16T16:12:22.222685095Z\",\n        \"updatedTimestamp\": \"2021-04-16T16:13:12.022671090Z\"\n    }\n}"}},"schema":{"type":"object","properties":{"record":{"type":"object","properties":{"id":{"type":"string","example":"1fba439a-208e-48e6-bd23-f6c97c3e0519"},"externalId":{"type":"string","example":"test-obj-1"},"schemaId":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"value":{"type":"integer","example":100,"default":0}}}},"relationships":{"type":"object","properties":{"primary-contact":{"type":"array","items":{"type":"string","example":"14"}}}},"createdTimestamp":{"type":"string","example":"2021-04-16T16:12:22.222685095Z"},"updatedTimestamp":{"type":"string","example":"2021-04-16T16:13:12.022671090Z"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\":400,\n      \"title\":\"Bad Request\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a record by id","description":"","operationId":"delete-a-record","x-canonical-resource":"custom_object_record","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"schemaId","in":"path","description":"ID of schema","schema":{"type":"string"},"required":true},{"name":"recordId","in":"path","description":"ID of record","schema":{"type":"string"},"required":true}],"responses":{"202":{"description":"202","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"status\":400,\n      \"title\":\"Bad Request\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":400,"default":0},"title":{"type":"string","example":"Bad Request"}}}}}}}}}},"deprecated":false}},"/customObjects/schemas":{"get":{"summary":"List all schemas","description":"Retrieve all schemas available within an account.\n\nUsers are encouraged to leverage the `?showFields=all` query parameter when programmatically creating new schema fields, to ensure field id uniqueness. Fields that have been deleted will contain a `status: marked_for_deletion` attribute.","operationId":"list-all-schemas","x-canonical-resource":"custom_object_schema","parameters":[{"name":"limit","in":"query","description":"The number of schemas to retrieve for each API call. Maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of items to return","schema":{"type":"integer","format":"int32","default":0}},{"name":"orders","in":"query","description":"Array of sorting criteria to fetch items","schema":{"type":"array","items":{"type":"string"}}},{"name":"filters","in":"query","description":"Filters schemas by different criteria","schema":{"type":"string"}},{"name":"showFields","in":"query","description":"Toggle which fields are shown in the response body of a schema (if there hidden due to e.g. recently being deleted). Omit this parameter entirely to hide fields by default.","schema":{"type":"string","default":"all"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"schemas\": [\n    {\n      \"id\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n      \"slug\": \"my-object\",\n      \"visibility\": \"private\",\n      \"labels\": {\n        \"singular\": \"My Object\",\n        \"plural\": \"My Objects\"\n      },\n      \"description\": \"Sample Schema\",\n      \"createdTimestamp\": \"2021-04-16T15:08:25.783751329Z\",\n      \"updatedTimestamp\": \"2021-04-16T15:08:25.783751329Z\",\n      \"fields\": [\n        {\n          \"id\": \"my-number-field\",\n          \"labels\": {\n            \"singular\": \"Number\",\n            \"plural\": \"Numbers\"\n          },\n          \"type\": \"number\",\n          \"required\": false,\n          \"scale\": 0\n        }\n      ],\n      \"icons\": {\n        \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n      },\n      \"relationships\": [\n        {\n          \"id\": \"primary-contact\",\n          \"labels\": {\n            \"singular\": \"Primary Contact\",\n            \"plural\": \"Primary Contacts\"\n          },\n          \"description\": \"Primary contact to this object\",\n          \"namespace\": \"contacts\",\n          \"hasMany\": false\n        }\n      ]\n    }\n  ],\n  \"meta\": {\n    \"total\": 1,\n    \"count\": 1,\n    \"limit\": 20,\n    \"offset\": 0\n  }\n}\n"}},"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"slug":{"type":"string","example":"my-object"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"My Object"},"plural":{"type":"string","example":"My Objects"}}},"description":{"type":"string","example":"Sample Schema"},"createdTimestamp":{"type":"string","example":"2021-04-16T15:08:25.783751329Z"},"updatedTimestamp":{"type":"string","example":"2021-04-16T15:08:25.783751329Z"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Number"},"plural":{"type":"string","example":"Numbers"}}},"type":{"type":"string","example":"number"},"required":{"type":"boolean","example":false,"default":true},"scale":{"type":"integer","example":0,"default":0}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact to this object"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true}}}}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"default":0},"count":{"type":"integer","example":1,"default":0},"limit":{"type":"integer","example":20,"default":0},"offset":{"type":"integer","example":0,"default":0}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"post":{"summary":"Create a schema","description":"","operationId":"create-a-schema","x-canonical-resource":"custom_object_schema","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"properties":{"slug":{"type":"string"},"labels":{"properties":{"singular":{"type":"string","description":"Singular label for Schema"},"plural":{"type":"string","description":"Plural label for Schema"}},"required":[],"type":"object"},"description":{"type":"string","description":"Description of the Schema"},"fields":{"type":"array","description":"List of Schema fields","items":{"properties":{"id":{"type":"string"},"slug":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"type":{"type":"string"},"scale":{"type":"integer","format":"int32"},"isRequired":{"type":"boolean"}},"type":"object"}},"relationships":{"type":"array","items":{"properties":{"id":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"description":{"type":"string"},"namespace":{"type":"string"},"hasMany":{"type":"boolean"}},"type":"object"}}},"required":[],"type":"object"}}},"examples":{"A single field with a relationship to the contact":{"value":{"schema":{"slug":"my-object","labels":{"singular":"My Object","plural":"My Objects"},"description":"Sample Schema","fields":[{"id":"my-number-field","labels":{"singular":"Number","plural":"Numbers"},"type":"number","required":false,"scale":0}],"relationships":[{"id":"primary-contact","labels":{"singular":"Primary Contact","plural":"Primary Contacts"},"description":"Primary contact to this object","namespace":"contacts","hasMany":false}]}}},"A single field with a relationship to an account":{"value":{"schema":{"slug":"my-object","labels":{"singular":"My Object","plural":"My Objects"},"description":"Sample Schema","fields":[{"id":"my-number-field","labels":{"singular":"Number","plural":"Numbers"},"type":"number","required":false,"scale":0}],"relationships":[{"id":"account","labels":{"singular":"Account","plural":"Accounts"},"description":"Accounts related to this object","namespace":"accounts","hasMany":false}]}}},"A single field with a relationship to a deal":{"value":{"schema":{"slug":"my-object","labels":{"singular":"My Object","plural":"My Objects"},"description":"Sample Schema","fields":[{"id":"my-number-field","labels":{"singular":"Number","plural":"Numbers"},"type":"number","required":false,"scale":0}],"relationships":[{"id":"deal","labels":{"singular":"Deal","plural":"Deals"},"description":"Deals related to this object","namespace":"deals","hasMany":false}]}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"schema\": {\n        \"id\": \"2123028c-64e6-40e2-97bc-9d63a2ca920b\",\n        \"slug\": \"my-object\",\n        \"visibility\": \"private\",\n        \"labels\": {\n            \"singular\": \"My Object\",\n            \"plural\": \"My Objects\"\n        },\n        \"description\": \"Sample Schema\",\n        \"createdTimestamp\": \"2021-03-19T18:23:17.153996399Z\",\n        \"updatedTimestamp\": \"2021-03-19T18:23:17.153996399Z\",\n        \"fields\": [{\n            \"id\": \"my-number-field\",\n            \"labels\": {\n                \"singular\": \"Number\",\n                \"plural\": \"Numbers\"\n            },\n            \"type\": \"number\",\n            \"required\": false,\n            \"scale\": 0\n        }],\n        \"icons\": {\n            \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n        },\n        \"relationships\": [{\n            \"id\": \"primary-contact\",\n            \"labels\": {\n                \"singular\": \"Primary Contact\",\n                \"plural\": \"Primary Contacts\"\n            },\n            \"description\": \"Primary contact to this object\",\n            \"namespace\": \"contacts\",\n            \"hasMany\": false\n        }]\n    }\n}"}},"schema":{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"2123028c-64e6-40e2-97bc-9d63a2ca920b"},"slug":{"type":"string","example":"my-object"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"My Object"},"plural":{"type":"string","example":"My Objects"}}},"description":{"type":"string","example":"Sample Schema"},"createdTimestamp":{"type":"string","example":"2021-03-19T18:23:17.153996399Z"},"updatedTimestamp":{"type":"string","example":"2021-03-19T18:23:17.153996399Z"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Number"},"plural":{"type":"string","example":"Numbers"}}},"type":{"type":"string","example":"number"},"required":{"type":"boolean","example":false,"default":true},"scale":{"type":"integer","example":0,"default":0}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact to this object"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true}}}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"invalid field value":{"value":"{\n  \"errors\": [\n    {\n      \"title\": \"Invalid value for field \\\"schema.fields.labels\\\"\",\n      \"detail\": \"Schema fields must provide labels\",\n      \"source\": {\n        \"type\": \"pointer\",\n        \"value\": \"/data/attributes/schema/fields/labels\"\n      }\n    }\n  ]\n}"},"slug conflict":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"Invalid value for field \\\"schema.slug\\\"\",\n            \"detail\": \"Schema slug must be unique\",\n            \"source\": {\n                \"type\": \"pointer\",\n                \"value\": \"/data/attributes/schema/slug\"\n            }\n        }\n    ]\n}"}},"schema":{"oneOf":[{"title":"invalid field value","type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"Invalid value for field \"schema.fields.labels\""},"detail":{"type":"string","example":"Schema fields must provide labels"},"source":{"type":"object","properties":{"type":{"type":"string","example":"pointer"},"value":{"type":"string","example":"/data/attributes/schema/fields/labels"}}}}}}}},{"title":"slug conflict","type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"Invalid value for field \"schema.slug\""},"detail":{"type":"string","example":"Schema slug must be unique"},"source":{"type":"object","properties":{"type":{"type":"string","example":"pointer"},"value":{"type":"string","example":"/data/attributes/schema/slug"}}}}}}}}]}}}}},"deprecated":false}},"/customObjects/schemas/public":{"post":{"summary":"Create a public schema","description":"","operationId":"create-a-public-schema","x-canonical-resource":"custom_object_schema","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"properties":{"slug":{"type":"string"},"appId":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"description":{"type":"string"},"fields":{"type":"array","items":{"properties":{"id":{"type":"string"},"slug":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"type":{"type":"string"},"scale":{"type":"integer","format":"int32"},"isRequired":{"type":"boolean"}},"type":"object"}},"relationships":{"type":"array","items":{"properties":{"id":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"description":{"type":"string"},"namespace":{"type":"string"},"hasMany":{"type":"boolean"}},"type":"object"}}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"schema":{"slug":"event-tickets","appId":"cxapp-studio-app-id","labels":{"singular":"Event Ticket","plural":"Event Tickets"},"description":"Event Tickets","fields":[{"id":"name","labels":{"singular":"Name","plural":"Names"},"type":"textarea"}],"relationships":[{"id":"primary-contact","labels":{"singular":"Primary Contact","plural":"Primary Contacts"},"description":"Primary contact that owns a ticket","namespace":"contacts"}]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"schema\": {\n    \"id\": \"230f6065-a8e5-4df2-a70a-f6832d004d8d\",\n    \"slug\": \"app-230f6065-a8e5-4df2-a70a-f6832d004d8d-event-tickets\",\n    \"visibility\": \"public\",\n    \"labels\": {\"singular\": \"Event Ticket\", \"plural\": \"Event Tickets\"},\n    \"description\": \"Event Tickets\",\n    \"appId\": \"cxapp-studio-app-id\",\n    \"fields\": [\n        {\n            \"id\": \"name\",\n            \"labels\": {\"singular\": \"Name\", \"plural\": \"Names\"},\n            \"type\": \"textarea\"\n        }\n    ],\n    \"relationships\": [\n      {\n        \"id\": \"primary-contact\",\n        \"labels\": {\n          \"singular\": \"Primary Contact\",\n          \"plural\": \"Primary Contacts\"\n        },\n        \"description\": \"Primary contact that owns a ticket\",\n        \"namespace\": \"contacts\",\n        \"hasMany\": false,\n        \"inherited\": false\n      }\n    ],\n    \"icons\": {\n        \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n    }\n  }\n}"}},"schema":{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"230f6065-a8e5-4df2-a70a-f6832d004d8d"},"slug":{"type":"string","example":"app-230f6065-a8e5-4df2-a70a-f6832d004d8d-event-tickets"},"visibility":{"type":"string","example":"public"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Event Ticket"},"plural":{"type":"string","example":"Event Tickets"}}},"description":{"type":"string","example":"Event Tickets"},"appId":{"type":"string","example":"cxapp-studio-app-id"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"name"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Name"},"plural":{"type":"string","example":"Names"}}},"type":{"type":"string","example":"textarea"}}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact that owns a ticket"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true},"inherited":{"type":"boolean","example":false,"default":true}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/customObjects/schemas/{id}":{"get":{"summary":"Retrieve a schema","description":"Retrieve a specific schema by id.\n\nUsers are encouraged to leverage the `?showFields=all` query parameter when programmatically creating new schema fields, to ensure field id uniqueness. Fields that have been deleted will contain a `status: marked_for_deletion` attribute.","operationId":"retrieve-a-schema","x-canonical-resource":"custom_object_schema","parameters":[{"name":"id","in":"path","description":"Id of the Schema","schema":{"type":"string"},"required":true},{"name":"showFields","in":"query","description":"Toggle which fields are shown in the response body of a schema (if there hidden due to e.g. recently being deleted). Omit this parameter entirely to hide fields by default.","schema":{"type":"string","default":"all"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"schema\": {\n    \"id\": \"6449c3f3-b68d-46d1-850b-c8aea998ce1b\",\n    \"slug\": \"my-object\",\n    \"visibility\": \"private\",\n    \"labels\": {\n      \"singular\": \"My Object\",\n      \"plural\": \"My Objects\"\n    },\n    \"description\": \"Sample Schema\",\n    \"createdTimestamp\": \"2021-04-16T15:08:25.783751329Z\",\n    \"updatedTimestamp\": \"2021-04-16T15:08:25.783751329Z\",\n    \"fields\": [\n      {\n        \"id\": \"my-number-field\",\n        \"labels\": {\n          \"singular\": \"Number\",\n          \"plural\": \"Numbers\"\n        },\n        \"type\": \"number\",\n        \"required\": false,\n        \"scale\": 0\n      }\n    ],\n    \"icons\": {\n      \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n    },\n    \"relationships\": [\n      {\n        \"id\": \"primary-contact\",\n        \"labels\": {\n          \"singular\": \"Primary Contact\",\n          \"plural\": \"Primary Contacts\"\n        },\n        \"description\": \"Primary contact to this object\",\n        \"namespace\": \"contacts\",\n        \"hasMany\": false\n      }\n    ]\n  }\n}"}},"schema":{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"6449c3f3-b68d-46d1-850b-c8aea998ce1b"},"slug":{"type":"string","example":"my-object"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"My Object"},"plural":{"type":"string","example":"My Objects"}}},"description":{"type":"string","example":"Sample Schema"},"createdTimestamp":{"type":"string","example":"2021-04-16T15:08:25.783751329Z"},"updatedTimestamp":{"type":"string","example":"2021-04-16T15:08:25.783751329Z"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Number"},"plural":{"type":"string","example":"Numbers"}}},"type":{"type":"string","example":"number"},"required":{"type":"boolean","example":false,"default":true},"scale":{"type":"integer","example":0,"default":0}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact to this object"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true}}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"Not Found\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Not Found"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a schema","description":"","operationId":"delete-a-schema","x-canonical-resource":"custom_object_schema","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of schema to delete","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"Not Found\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Not Found"}}}}}}},"deprecated":false}},"/customObjects/schemas/{id}/child":{"post":{"summary":"Create a child schema","description":"","operationId":"create-a-child-schema","x-canonical-resource":"custom_object_schema","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of the parent schema the new child schema will extend","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"schema\": {\n    \"id\": \"475c4ea7-65cc-4d59-a690-6ac232633fca\",\n    \"parentId\": \"230f6065-a8e5-4df2-a70a-f6832d004d8d\",\n    \"slug\": \"app-cxapp-studio-app-id-event-tickets\",\n    \"appId\": \"cxapp-studio-app-id\",\n    \"visibility\": \"private\",\n    \"labels\": {\"singular\": \"Event Ticket\", \"plural\": \"Event Tickets\"},\n    \"description\": \"Event Tickets\",\n    \"fields\": [\n        {\n            \"id\": \"name\",\n            \"labels\": {\"singular\": \"Name\", \"plural\": \"Names\"},\n            \"type\": \"textarea\",\n            \"inherited\": true\n        }\n    ],\n    \"relationships\": [\n      {\n        \"id\": \"primary-contact\",\n        \"labels\": {\n          \"singular\": \"Primary Contact\",\n          \"plural\": \"Primary Contacts\"\n        },\n        \"description\": \"Primary contact that owns a ticket\",\n        \"namespace\": \"contacts\",\n        \"inherited\": true\n      }\n    ],\n    \"icons\": {\n        \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n    }\n  }\n}"}},"schema":{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"475c4ea7-65cc-4d59-a690-6ac232633fca"},"parentId":{"type":"string","example":"230f6065-a8e5-4df2-a70a-f6832d004d8d"},"slug":{"type":"string","example":"app-cxapp-studio-app-id-event-tickets"},"appId":{"type":"string","example":"cxapp-studio-app-id"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Event Ticket"},"plural":{"type":"string","example":"Event Tickets"}}},"description":{"type":"string","example":"Event Tickets"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"name"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Name"},"plural":{"type":"string","example":"Names"}}},"type":{"type":"string","example":"textarea"},"inherited":{"type":"boolean","example":true,"default":true}}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact that owns a ticket"},"namespace":{"type":"string","example":"contacts"},"inherited":{"type":"boolean","example":true,"default":true}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/customObjects/schemas/{schemaId}":{"put":{"summary":"Update a schema","description":"Make an update to a given schema.\n\nTo delete a schema field, reference the field delete endpoint: https://developers.activecampaign.com/reference/delete-a-field-1\n\nUsers are encouraged to leverage the `?showFields=all` query parameter when programmatically creating new schema fields, to ensure field id uniqueness. Fields that have been deleted will contain a `status: marked_for_deletion` attribute.","operationId":"update-a-schema","x-canonical-resource":"custom_object_schema","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"schemaId","in":"path","description":"Id of Schema being updated","schema":{"type":"string"},"required":true},{"name":"validateOnly","in":"header","description":"When set to `true` the API will validate the schema update without saving changes","schema":{"type":"boolean","default":false}},{"name":"showFields","in":"query","description":"Toggle which fields are shown in the response body of a schema (if there hidden due to e.g. recently being deleted). Omit this parameter entirely to hide fields by default.","schema":{"type":"string","default":"all"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"properties":{"slug":{"type":"string"},"labels":{"properties":{"singular":{"type":"string","description":"Singular label for Schema"},"plural":{"type":"string","description":"Plural label for Schema"}},"required":[],"type":"object"},"description":{"type":"string","description":"Text description of the Schema"},"appId":{"type":"string"},"fields":{"type":"array","items":{"properties":{"id":{"type":"string","description":"id of the field"},"value":{"type":"string","description":"Data type, appropriate for the field"}},"type":"object"}},"icons":{"properties":{"default":{"type":"string","description":"URI location of the default icon shown on Schema"}},"required":[],"type":"object"},"relationships":{"type":"object","properties":{"id":{"type":"string"},"labels":{"type":"object","properties":{"singular":{"type":"string","description":"human-readable singular name"},"plural":{"type":"string","description":"human-readable plural name"}}},"description":{"type":"string"},"namespace":{"type":"string"},"hasMany":{"type":"boolean"}}}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"schema":{"slug":"stripe-order","labels":{"singular":"Stripe Order","plural":"Stripe Orders"},"description":"Orders placed through the Stripe integration","appId":"123456","fields":[{"id":"name","labels":{"singular":"Product Name","plural":"Product Name"},"description":"Name of the product from the Stripe integration","isRequired":true,"origin":"stripe","type":"text"},{"id":"total","labels":{"singular":"Order Total","plural":"Order Totals"},"description":"Total cost of the order","isRequired":true,"origin":"stripe","type":"currency","defaultCurrency":"USD"},{"id":"status","labels":{"singular":"Order Status","plural":"Order Statuses"},"description":"Status of the order","isRequired":true,"origin":"stripe","type":"dropdown","options":[{"value":"Processed"}]},{"id":"features","labels":{"singular":"Order Feature","plural":"Order Features"},"description":"Extra features for the order","isRequired":true,"origin":"stripe","type":"multiselect","options":[{"value":"Expedited Shipping"}]},{"id":"rating","labels":{"singular":"Order Rating","plural":"Order Ratings"},"description":"Customer satisfaction rating","isRequired":true,"origin":"stripe","type":"decimal","scale":2}],"icons":{"default":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"},"relationships":[{"id":"primary-contact","labels":{"singular":"Primary Contact","plural":"Primary Contacts"},"description":"Products purchased in this Stripe order","namespace":"contacts","hasMany":false}]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"schema\": {\n    \"id\": \"schema-9999-9999\",\n    \"slug\": \"stripe-order\",\n    \"labels\": {\n      \"singular\": \"Stripe Order\",\n      \"plural\": \"Stripe Orders\"\n    },\n    \"description\": \"Orders placed through the Stripe integration\",\n    \"appId\": \"123456\",\n    \"fields\": [\n      {\n        \"id\": \"name\",\n        \"labels\": {\n          \"singular\": \"Product Name\",\n          \"plural\": \"Product Name\"\n        },\n        \"description\": \"Name of the product from the Stripe integration\",\n        \"isRequired\": true,\n        \"origin\": \"stripe\",\n        \"type\": \"text\"\n      },\n      {\n        \"id\": \"total\",\n        \"labels\": {\n          \"singular\": \"Order Total\",\n          \"plural\": \"Order Totals\"\n        },\n        \"description\": \"Total cost of the order\",\n        \"isRequired\": true,\n        \"origin\": \"stripe\",\n        \"type\": \"currency\",\n        \"defaultCurrency\": \"USD\"\n      },\n      {\n        \"id\": \"status\",\n        \"labels\": {\n          \"singular\": \"Order Status\",\n          \"plural\": \"Order Statuses\"\n        },\n        \"description\": \"Status of the order\",\n        \"isRequired\": true,\n        \"origin\": \"stripe\",\n        \"type\": \"dropdown\",\n        \"options\": [\n          {\n            \"id\": \"264d3b73-069e-4ca1-b270-dbfa3137b541\",\n            \"value\": \"Processed\"\n          }\n        ]\n      },\n      {\n        \"id\": \"features\",\n        \"labels\": {\n          \"singular\": \"Order Feature\",\n          \"plural\": \"Order Features\"\n        },\n        \"description\": \"Extra features for the order\",\n        \"isRequired\": true,\n        \"origin\": \"stripe\",\n        \"type\": \"multiselect\",\n        \"options\": [\n          {\n            \"id\": \"041ef416-a85b-678f-4a15-5dd481dad123\",\n            \"value\": \"Expedited Shipping\"\n          }\n        ]\n      },\n      {\n        \"id\": \"rating\",\n        \"labels\": {\n          \"singular\": \"Order Rating\",\n          \"plural\": \"Order Ratings\"\n        },\n        \"description\": \"Customer satisfaction rating\",\n        \"isRequired\": true,\n        \"origin\": \"stripe\",\n        \"type\": \"decimal\",\n        \"scale\": 2\n      }\n    ],\n    \"icons\": {\n      \"default\": \"https://activehosted.com/temp-placeholder.svg\"\n    },\n    \"relationships\": [\n      {\n        \"id\": \"primary-contact\",\n        \"labels\": {\n          \"singular\": \"Primary Contact\",\n          \"plural\": \"Primary Contacts\"\n        },\n        \"description\": \"Products purchased in this Stripe order\",\n        \"namespace\": \"contacts\",\n        \"hasMany\": false\n      }\n    ],\n    \"createdTimestamp\": \"2021-04-13T21:12:53.390Z\",\n    \"updatedTimestamp\": \"2021-04-13T21:12:53.390Z\"\n  }\n}"}},"schema":{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"schema-9999-9999"},"slug":{"type":"string","example":"stripe-order"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Stripe Order"},"plural":{"type":"string","example":"Stripe Orders"}}},"description":{"type":"string","example":"Orders placed through the Stripe integration"},"appId":{"type":"string","example":"123456"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"name"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Product Name"},"plural":{"type":"string","example":"Product Name"}}},"description":{"type":"string","example":"Name of the product from the Stripe integration"},"isRequired":{"type":"boolean","example":true,"default":true},"origin":{"type":"string","example":"stripe"},"type":{"type":"string","example":"text"}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://activehosted.com/temp-placeholder.svg"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Products purchased in this Stripe order"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true}}}},"createdTimestamp":{"type":"string","example":"2021-04-13T21:12:53.390Z"},"updatedTimestamp":{"type":"string","example":"2021-04-13T21:12:53.390Z"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"errors\": [\n    {\n      \"title\": \"Invalid value for field \\\"{field_name}\\\"\",\n      \"detail\": \"{description}\",\n      \"source\": {\n        \"type\": \"pointer\",\n        \"value\": \"/data/attributes/{field_name}\"\n      }\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"Invalid value for field \"{field_name}\""},"detail":{"type":"string","example":"{description}"},"source":{"type":"object","properties":{"type":{"type":"string","example":"pointer"},"value":{"type":"string","example":"/data/attributes/{field_name}"}}}}}}}}}}}},"deprecated":false}},"/customObjects/schemas/{schemaId}/fields/{fieldId}":{"delete":{"summary":"Delete a field","description":"Deleting a schema field is an irreversible process.\n\nAssuming a valid `202 Accepted` response is received, any associated field data on associated records will immediately be unavailable to the user. There may be a small delay if record requests are in the midst of processing when the field delete request is issued.\n\nThe deleted field id will *not* be immediately recycled for reuse. Users are encouraged to leverage the `?showFields=all` query parameter when programmatically creating new schema fields, to ensure field id uniqueness. Fields that have been deleted will contain a `status: marked_for_deletion` attribute.\n\nThe field delete operation is only permitted for admin users.\nField deletion is not permitted on public or child schemas (private schemas only).","operationId":"delete-a-field-1","x-canonical-resource":"custom_object_schema","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"schemaId","in":"path","description":"Schema ID of the field to be deleted","schema":{"type":"string"},"required":true},{"name":"fieldId","in":"path","description":"Field ID of the field to be deleted","schema":{"type":"string"},"required":true},{"name":"showFields","in":"query","description":"Toggle which fields are shown in the response body of a schema (if there hidden due to e.g. recently being deleted). Omit this parameter entirely to hide fields by default.","schema":{"type":"string","default":"all"}}],"responses":{"202":{"description":"202","content":{"application/json":{"examples":{"Accepted":{"value":"{\n    \"schema\": {\n        \"id\": \"82ec659f-8283-4e88-9df3-26f4585fec02\",\n        \"slug\": \"my-object\",\n        \"visibility\": \"private\",\n        \"labels\": {\n            \"singular\": \"My Object\",\n            \"plural\": \"My Objects\"\n        },\n        \"description\": \"Sample Schema\",\n        \"createdTimestamp\": \"2021-10-04T20:08:09.574382410Z\",\n        \"updatedTimestamp\": \"2022-06-10T14:19:06.834158129Z\",\n        \"fields\": [\n            {\n                \"id\": \"my-number-field\",\n                \"labels\": {\n                    \"singular\": \"Number\",\n                    \"plural\": \"Numbers\"\n                },\n                \"type\": \"number\",\n                \"required\": false,\n                \"scale\": 0,\n                \"inherited\": false\n            },\n            {\n                \"id\": \"multiselect\",\n                \"labels\": {\n                    \"singular\": \"Multiselect\",\n                    \"plural\": \"Multiselect\"\n                },\n                \"type\": \"multiselect\",\n                \"required\": false,\n                \"options\": [\n                    {\n                        \"id\": \"c56d7f15-d61d-46a6-9b7e-edec21192cd5\",\n                        \"value\": \"Option 4\"\n                    },\n                    {\n                        \"id\": \"91fa9499-c08d-4b24-97c7-04a7fcf5d0dc\",\n                        \"value\": \"Option 5\"\n                    },\n                    {\n                        \"id\": \"42bc2e29-eab5-40ff-85cb-b703c7bc9fd9\",\n                        \"value\": \"Option 6\"\n                    }\n                ],\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"test-field-1\",\n                \"labels\": {\n                    \"singular\": \"test field\",\n                    \"plural\": \"test field\"\n                },\n                \"type\": \"text\",\n                \"required\": false,\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"test-field\",\n                \"labels\": {\n                    \"singular\": \"test field\",\n                    \"plural\": \"test field\"\n                },\n                \"type\": \"text\",\n                \"required\": false,\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"dropdown\",\n                \"labels\": {\n                    \"singular\": \"Dropdown\",\n                    \"plural\": \"Dropdown\"\n                },\n                \"type\": \"dropdown\",\n                \"required\": false,\n                \"options\": [\n                    {\n                        \"id\": \"81529d6b-b5f5-4b13-a3d7-f00b62f1072f\",\n                        \"value\": \"Option 1\"\n                    },\n                    {\n                        \"id\": \"0a9d10a0-a3ea-4247-a2ef-0ed990e2d908\",\n                        \"value\": \"Option 2\"\n                    },\n                    {\n                        \"id\": \"d60f84cf-cca5-4284-97fd-fdc833caa82b\",\n                        \"value\": \"Option 3\"\n                    }\n                ],\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            }\n        ],\n        \"icons\": {\n            \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n        },\n        \"relationships\": [\n            {\n                \"id\": \"primary-contact\",\n                \"labels\": {\n                    \"singular\": \"Primary Contact\",\n                    \"plural\": \"Primary Contacts\"\n                },\n                \"description\": \"Primary contact to this object\",\n                \"namespace\": \"contacts\",\n                \"hasMany\": false,\n                \"inherited\": false\n            }\n        ]\n    }\n}"},"Result":{"value":"{\n    \"schema\": {\n        \"id\": \"82ec659f-8283-4e88-9df3-26f4585fec02\",\n        \"slug\": \"my-object\",\n        \"visibility\": \"private\",\n        \"labels\": {\n            \"singular\": \"My Object\",\n            \"plural\": \"My Objects\"\n        },\n        \"description\": \"Sample Schema\",\n        \"createdTimestamp\": \"2021-10-04T20:08:09.574382410Z\",\n        \"updatedTimestamp\": \"2022-06-10T14:19:06.834158129Z\",\n        \"fields\": [\n            {\n                \"id\": \"my-number-field\",\n                \"labels\": {\n                    \"singular\": \"Number\",\n                    \"plural\": \"Numbers\"\n                },\n                \"type\": \"number\",\n                \"required\": false,\n                \"scale\": 0,\n                \"inherited\": false\n            },\n            {\n                \"id\": \"multiselect\",\n                \"labels\": {\n                    \"singular\": \"Multiselect\",\n                    \"plural\": \"Multiselect\"\n                },\n                \"type\": \"multiselect\",\n                \"required\": false,\n                \"options\": [\n                    {\n                        \"id\": \"c56d7f15-d61d-46a6-9b7e-edec21192cd5\",\n                        \"value\": \"Option 4\"\n                    },\n                    {\n                        \"id\": \"91fa9499-c08d-4b24-97c7-04a7fcf5d0dc\",\n                        \"value\": \"Option 5\"\n                    },\n                    {\n                        \"id\": \"42bc2e29-eab5-40ff-85cb-b703c7bc9fd9\",\n                        \"value\": \"Option 6\"\n                    }\n                ],\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"test-field-1\",\n                \"labels\": {\n                    \"singular\": \"test field\",\n                    \"plural\": \"test field\"\n                },\n                \"type\": \"text\",\n                \"required\": false,\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"test-field\",\n                \"labels\": {\n                    \"singular\": \"test field\",\n                    \"plural\": \"test field\"\n                },\n                \"type\": \"text\",\n                \"required\": false,\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            },\n            {\n                \"id\": \"dropdown\",\n                \"labels\": {\n                    \"singular\": \"Dropdown\",\n                    \"plural\": \"Dropdown\"\n                },\n                \"type\": \"dropdown\",\n                \"required\": false,\n                \"options\": [\n                    {\n                        \"id\": \"81529d6b-b5f5-4b13-a3d7-f00b62f1072f\",\n                        \"value\": \"Option 1\"\n                    },\n                    {\n                        \"id\": \"0a9d10a0-a3ea-4247-a2ef-0ed990e2d908\",\n                        \"value\": \"Option 2\"\n                    },\n                    {\n                        \"id\": \"d60f84cf-cca5-4284-97fd-fdc833caa82b\",\n                        \"value\": \"Option 3\"\n                    }\n                ],\n                \"inherited\": false,\n                \"status\": \"marked_for_deletion\"\n            }\n        ],\n        \"icons\": {\n            \"default\": \"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png\"\n        },\n        \"relationships\": [\n            {\n                \"id\": \"primary-contact\",\n                \"labels\": {\n                    \"singular\": \"Primary Contact\",\n                    \"plural\": \"Primary Contacts\"\n                },\n                \"description\": \"Primary contact to this object\",\n                \"namespace\": \"contacts\",\n                \"hasMany\": false,\n                \"inherited\": false\n            }\n        ]\n    }\n}"}},"schema":{"oneOf":[{"title":"Accepted","type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"82ec659f-8283-4e88-9df3-26f4585fec02"},"slug":{"type":"string","example":"my-object"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"My Object"},"plural":{"type":"string","example":"My Objects"}}},"description":{"type":"string","example":"Sample Schema"},"createdTimestamp":{"type":"string","example":"2021-10-04T20:08:09.574382410Z"},"updatedTimestamp":{"type":"string","example":"2022-06-10T14:19:06.834158129Z"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Number"},"plural":{"type":"string","example":"Numbers"}}},"type":{"type":"string","example":"number"},"required":{"type":"boolean","example":false,"default":true},"scale":{"type":"integer","example":0,"default":0},"inherited":{"type":"boolean","example":false,"default":true}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact to this object"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true},"inherited":{"type":"boolean","example":false,"default":true}}}}}}}},{"type":"object","properties":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"82ec659f-8283-4e88-9df3-26f4585fec02"},"slug":{"type":"string","example":"my-object"},"visibility":{"type":"string","example":"private"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"My Object"},"plural":{"type":"string","example":"My Objects"}}},"description":{"type":"string","example":"Sample Schema"},"createdTimestamp":{"type":"string","example":"2021-10-04T20:08:09.574382410Z"},"updatedTimestamp":{"type":"string","example":"2022-06-10T14:19:06.834158129Z"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"my-number-field"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Number"},"plural":{"type":"string","example":"Numbers"}}},"type":{"type":"string","example":"number"},"required":{"type":"boolean","example":false,"default":true},"scale":{"type":"integer","example":0,"default":0},"inherited":{"type":"boolean","example":false,"default":true}}}},"icons":{"type":"object","properties":{"default":{"type":"string","example":"https://d226aj4ao1t61q.cloudfront.net/n9mayqo2d_customobject.png"}}},"relationships":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"primary-contact"},"labels":{"type":"object","properties":{"singular":{"type":"string","example":"Primary Contact"},"plural":{"type":"string","example":"Primary Contacts"}}},"description":{"type":"string","example":"Primary contact to this object"},"namespace":{"type":"string","example":"contacts"},"hasMany":{"type":"boolean","example":false,"default":true},"inherited":{"type":"boolean","example":false,"default":true}}}}}}}}]}}}}},"deprecated":false}},"/dataLookups":{"get":{"summary":"Search the account's campaigns, automations and templates by name","description":"Looks assets up by name in the account's data lookup index, which holds one row per campaign, automation and campaign template and is kept in step with them by database triggers. Internal: backs the asset picker of the in-app AI assistant.\n\nWith `name`, rows are ranked by full-text relevance, newest first among equals, and then cut where relevance drops the most from one row to the next, so only the closest cluster of matches comes back. Without `name`, rows come back newest first with no cut. `limit` caps the rows read before the cut, so fewer can be returned.\n\nOnly the kinds of asset listed by List the data lookup categories are searched, and a user outside the Admin group only finds the campaigns, automations and templates their lists and groups give them access to. Campaign and campaign template names have their creation date appended in the account's date format, so that two records with the same name can be told apart.","operationId":"list-all-data-lookups","parameters":[{"name":"table","in":"query","description":"Search one kind of asset only, named by its table: em_campaign (campaigns), em_series (automations) or em_template (campaign templates). The parameters value of each entry in List the data lookup categories is this filter. Omit it, or send it empty, to search every kind the user may see.","schema":{"type":"string"},"example":"em_campaign"},{"name":"name","in":"query","description":"Text to look for in asset names: a MySQL full-text search in boolean mode with * appended, so the last word also matches as a prefix and boolean operators in the text take effect. Omit it to list the newest assets instead.","schema":{"type":"string"},"example":"spring sale"},{"name":"limit","in":"query","description":"Most rows to read before the relevance cut, from 1 to 1000.","schema":{"type":"integer","default":50},"example":50}],"responses":{"200":{"description":"The matching assets.","content":{"application/json":{"schema":{"required":["lookups","meta"],"properties":{"lookups":{"description":"The assets, best match first.","type":"array","items":{"required":["table","pkey","name","created_timestamp","updated_timestamp","userid","asset_type","relevance"],"properties":{"table":{"description":"Table the asset lives in: em_campaign, em_series or em_template.","type":"string","example":"em_campaign"},"pkey":{"description":"ID of the asset in that table, which is its campaign, automation or template ID.","type":"integer","example":42},"name":{"description":"Name of the asset. For a campaign or a campaign template, followed by \" - \" and its creation date in the account's date format.","type":"string","example":"Spring sale - 03/02/2026"},"created_timestamp":{"description":"When the asset was created, as Y-m-d H:i:s with no time zone.","type":"string","example":"2026-03-02 09:15:00"},"updated_timestamp":{"description":"When the asset was last changed, as Y-m-d H:i:s with no time zone.","type":"string","example":"2026-03-04 16:40:12"},"userid":{"description":"ID of the user who owns the asset; 0 when it has none.","type":"integer","example":1},"asset_type":{"description":"Kind of asset, the asset_type of its entry in List the data lookup categories.","type":"string","enum":["campaign","automation","campaign_template"],"example":"campaign"},"relevance":{"description":"Full-text relevance score of the match, as a decimal string rather than a JSON number. \"0.1\" for every row when no name was given.","type":"string","example":"0.6931471824645996"}},"type":"object"}},"meta":{"required":["total"],"properties":{"total":{"description":"Number of assets in lookups. Not a count of every match.","type":"integer","example":1}},"type":"object"}},"type":"object"}}}},"422":{"description":"limit is not a number from 1 to 1000, or table is not one of the kinds of asset the user may search.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"One error per failed check.","type":"array","items":{"required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed, for example \"This value should be between 1 and 1000.\", \"The value you selected is not a valid choice.\" for table, or \"Unexpected type\".","type":"string","example":"This value should be between 1 and 1000."},"source":{"description":"The parameter that failed the check.","properties":{"pointer":{"description":"The parameter, as /data/attributes/<name>.","type":"string","example":"/data/attributes/limit"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/dataLookups/categories":{"get":{"summary":"List the data lookup categories","description":"The kinds of asset the signed-in user may look up with Search the account's campaigns, automations and templates by name, each with the table filter that selects it: campaigns, automations and campaign templates today. Internal: backs the category menu of the in-app AI assistant's asset picker.","operationId":"list-all-data-lookup-categories","responses":{"200":{"description":"The categories, in a fixed order.","content":{"application/json":{"schema":{"required":["categories"],"properties":{"categories":{"description":"One entry per kind of asset the user may search.","type":"array","items":{"required":["label","asset_type","parameters"],"properties":{"label":{"description":"English display name of the category. Not translated.","type":"string","example":"Campaigns"},"asset_type":{"description":"Kind of asset, as the asset_type of a lookup.","type":"string","enum":["campaign","automation","campaign_template"],"example":"campaign"},"parameters":{"description":"Query string that restricts a search to this category: table= and the table name.","type":"string","example":"table=em_campaign"}},"type":"object"}}},"type":"object"},"example":{"categories":[{"label":"Campaigns","asset_type":"campaign","parameters":"table=em_campaign"},{"label":"Automations","asset_type":"automation","parameters":"table=em_series"},{"label":"Campaign Templates","asset_type":"campaign_template","parameters":"table=em_template"}]}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/dealActivities":{"get":{"summary":"List all deal activities","description":"View a recent activity for Deals. A specific deal's activity can also be viewed using /api/3/deals/[dealID]/dealActivities.","operationId":"list-all-deal-activities","x-canonical-resource":"dealActivities","parameters":[{"name":"exclude=email","in":"query","description":"Include this param to exclude \"email\", \"connection_email\", and \"LinkData\" activity types","schema":{"type":"string"}},{"name":"deal","in":"query","description":"Filter by deal ID","schema":{"type":"string"}},{"name":"filters[data_type]","in":"query","description":"Enter any dataType (see Response Details) to filter by that type. Examples: \"userid\" or task\" or \"note\"","schema":{"type":"string"}},{"name":"filters[data_id]","in":"query","description":"Enter any dataId (see Response details) to filter by related object. Example \"291\" for a note with ID 291","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"\"dealActivities\": [\n\t{\n    \"d_id\": \"1361\",\n    \"d_stageid\": \"0\",\n    \"userid\": \"1\",\n    \"dataId\": \"0\",\n    \"dataType\": \"\",\n    \"dataAction\": \"add\",\n    \"dataOldval\": \"\",\n    \"cdate\": \"2023-03-29T10:22:03-05:00\",\n    \"sortdate\": \"2023-03-29T10:22:03-05:00\",\n    \"isAddtask\": \"0\",\n    \"deleted\": \"0\",\n    \"seriesid\": \"0\",\n    \"links\": {\n      \"deal\": \"https://account.activehosted.com/api/3/dealActivities/15110/deal\",\n      \"stage\": \"https://account.activehosted.com/api/3/dealActivities/15110/stage\",\n      \"user\": \"https://account.activehosted.com/api/3/dealActivities/15110/user\",\n      \"automation\": \"https://account.activehosted.com/api/3/dealActivities/15110/automation\",\n      \"activity\": \"https://account.activehosted.com/api/3/dealActivities/15110/activity\"\n    },\n    \"id\": \"15110\",\n    \"deal\": \"1361\",\n    \"stage\": null,\n    \"user\": \"1\",\n    \"automation\": null\n   },\n  {\n    \"d_id\": \"1361\",\n    \"d_stageid\": \"0\",\n    \"userid\": \"1\",\n    \"dataId\": \"1512\",\n    \"dataType\": \"contact\",\n    \"dataAction\": \"add\",\n    \"dataOldval\": \"\",\n    \"cdate\": \"2023-03-29T10:22:04-05:00\",\n    \"sortdate\": \"2023-03-29T10:22:04-05:00\",\n    \"isAddtask\": \"0\",\n    \"deleted\": \"0\",\n    \"seriesid\": \"0\",\n    \"links\": {\n      \"deal\": \"https://account.activehosted.com/api/3/dealActivities/15111/deal\",\n      \"stage\": \"https://account.activehosted.com/api/3/dealActivities/15111/stage\",\n      \"user\": \"https://account.activehosted.com/api/3/dealActivities/15111/user\",\n      \"automation\": \"https://account.activehosted.com/api/3/dealActivities/15111/automation\",\n      \"activity\": \"https://account.activehosted.com/api/3/dealActivities/15111/activity\"\n    },\n    \"id\": \"15111\",\n    \"deal\": \"1361\",\n    \"stage\": null,\n    \"user\": \"1\",\n    \"automation\": null\n   }\n  ],\n  \"meta\": {\n  \"total\": \"2\"\n  }\n}"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealConnections":{"get":{"summary":"List connected mailboxes","description":"Internal: backs the connected emails settings page and the deal email composer. Without `useGroup`, returns the current user's own mailboxes a page at a time, with `filters`, `orders` and `ids` applied. With `useGroup` (any value), returns every mailbox in the account when the user is in the main admin group and only the user's own otherwise, all at once: paging, filters, ordering and `ids` are ignored. An account without the Deals feature gets an empty `dealConnections` list and no `meta`.","operationId":"list-all-deal-connections","parameters":[{"name":"useGroup","in":"query","description":"Present (with any value) to list every mailbox in the account for a user in the main admin group, or the user's own for anyone else, without paging","required":false,"schema":{"type":"string"},"example":"1"},{"name":"filters[status]","in":"query","description":"Only mailboxes whose status is exactly this value","required":false,"schema":{"type":"string"},"example":"running"},{"name":"orders[status]","in":"query","description":"Sort by status: DESC for descending, any other value for ascending","required":false,"schema":{"type":"string"},"example":"DESC"},{"name":"ids","in":"query","description":"Comma-separated connection IDs to return; the page size becomes the number of IDs","required":false,"schema":{"type":"string"},"example":"1,3"},{"name":"limit","in":"query","description":"Page size: 20 when left out, at most 100; the string null returns up to 1000","required":false,"schema":{"type":"string"},"example":"20"},{"name":"offset","in":"query","description":"Number of mailboxes to skip, 0 when left out","required":false,"schema":{"type":"integer"},"example":0}],"responses":{"200":{"description":"The mailboxes","content":{"application/json":{"schema":{"properties":{"dealConnections":{"description":"The connected mailboxes","type":"array","items":{"$ref":"#/components/schemas/DealConnection"}},"meta":{"description":"Left out when the account does not have the Deals feature","properties":{"total":{"description":"Number of mailboxes that match, across every page; with useGroup, the number returned","type":"integer","example":2}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user does not have the deals permission. Checked before anything else.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}}},"x-canonical-resource":"deal_connection","x-internal":true},"post":{"summary":"Create a connected mailbox record","description":"Internal: writes one row of the connected mailbox table as sent; the app connects mailboxes through the Nylas authorization flow instead (GET /nylas/v3/authorize). Only the properties in `dealConnection` are read, and none is required or validated: columns left out take their database defaults (API version 2, sync option 1, `preferred_email` null, the other flags 0). Once the row is written a Nylas email backfill is started for it; that fails for a connection that is not on Nylas API v3 or when the backfill request fails, and the request then answers 500 although the row was created. A body with no properties in `dealConnection` writes nothing and still answers 201, with a null `id`.","operationId":"create-a-deal-connection","x-canonical-resource":"deal_connection","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dealConnection"],"properties":{"dealConnection":{"type":"object","description":"The columns to store","properties":{"userid":{"type":["integer","string"],"description":"ID of the user the mailbox belongs to; stored as sent","example":1},"email":{"type":"string","description":"Address of the mailbox","example":"jane@example.com"},"accountid":{"type":"string","description":"Nylas API v2 account ID of the mailbox","example":""},"provider":{"type":["string","null"],"enum":["nylas","contextio",null],"description":"Sync service: nylas, contextio or null","example":"nylas"},"type":{"type":["string","null"],"description":"Email provider of the mailbox as Nylas names it, for example google or microsoft","example":"google"},"version":{"type":"string","description":"Legacy column; not read by current code","example":""},"status":{"type":"string","description":"Sync state, for example running or invalid","example":"running"},"privacy":{"type":["integer","string"],"description":"1 to show emails synced from the mailbox only to its owner, 0 to every user","example":0},"cdate":{"type":["string","null"],"description":"When the mailbox was connected; any date PHP can parse, for example ISO 8601 with an offset","example":"2026-05-04T10:12:30-05:00"},"sentiment_enabled":{"type":["integer","string"],"description":"1 to show the sentiment of synced emails, 0 to hide it","example":1},"preferred_email":{"type":["integer","string","null"],"description":"1 to mark the mailbox the one its user sends deal emails from. Other mailboxes of the user are not changed; use PUT /dealConnections/updatePreferredEmail/{id} for that.","example":1},"has_send_scope":{"type":["integer","string"],"description":"1 when the Nylas connection may send email","example":1},"sync_option":{"type":["integer","string"],"description":"0 to sync every email, 1 only emails with the primary contacts of open deals","example":0},"last_synced":{"type":["string","null"],"description":"When emails were last synced, Y-m-d H:i:s","example":"2026-10-14 08:00:00"},"api_version":{"type":"string","description":"Nylas API version: 2 or 3","example":"3"},"grant_id":{"type":["string","null"],"description":"Nylas API v3 grant of the mailbox","example":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41"}}}}},"example":{"dealConnection":{"userid":1,"email":"jane@example.com","provider":"nylas","type":"google","status":"running","api_version":"3","grant_id":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41","has_send_scope":1,"sync_option":0}}}}},"responses":{"201":{"description":"Created. The connection holds the properties as sent, not read back, plus `id` and an empty `links`.","content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"$ref":"#/components/schemas/DealConnection"}}},"example":{"dealConnection":{"userid":1,"email":"jane@example.com","provider":"nylas","type":"google","status":"running","api_version":"3","grant_id":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41","has_send_scope":1,"sync_option":0,"links":[],"id":"6"}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The user does not have the deals permission. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"500":{"description":"The row was written but the email backfill could not be started: the connection is not on Nylas API v3, or the backfill request failed.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Generic message","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/dealConnections/updatePreferredEmail/{id}":{"put":{"summary":"Set the preferred connected mailbox","description":"Internal: backs the preferred email choice on the connected emails settings page. Marks this connection as the one its owner sends deal emails from (`preferred_email` 1) and every other mailbox of the same user as not preferred (0). The owner is the connection's user, not necessarily the user making the request. Served by a legacy api/3 file that answers only PUT.","operationId":"set-preferred-deal-connection","x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the connection to make preferred; must be a positive integer","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The connection is now preferred","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"ID of the connection","example":"3"},"email":{"type":"string","description":"Address of the mailbox","example":"jane@example.com"},"preferred_email":{"type":"string","description":"Always \"1\"","example":"1"}}},"example":{"id":"3","email":"jane@example.com","preferred_email":"1"}}}},"403":{"description":"The user does not have the deals permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealConnection with id 9"}}}}}},"422":{"description":"The ID is not a positive integer, or is missing.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"422"},"detail":{"type":"string","description":"What was wrong with the ID","example":"Please provide a valid id"}}}}}},"example":{"errors":[{"status":"422","detail":"Please provide a valid id"}]}}}}},"x-internal":true}},"/dealConnections/upgrade":{"post":{"summary":"Move a connected mailbox to Nylas API v3","description":"Internal: moves an existing mailbox connection from Nylas API v2 to v3. Takes the first connection in the account with this `email`, stores `nylasGrantId` as its grant and `provider` as its type, and sets its status to running and its API version to 3. A connection already on API v3 is left unchanged and the call still answers 200.","operationId":"upgrade-a-deal-connection-to-nylas-v3","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["email","nylasGrantId","provider"],"properties":{"email":{"description":"Address of the connected mailbox to move","type":"string","example":"jane@example.com"},"nylasGrantId":{"description":"Nylas API v3 grant to use for the mailbox","type":"string","example":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41"},"provider":{"description":"Email provider of the mailbox as Nylas API v3 names it, stored as the connection type","type":"string","example":"google"}},"type":"object"}}}},"responses":{"200":{"description":"The connection uses Nylas API v3, now or already","content":{"application/json":{"schema":{"properties":{"acAccountId":{"description":"ID of the ActiveCampaign account the connection belongs to","type":["integer","string"],"example":1234567}},"type":"object"}}}},"403":{"description":"The user does not have the deals permission. Checked before anything else.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry describing the error","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No connection in the account has this address. The body is empty."},"422":{"description":"email, nylasGrantId or provider is missing or empty, or the body is not JSON.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always the same message","type":"string","example":"email, nylasGrantId, and provider must be sent"}},"type":"object"}}}}},"x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/dealConnections/{id}":{"get":{"summary":"Retrieve a connected mailbox","description":"Internal: returns one connected mailbox by ID.","operationId":"retrieve-a-deal-connection","x-canonical-resource":"deal_connection","parameters":[{"name":"id","in":"path","description":"ID of the connection","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The connection","content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"$ref":"#/components/schemas/DealConnection"}}},"example":{"dealConnection":{"id":"3","userid":"1","email":"jane@example.com","accountid":"","provider":"nylas","type":"google","version":"","status":"running","privacy":"0","cdate":"2026-05-04T10:12:30-05:00","sentiment_enabled":"1","preferred_email":"1","has_send_scope":"1","sync_option":"0","last_synced":"2026-10-14 08:00:00","api_version":"3","grant_id":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41","links":[]}}}}},"403":{"description":"The user does not have the deals permission. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealConnection with id 9"}}}}}}},"x-internal":true},"put":{"summary":"Update a connected mailbox","description":"Internal: changes the columns sent in `dealConnection` on one connection and stores them; no field is validated. Fields left out keep their value and a body without `dealConnection` changes nothing and still answers 200. Changing `preferred_email` here does not clear it on the user's other mailboxes; PUT /dealConnections/updatePreferredEmail/{id} does. The response is the stored row with the changed values as sent, not read back. PATCH /dealConnections/{id} does the same thing.","operationId":"update-a-deal-connection","x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the connection","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"type":"object","description":"The columns to change","properties":{"userid":{"type":["integer","string"],"description":"ID of the user the mailbox belongs to; stored as sent","example":1},"email":{"type":"string","description":"Address of the mailbox","example":"jane@example.com"},"accountid":{"type":"string","description":"Nylas API v2 account ID of the mailbox","example":""},"provider":{"type":["string","null"],"enum":["nylas","contextio",null],"description":"Sync service: nylas, contextio or null","example":"nylas"},"type":{"type":["string","null"],"description":"Email provider of the mailbox as Nylas names it, for example google or microsoft","example":"google"},"version":{"type":"string","description":"Legacy column; not read by current code","example":""},"status":{"type":"string","description":"Sync state, for example running or invalid","example":"running"},"privacy":{"type":["integer","string"],"description":"1 to show emails synced from the mailbox only to its owner, 0 to every user","example":0},"cdate":{"type":["string","null"],"description":"When the mailbox was connected; any date PHP can parse, for example ISO 8601 with an offset","example":"2026-05-04T10:12:30-05:00"},"sentiment_enabled":{"type":["integer","string"],"description":"1 to show the sentiment of synced emails, 0 to hide it","example":1},"preferred_email":{"type":["integer","string","null"],"description":"1 to mark the mailbox the one its user sends deal emails from. Other mailboxes of the user are not changed; use PUT /dealConnections/updatePreferredEmail/{id} for that.","example":1},"has_send_scope":{"type":["integer","string"],"description":"1 when the Nylas connection may send email","example":1},"sync_option":{"type":["integer","string"],"description":"0 to sync every email, 1 only emails with the primary contacts of open deals","example":0},"last_synced":{"type":["string","null"],"description":"When emails were last synced, Y-m-d H:i:s","example":"2026-10-14 08:00:00"},"api_version":{"type":"string","description":"Nylas API version: 2 or 3","example":"3"},"grant_id":{"type":["string","null"],"description":"Nylas API v3 grant of the mailbox","example":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41"}}}}},"example":{"dealConnection":{"status":"running","sync_option":0}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"$ref":"#/components/schemas/DealConnection"}}},"example":{"dealConnection":{"id":"3","userid":"1","email":"jane@example.com","accountid":"","provider":"nylas","type":"google","version":"","status":"running","privacy":"0","cdate":"2026-05-04T10:12:30-05:00","sentiment_enabled":"1","preferred_email":"1","has_send_scope":"1","sync_option":0,"last_synced":"2026-10-14 08:00:00","api_version":"3","grant_id":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41","links":[]}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The user does not have the deals permission (checked before anything else), or the request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealConnection with id 9"}}}}}}},"x-internal":true},"patch":{"summary":"Update a connected mailbox with PATCH","description":"Internal: changes the columns sent in `dealConnection` on one connection and stores them; no field is validated. Fields left out keep their value and a body without `dealConnection` changes nothing and still answers 200. Changing `preferred_email` here does not clear it on the user's other mailboxes; PUT /dealConnections/updatePreferredEmail/{id} does. The response is the stored row with the changed values as sent, not read back. The whitelist routes PATCH to the same action as PUT /dealConnections/{id}, so the body and every answer are the same.","operationId":"patch-a-deal-connection","x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the connection","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"type":"object","description":"The columns to change","properties":{"userid":{"type":["integer","string"],"description":"ID of the user the mailbox belongs to; stored as sent","example":1},"email":{"type":"string","description":"Address of the mailbox","example":"jane@example.com"},"accountid":{"type":"string","description":"Nylas API v2 account ID of the mailbox","example":""},"provider":{"type":["string","null"],"enum":["nylas","contextio",null],"description":"Sync service: nylas, contextio or null","example":"nylas"},"type":{"type":["string","null"],"description":"Email provider of the mailbox as Nylas names it, for example google or microsoft","example":"google"},"version":{"type":"string","description":"Legacy column; not read by current code","example":""},"status":{"type":"string","description":"Sync state, for example running or invalid","example":"running"},"privacy":{"type":["integer","string"],"description":"1 to show emails synced from the mailbox only to its owner, 0 to every user","example":0},"cdate":{"type":["string","null"],"description":"When the mailbox was connected; any date PHP can parse, for example ISO 8601 with an offset","example":"2026-05-04T10:12:30-05:00"},"sentiment_enabled":{"type":["integer","string"],"description":"1 to show the sentiment of synced emails, 0 to hide it","example":1},"preferred_email":{"type":["integer","string","null"],"description":"1 to mark the mailbox the one its user sends deal emails from. Other mailboxes of the user are not changed; use PUT /dealConnections/updatePreferredEmail/{id} for that.","example":1},"has_send_scope":{"type":["integer","string"],"description":"1 when the Nylas connection may send email","example":1},"sync_option":{"type":["integer","string"],"description":"0 to sync every email, 1 only emails with the primary contacts of open deals","example":0},"last_synced":{"type":["string","null"],"description":"When emails were last synced, Y-m-d H:i:s","example":"2026-10-14 08:00:00"},"api_version":{"type":"string","description":"Nylas API version: 2 or 3","example":"3"},"grant_id":{"type":["string","null"],"description":"Nylas API v3 grant of the mailbox","example":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41"}}}}},"example":{"dealConnection":{"status":"running","sync_option":0}}}}},"responses":{"200":{"description":"The change was saved, or there was nothing to change","content":{"application/json":{"schema":{"type":"object","properties":{"dealConnection":{"$ref":"#/components/schemas/DealConnection"}}},"example":{"dealConnection":{"id":"3","userid":"1","email":"jane@example.com","accountid":"","provider":"nylas","type":"google","version":"","status":"running","privacy":"0","cdate":"2026-05-04T10:12:30-05:00","sentiment_enabled":"1","preferred_email":"1","has_send_scope":"1","sync_option":0,"last_synced":"2026-10-14 08:00:00","api_version":"3","grant_id":"5d1f0c2a-8e6b-4c51-9a0e-0f3b2c7d9e41","links":[]}}}}},"400":{"description":"The request body is JSON but is a non-empty list or a scalar, not an object. Checked before anything else.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"What was wrong with the body","example":"Request body must be a JSON object, array given."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The user does not have the deals permission (checked before anything else), or the request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealConnection with id 9"}}}}}}},"x-internal":true},"delete":{"summary":"Delete a connected mailbox","description":"Internal: removes one connected mailbox. For a mailbox on Nylas API v3 its Nylas grant is revoked first, so the mailbox stops syncing; an HTTP failure revoking the grant is logged and does not stop the delete.","operationId":"delete-a-deal-connection","x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the connection","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{}}}},"403":{"description":"The user does not have the deals permission, or the row could not be deleted. In the second case the body is the plain-text message `Failed to delete dealConnection`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always \"Forbidden\"","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}},"text/plain":{"schema":{"type":"string"},"example":"Failed to delete dealConnection"}}},"404":{"description":"No connection has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealConnection with id 9"}}}}}}},"x-internal":true}},"/dealCustomFieldData":{"post":{"summary":"Set a deal custom field value","description":"","operationId":"create-custom-deal-field-value","x-canonical-resource":"custom_field_value","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealCustomFieldDatum":{"properties":{"dealId":{"type":"integer","description":"The ID of the deal this field value relates to","format":"int32"},"customFieldId":{"type":"integer","description":"The ID of the custom field metum this field value relates to","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For `currency` field only, this needs to be in cents: eg, 10050 = 100.5) For `dropdown` and `radio` fields send one option as a plain string, exactly as it appears in the field's options (for example `option 1`). For `multiselect` and `checkbox` fields send a JSON array of options. The `||option 1||option 2||` form used by contact custom fields is not accepted here."},"fieldCurrency":{"type":"string","description":"Currency code for the money value","default":"Default Currency for Field"}},"required":["dealId","customFieldId","fieldValue"],"type":"object"}}},"examples":{"text":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":1,"fieldValue":"Northeast region"}}},"textarea":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":2,"fieldValue":"Met at the 2026 trade show.\nFollow up after the product demo."}}},"hidden":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":3,"fieldValue":"partner-ref-1234"}}},"dropdown":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":4,"fieldValue":"option 1"}}},"radio":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":5,"fieldValue":"option 2"}}},"multiselect":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":6,"fieldValue":["option 1","option 3","option 4"]}}},"checkbox":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":7,"fieldValue":["option 1"]}}},"currency":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":8,"fieldValue":9999,"fieldCurrency":"usd"}}},"number":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":9,"fieldValue":"100.99"}}},"date":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":10,"fieldValue":"2026-12-31"}}},"datetime":{"value":{"dealCustomFieldDatum":{"dealId":2,"customFieldId":11,"fieldValue":"2026-05-19T14:45:00-05:00"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldDatum\": {\n        \"id\": \"5\",\n        \"dealCustomFieldMetumId\": 1,\n        \"dealId\": 2,\n        \"customFieldId\": 1,\n        \"createdTimestamp\": \"2018-11-06 02:27:05\",\n        \"updatedTimestamp\": \"2018-11-06 02:27:05\",\n        \"fieldValue\": \"test title\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/5/deal\",\n            \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/5/dealCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","examples":["5"]},"dealCustomFieldMetumId":{"type":"integer","default":0,"examples":[1]},"dealId":{"type":"integer","default":0,"examples":[2]},"customFieldId":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-11-06 02:27:05"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:27:05"]},"fieldValue":{"type":"string","examples":["test title"]},"links":{"type":"object","properties":{"deal":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/5/deal"]},"dealCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/5/dealCustomFieldMetum"]}}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"detail\": \"The custom field value `abc` could not be saved to the custom field of type `date`.\"\n        }\n    ]\n}"}},"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","example":"422"},"title":{"type":"string","example":"The given data was invalid."},"detail":{"type":"string","example":"The deal id field is required."}}}}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"detail":{"type":"string","example":"A related deal was not found."}}}}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"detail":{"type":"string","example":"A custom field value must be provided."}}}}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"detail":{"type":"string","example":"The custom field value `abc` could not be saved to the custom field of type `date`."}}}}}}]}}}}},"deprecated":false,"x-mcp-tool":{"name":"set_deal_custom_field_value","title":"Set Deal Custom Field Value","description":"Give one deal its first value in a field it holds no value for yet. To change a value the deal already holds, use update_deal_custom_field_value with that value's id from list_deal_custom_field_values.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List deal custom field values","description":"","operationId":"list-all-custom-fielddata-field-values","x-canonical-resource":"custom_field_value","parameters":[{"name":"filters[dealId]","in":"query","description":"Filter results by a specific deal (note that Id uses a capital I)","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldData\": [\n        {\n            \"id\": \"3\",\n            \"dealCustomFieldMetumId\": 1,\n            \"dealId\": 1,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:26:07\",\n            \"updatedTimestamp\": \"2018-11-06 02:26:07\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/3/deal\",\n                \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/3/dealCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"4\",\n            \"dealCustomFieldMetumId\": 1,\n            \"dealId\": 3,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:26:51\",\n            \"updatedTimestamp\": \"2018-11-06 02:26:51\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/4/deal\",\n                \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/4/dealCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"5\",\n            \"dealCustomFieldMetumId\": 1,\n            \"dealId\": 2,\n            \"customFieldId\": 1,\n            \"createdTimestamp\": \"2018-11-06 02:27:05\",\n            \"updatedTimestamp\": \"2018-11-06 02:27:05\",\n            \"fieldValue\": \"test title\",\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/5/deal\",\n                \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/5/dealCustomFieldMetum\"\n            }\n        },\n        {\n            \"id\": \"1\",\n            \"dealCustomFieldMetumId\": 5,\n            \"dealId\": 2,\n            \"customFieldId\": 5,\n            \"createdTimestamp\": \"2018-10-29 20:40:38\",\n            \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n            \"fieldValue\": \"New title\",\n            \"links\": {\n                \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/deal\",\n                \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/dealCustomFieldMetum\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldData":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["3"]},"dealCustomFieldMetumId":{"type":"integer","default":0,"examples":[1]},"dealId":{"type":"integer","default":0,"examples":[1]},"customFieldId":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-11-06 02:26:07"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:26:07"]},"fieldValue":{"type":"string","examples":["test title"]},"links":{"type":"object","properties":{"deal":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/3/deal"]},"dealCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/3/dealCustomFieldMetum"]}}}}}},"meta":{"type":"object","properties":{"total":{"type":"string"}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_deal_custom_field_values","title":"List Deal Custom Field Values","description":"The values deals hold in their deal custom fields, one item per deal per field.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/dealCustomFieldData/bulkCreate":{"post":{"summary":"Bulk create a custom deal field value","description":"","operationId":"bulk-create-a-custom-deal-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"array":{"properties":{"dealId":{"type":"integer","description":"The ID of the deal this field value relates to","format":"int32"},"customFieldId":{"type":"integer","description":"The ID of the custom field metum this field value relates to","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For currency field only, this needs to be in cents: eg, 10050 = 100.5)"},"fieldCurrency":{"type":"string","description":"Currency code for the money value"}},"required":["dealId","customFieldId","fieldValue"],"type":"object"}}},"examples":{"Request Example":{"value":[{"dealId":"1","customFieldId":"1","fieldValue":"test title"},{"dealId":"1","customFieldId":"2","fieldValue":"test title"},{"dealId":"1","customFieldId":"3","fieldValue":["option 1","option 3","option 4"]},{"dealId":"1","customFieldId":"4","fieldValue":9999,"fieldCurrency":"cad"},{"dealId":"1","customFieldId":"5","fieldValue":"100.99"},{"dealId":"1","customFieldId":"6","fieldValue":"2018-12-31"},{"dealId":"1","customFieldId":"7","fieldValue":"2020-05-19T02:45:00-05:00"}]}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"the bulk insert was successful\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"the bulk insert was successful"}}}}}}},"deprecated":false}},"/dealCustomFieldData/bulkUpdate":{"patch":{"summary":"Bulk update deal custom field values","description":"","operationId":"bulk-update-a-custom-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"array":{"properties":{"id":{"type":"integer","description":"ID of the dealCustomFieldData to update","format":"int32"},"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For currency field only, this needs to be in cents: eg, 10050 = 100.5)"},"fieldCurrency":{"type":"string","description":"Currency code for the money value"}},"required":["id","fieldValue"],"type":"object"}}},"examples":{"Request Example":{"value":[{"id":"1","fieldValue":"test title"},{"id":"2","fieldValue":["option 1","option 3","option 4"]},{"id":"3","fieldValue":9999,"fieldCurrency":"cad"},{"id":"4","fieldValue":"100.99"},{"id":"5","fieldValue":"2018-12-31"},{"id":"6","fieldValue":"2020-05-19T02:45:00-05:00"}]}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"DealCustomFieldDatas with ID(s): 1, 2, 3, 4, 5 successfully bulk updated.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"DealCustomFieldDatas with ID(s): 1, 2, 3, 4, 5 successfully bulk updated."}}}}}}},"deprecated":false}},"/dealCustomFieldData/{id}":{"get":{"summary":"Retrieve a deal custom field value","description":"","operationId":"retrieve-a-custom-deal-field-value","x-canonical-resource":"custom_field_value","parameters":[{"name":"id","in":"path","description":"ID of the dealCustomFieldData to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldDatum\": {\n        \"id\": \"1\",\n        \"dealCustomFieldMetumId\": 5,\n        \"dealId\": 2,\n        \"customFieldId\": 5,\n        \"createdTimestamp\": \"2018-10-29 20:40:38\",\n        \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n        \"fieldValue\": \"New title\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/deal\",\n            \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/dealCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"dealCustomFieldMetumId":{"type":"integer","example":5,"default":0},"dealId":{"type":"integer","example":2,"default":0},"customFieldId":{"type":"integer","example":5,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-29 20:40:38"},"updatedTimestamp":{"type":"string","example":"2018-11-06 02:21:36"},"fieldValue":{"type":"string","example":"New title"},"links":{"type":"object","properties":{"deal":{"type":"string","example":"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/deal"},"dealCustomFieldMetum":{"type":"string","example":"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/dealCustomFieldMetum"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"put":{"summary":"Update a deal custom field value","description":"","operationId":"update-a-custom-deal-field-value","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom fields value to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealCustomFieldDatum":{"properties":{"fieldValue":{"type":["string","number","array"],"items":{"type":"string"},"description":"Values for the field. (For `currency` field only, this needs to be in cents: eg, 10050 = 100.5) For `dropdown` and `radio` fields send one option as a plain string, exactly as it appears in the field's options (for example `option 1`). For `multiselect` and `checkbox` fields send a JSON array of options. The `||option 1||option 2||` form used by contact custom fields is not accepted here."},"fieldCurrency":{"type":"string","description":"Currency code for the `currency` value","default":"Default Currency for Field"}},"required":[],"type":"object"}}},"examples":{"text":{"value":{"dealCustomFieldDatum":{"fieldValue":"Northeast region"}}},"textarea":{"value":{"dealCustomFieldDatum":{"fieldValue":"Met at the 2026 trade show.\nFollow up after the product demo."}}},"hidden":{"value":{"dealCustomFieldDatum":{"fieldValue":"partner-ref-1234"}}},"dropdown":{"value":{"dealCustomFieldDatum":{"fieldValue":"option 1"}}},"radio":{"value":{"dealCustomFieldDatum":{"fieldValue":"option 2"}}},"multiselect":{"value":{"dealCustomFieldDatum":{"fieldValue":["option 1","option 3","option 4"]}}},"checkbox":{"value":{"dealCustomFieldDatum":{"fieldValue":["option 1"]}}},"currency":{"value":{"dealCustomFieldDatum":{"fieldValue":9999,"fieldCurrency":"usd"}}},"number":{"value":{"dealCustomFieldDatum":{"fieldValue":"100.99"}}},"date":{"value":{"dealCustomFieldDatum":{"fieldValue":"2026-12-31"}}},"datetime":{"value":{"dealCustomFieldDatum":{"fieldValue":"2026-05-19T14:45:00-05:00"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldDatum\": {\n        \"id\": \"1\",\n        \"dealCustomFieldMetumId\": 5,\n        \"dealId\": 2,\n        \"customFieldId\": 5,\n        \"createdTimestamp\": \"2018-10-29 20:40:38\",\n        \"updatedTimestamp\": \"2018-11-06 02:21:36\",\n        \"fieldValue\": \"New title\",\n        \"links\": {\n            \"deal\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/deal\",\n            \"dealCustomFieldMetum\": \"https://:account.api-us1.com/api/:version/dealCustomFieldData/1/dealCustomFieldMetum\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldDatum":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"dealCustomFieldMetumId":{"type":"integer","default":0,"examples":[5]},"dealId":{"type":"integer","default":0,"examples":[2]},"customFieldId":{"type":"integer","default":0,"examples":[5]},"createdTimestamp":{"type":"string","examples":["2018-10-29 20:40:38"]},"updatedTimestamp":{"type":"string","examples":["2018-11-06 02:21:36"]},"fieldValue":{"type":"string","examples":["New title"]},"links":{"type":"object","properties":{"deal":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/1/deal"]},"dealCustomFieldMetum":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldData/1/dealCustomFieldMetum"]}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"detail\": \"The custom field value could not be saved to the custom field of type `number`.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"detail":{"type":"string","example":"The custom field value could not be saved to the custom field of type `number`."}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"update_deal_custom_field_value","title":"Update Deal Custom Field Value","description":"Change a deal custom field value that already exists, by the value's id from list_deal_custom_field_values.","annotations":{"readOnlyHint":false,"idempotentHint":true,"openWorldHint":false}}},"delete":{"summary":"Delete a deal custom field value","description":"","operationId":"delete-a-custom-deal-field-data","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the dealCustomFieldData to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"DealCustomFieldData deleted.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"DealCustomFieldData deleted."}}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false}},"/dealCustomFieldMeta":{"post":{"summary":"Create a deal custom field","description":"","operationId":"create-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealCustomFieldMetum":{"properties":{"fieldLabel":{"type":"string","description":"Name of the field"},"fieldType":{"type":"string","description":"Type of field. Possible values are: `text`, `textarea`, `date`, `datetime`, `dropdown`, `multiselect`, `radio`, `checkbox`, `hidden`, `currency`, `number`, or `lookup`. A `lookup` field shows a field of a related object instead of holding a value of its own, and is configured through `field_options`. The type of an existing field is never changed by an update, so a field has to be created as a `lookup`."},"fieldOptions":{"type":["array","object"],"description":"Options for the field. A list of values, necessary if `field_type` is `dropdown`, `multiselect`, `radio`, or `checkbox`. For a `lookup` field it is an object instead: `{\"lookup\": {\"object\": \"account|contact|deal\", \"field\": \"<field id>\"}}`, naming the object and the field whose value is shown. An update may change a lookup field's configuration, and an update that omits it keeps the stored one.","items":{"type":"string"}},"fieldDefault":{"type":"string","description":"Default value of the field. For a `date` field use YYYY-MM-DD; YYYY/MM/DD and MM/DD/YYYY are also accepted, and the value is stored as YYYY-MM-DD."},"fieldDefaultCurrency":{"type":"string","description":"The 3-letter currency code of the default currency for the field. Only necessary if `field_type` is `currency`."},"isFormVisible":{"type":"boolean","description":"Whether or not the field is visible on forms"},"isRequired":{"type":["integer","boolean"],"description":"1 to make the field required, 0 (the default) to leave it optional. A required field must also send a non-empty `fieldDefault`, otherwise the request answers 400."},"displayOrder":{"type":"integer","description":"Order for displaying the field on Manage Fields page and deal profiles","format":"int32"}},"required":["fieldLabel","fieldType"],"type":"object"}}},"examples":{"text":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample text field2","fieldType":"text","fieldDefault":"Default Text","isFormVisible":1,"displayOrder":1}}},"textarea":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample textarea field","fieldType":"textarea","fieldDefault":"Default Text in Text Area","isFormVisible":1,"isRequired":1,"displayOrder":2}}},"date":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample date field","fieldType":"date","fieldDefault":"2018-12-31","isFormVisible":1,"isRequired":1,"displayOrder":3}}},"dropdown":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample dropdown field","fieldType":"dropdown","fieldDefault":"option 2","fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"isRequired":1,"displayOrder":4}}},"multiselect":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample multiselect field","fieldType":"multiselect","fieldDefault":["option 2","option 3"],"fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"isRequired":1,"displayOrder":5}}},"radio":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample radio field","fieldType":"radio","fieldDefault":"option 2","fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"isRequired":1,"displayOrder":6}}},"checkbox":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample checkbox field","fieldType":"checkbox","fieldDefault":["option 2","option 3"],"fieldOptions":["option 1","option 2","option 3"],"isFormVisible":1,"isRequired":1,"displayOrder":7}}},"hidden":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample hidden field","fieldType":"hidden","fieldDefault":"Default Text in Hidden Field","isFormVisible":1,"isRequired":1,"displayOrder":8}}},"number":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample number field","fieldType":"number","fieldDefault":"100.99","isFormVisible":1,"isRequired":1,"displayOrder":9}}},"currency":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample money field","fieldType":"currency","fieldDefault":"10099","fieldDefaultCurrency":"aud","isFormVisible":1,"isRequired":1,"displayOrder":10}}},"datetime (ISO)":{"value":{"dealCustomFieldMetum":{"fieldLabel":"sample datetime field","fieldType":"datetime","fieldDefault":"2020-05-16T03:15:00-05:00","isFormVisible":1,"isRequired":1,"displayOrder":3}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 1,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 19:57:37\",\n        \"links\": {\n            \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/3/dealCustomFieldMeta/1/dealCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"fieldLabel":{"type":"string","examples":["title"]},"fieldType":{"type":"string","examples":["text"]},"fieldOptions":{},"fieldDefault":{"type":"string","examples":["Default Text"]},"isFormVisible":{"type":"integer","default":0,"examples":[1]},"isRequired":{"type":"integer","default":0,"examples":[1]},"displayOrder":{"type":"integer","default":0,"examples":[1]},"createdTimestamp":{"type":"string","examples":["2018-10-22 19:57:37"]},"updatedTimestamp":{"type":"string","examples":["2018-10-22 19:57:37"]},"links":{"type":"object","properties":{"dealCustomFieldData":{"type":"string","examples":["https://:account.api-us1.com/api/:version/3/dealCustomFieldMeta/1/dealCustomFieldData"]}}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"errors\": [{\n  \t\"title\": \"The field type field is required.\",\n    \"detail\": \"\",\n    \"code\": 422\n  }]\n}"}}}}}},"deprecated":false,"x-mcp-tool":{"name":"create_deal_custom_field","title":"Create Deal Custom Field","description":"Define a new custom field on deals: the deal field itself, with its type and label.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List deal custom fields","description":"","operationId":"retrieve-all-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","parameters":[{"name":"limit","in":"query","description":"The number of fields returned per request.","schema":{"type":"integer","format":"int32","default":100}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldMeta\": [\n        {\n            \"id\": \"1\",\n            \"fieldLabel\": \"Text Example\",\n            \"fieldType\": \"text\",\n            \"fieldOptions\": null,\n            \"fieldDefault\": 1,\n            \"fieldDefaultCurrency\": null,\n            \"isFormVisible\": 0,\n            \"isRequired\": 0,\n            \"displayOrder\": 1,\n            \"personalization\": \"\",\n            \"knownFieldId\": null,\n            \"hideFieldFlag\": 0,\n            \"createdTimestamp\": \"2019-04-23 15:34:00\",\n            \"updatedTimestamp\": \"2019-05-03 15:16:51\",\n            \"links\": {\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData\"\n            }\n        },\n        {\n            \"id\": \"2\",\n            \"fieldLabel\": \"Multiple Choice Example\",\n            \"fieldType\": \"multiselect\",\n            \"fieldOptions\": [\n            \t\"Option 1\",\n            \t\"Option 2\",\n            \t\"Option 3\"\n            ],\n            \"fieldDefault\": 1,\n            \"fieldDefaultCurrency\": null,\n            \"isFormVisible\": 0,\n            \"isRequired\": 0,\n            \"displayOrder\": 2,\n            \"personalization\": \"\",\n            \"knownFieldId\": null,\n            \"hideFieldFlag\": 0,\n            \"createdTimestamp\": \"2019-04-23 15:34:00\",\n            \"updatedTimestamp\": \"2019-05-03 15:16:51\",\n            \"links\": {\n                \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldMeta":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"fieldLabel":{"type":"string","examples":["Text Example"]},"fieldType":{"type":"string","examples":["text"]},"fieldOptions":{},"fieldDefault":{"type":"integer","default":0,"examples":[1]},"fieldDefaultCurrency":{},"isFormVisible":{"type":"integer","default":0,"examples":[0]},"isRequired":{"type":"integer","default":0,"examples":[0]},"displayOrder":{"type":"integer","default":0,"examples":[1]},"personalization":{"type":"string","examples":[""]},"knownFieldId":{},"hideFieldFlag":{"type":"integer","default":0,"examples":[0]},"createdTimestamp":{"type":"string","examples":["2019-04-23 15:34:00"]},"updatedTimestamp":{"type":"string","examples":["2019-05-03 15:16:51"]},"links":{"type":"object","properties":{"dealCustomFieldData":{"type":"string","examples":["https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData"]}}}}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_deal_custom_fields","title":"List Deal Custom Fields","description":"Every custom field defined on deals: the deal fields, each with its type and label.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/dealCustomFieldMeta/bulkDelete":{"delete":{"summary":"Delete several deal custom fields","description":"Deletes several deal custom fields in one call. Send a JSON array of field ids. Hosted sends the body on to the custom fields service in one DELETE, and the service does the delete. Hosted does not check the ids. A body that is empty or not valid JSON is sent as an empty array. A single value such as 5 is sent as [5]. An empty JSON object is sent as [], and an object with the keys 0, 1 and so on is sent as a list. Any other object is sent unchanged. The user needs permission to manage deal fields (pg_deal_fields), or the call returns 403 before anything is sent. Returns 405 for any other method. Returns 403, 404 or 409 when the service answers with that status, and 422 when the service refuses the request. Internal: not part of the public API.","operationId":"bulk-delete-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"array","description":"Ids of the fields to delete.","items":{"type":["integer","string"]}},"example":["2","3"]}}},"responses":{"200":{"$ref":"#/components/responses/DealCustomFieldMetaBulkResult"},"403":{"$ref":"#/components/responses/DealCustomFieldMetaBulkForbidden"},"404":{"$ref":"#/components/responses/DealCustomFieldMetaBulkNotFound"},"405":{"$ref":"#/components/responses/DealCustomFieldMetaBulkMethodNotAllowed"},"409":{"$ref":"#/components/responses/DealCustomFieldMetaBulkConflict"},"422":{"$ref":"#/components/responses/DealCustomFieldMetaBulkUnprocessable"}}}},"/dealCustomFieldMeta/bulkUpdate":{"patch":{"summary":"Update several deal custom fields","description":"Updates several deal custom fields in one call. Send a JSON array with one object per field: the field's id and the attributes to change. Hosted turns each top-level key from camelCase into snake_case, drops keys whose value is null, and sends the list to the custom fields service in one PATCH. Nested values such as fieldOptions are sent as they are. The service does the update and decides which keys it accepts. The request carries the user's time zone in a UserTimezone header. Unlike PUT /dealCustomFieldMeta/{id}, Hosted does not need the dealCustomFieldMetum wrapper. It also does not check personalization tags, check that a required field has a default, check that lookup fields are on for the account, or set updated_by. A body that is not valid JSON is sent as an empty array. The user needs permission to manage deal fields (pg_deal_fields), or the call returns 403 before anything is sent. Returns 405 for any other method. Returns 403, 404 or 409 when the service answers with that status, and 422 when the service refuses the request. Internal: not part of the public API.","operationId":"bulk-update-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DealCustomFieldMetaBulkUpdateItem"}},"example":[{"id":"2","fieldLabel":"Delivery method","displayOrder":2},{"id":"3","isFormVisible":1}]}}},"responses":{"200":{"$ref":"#/components/responses/DealCustomFieldMetaBulkResult"},"403":{"$ref":"#/components/responses/DealCustomFieldMetaBulkForbidden"},"404":{"$ref":"#/components/responses/DealCustomFieldMetaBulkNotFound"},"405":{"$ref":"#/components/responses/DealCustomFieldMetaBulkMethodNotAllowed"},"409":{"$ref":"#/components/responses/DealCustomFieldMetaBulkConflict"},"422":{"$ref":"#/components/responses/DealCustomFieldMetaBulkUnprocessable"}}}},"/dealCustomFieldMeta/bulkUpdatePersonalization":{"patch":{"summary":"Add missing personalization tags to deal custom fields","description":"Gives a personalization tag to each deal custom field that has none. It takes no body, and Hosted does not read one. First Hosted gets the deal custom fields from the custom fields service, in one request with no limit or offset. Whether that request returns every field is up to the service. For each field whose personalization is missing or empty, Hosted makes a tag from the field label. It drops every character other than letters, digits, underscores and white space, trims the ends, turns the result into upper case, turns each run of white space into one underscore and puts DEAL_ in front unless the tag already starts with it. A label of Delivery method gives DEAL_DELIVERY_METHOD. While a contact field already uses the tag, Hosted adds _1, or raises a number already at the end, so DEAL_Q_2 becomes DEAL_Q_3. It then asks the service to check the tag against deal and account fields, and uses the tag the service gives back, checking it against contact fields again until both agree. Tags made in the same call are not checked against each other. Last, Hosted sends one PATCH to the service with the id and new personalization of each of those fields, as in PATCH /dealCustomFieldMeta/bulkUpdate. When every field already has a tag, Hosted still sends the PATCH, with an empty array. The user needs permission to manage deal fields (pg_deal_fields), or the call returns 403 before anything is sent. Returns 405 for any other method. Returns 403, 404 or 409 when the service answers one of these requests with that status, and 422 when the service refuses the update. If the service refuses the list with 422, Hosted still sends the PATCH with an empty array, and the call returns the status of that PATCH. The body is then the 422 errors followed by the PATCH answer, which is not one JSON document. Internal: not part of the public API.","operationId":"bulk-update-custom-deal-field-meta-personalization","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"responses":{"200":{"$ref":"#/components/responses/DealCustomFieldMetaBulkResult"},"403":{"$ref":"#/components/responses/DealCustomFieldMetaBulkForbidden"},"404":{"$ref":"#/components/responses/DealCustomFieldMetaBulkNotFound"},"405":{"$ref":"#/components/responses/DealCustomFieldMetaBulkMethodNotAllowed"},"409":{"$ref":"#/components/responses/DealCustomFieldMetaBulkConflict"},"422":{"$ref":"#/components/responses/DealCustomFieldMetaBulkUnprocessable"}}}},"/dealCustomFieldMeta/{id}":{"get":{"summary":"Retrieve a deal custom field","description":"","operationId":"retrieve-a-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","parameters":[{"name":"id","in":"path","description":"ID of the field to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"New Title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 1,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 20:04:21\",\n        \"links\": {\n            \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"fieldLabel":{"type":"string","example":"New Title"},"fieldType":{"type":"string","example":"text"},"fieldOptions":{},"fieldDefault":{"type":"string","example":"Default Text"},"isFormVisible":{"type":"integer","example":1,"default":0},"isRequired":{"type":"integer","example":1,"default":0},"displayOrder":{"type":"integer","example":1,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-22 19:57:37"},"updatedTimestamp":{"type":"string","example":"2018-10-22 20:04:21"},"links":{"type":"object","properties":{"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"put":{"summary":"Update a deal custom field","description":"","operationId":"update-a-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom field to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealCustomFieldMetum":{"properties":{"fieldLabel":{"type":"string","description":"Name of the field"},"fieldOptions":{"type":"array","description":"Options for the field. Only necessary if field_type is dropdown, multiselect, radio, or checkbox.","items":{"type":"string"}},"fieldDefault":{"type":"string","description":"Default value of the field"},"isFormVisible":{"type":"boolean","description":"Whether or not the field is visible on forms"},"displayOrder":{"type":"integer","description":"Order for displaying the field on Manage Fields page and deal profiles","format":"int32"},"isRequired":{"type":["integer","boolean"],"description":"When truthy, fieldDefault must also be provided."},"personalization":{"type":"string","minLength":1,"description":"Personalization tag; must be non-empty and unique across contact, deal and account fields."}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"dealCustomFieldMetum":{"fieldLabel":"New Title","fieldDefault":"Default Text","isFormVisible":1,"displayOrder":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealCustomFieldMetum\": {\n        \"id\": \"1\",\n        \"fieldLabel\": \"New Title\",\n        \"fieldType\": \"text\",\n        \"fieldOptions\": null,\n        \"fieldDefault\": \"Default Text\",\n        \"isFormVisible\": 1,\n        \"isRequired\": 0,\n        \"displayOrder\": 1,\n        \"createdTimestamp\": \"2018-10-22 19:57:37\",\n        \"updatedTimestamp\": \"2018-10-22 20:04:21\",\n        \"links\": {\n            \"dealCustomFieldData\": \"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"dealCustomFieldMetum":{"type":"object","properties":{"id":{"type":"string","example":"1"},"fieldLabel":{"type":"string","example":"New Title"},"fieldType":{"type":"string","example":"text"},"fieldOptions":{},"fieldDefault":{"type":"string","example":"Default Text"},"isFormVisible":{"type":"integer","example":1,"default":0},"isRequired":{"type":"integer","example":0,"default":0},"displayOrder":{"type":"integer","example":1,"default":0},"createdTimestamp":{"type":"string","example":"2018-10-22 19:57:37"},"updatedTimestamp":{"type":"string","example":"2018-10-22 20:04:21"},"links":{"type":"object","properties":{"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/:version/dealCustomFieldMeta/1/dealCustomFieldData"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a deal custom field","description":"","operationId":"delete-a-custom-deal-field-meta","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the field to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"message\": \"DealCustomFieldMeta deleted.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"DealCustomFieldMeta deleted."}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false}},"/dealEmail/attachment":{"get":{"summary":"Download a deal email attachment","description":"Internal: backs the attachment download links on a connected-mailbox email in the contact and deal activity streams. Fetches one attachment of an email synced through a connected mailbox from the mailbox provider (Nylas), using the grant of the deal connection the email came through, and streams the file back with the provider's Content-Type, Content-Disposition and Content-Length headers. Other HTTP methods are answered 200 with an empty body.","operationId":"download-a-deal-email-attachment","x-canonical-resource":"emailActivities","parameters":[{"name":"connectionid","in":"query","description":"ID of the deal connection (the connected mailbox) the email was synced through. An unknown ID returns 404.","required":true,"schema":{"type":"integer"}},{"name":"file","in":"query","description":"The mailbox provider's ID of the attachment, as listed on the deal email.","required":true,"schema":{"type":"string"}},{"name":"messageid","in":"query","description":"The mailbox provider's ID of the message the attachment belongs to (the deal email's `emailmessageid`).","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The attachment's bytes. The media type is the attachment's own, as the mailbox provider reports it.","headers":{"Content-Disposition":{"description":"The mailbox provider's Content-Disposition for the file, normally an attachment with its file name.","schema":{"type":"string"}},"Content-Length":{"description":"Size of the file in bytes, as the mailbox provider reports it.","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"No deal connection with this `connectionid`, or the mailbox provider did not return the file (the `message` is then empty). The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record could not be found.","example":"No Result found for DealConnection with id 8"}}}}}},"500":{"description":"`file` or `messageid` is missing, or the deal connection has no mailbox provider grant.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A generic message; the cause is only in the server log.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/dealEmail/backfill":{"get":{"summary":"Backfill a connected mailbox's emails (retired)","description":"Internal and retired. This endpoint imported a Nylas v2 mailbox connection's older emails for a date range. Nylas v2 mailbox connections are no longer supported, so every request is logged as a warning and answered 404 with a plain-text message; nothing is read or changed and no parameter is read. Legacy endpoint with no method guard: any HTTP method gets the same answer; GET is the documented verb and the one the old callers used.","operationId":"backfill-deal-emails","x-canonical-resource":"emailActivities","responses":{"404":{"description":"Always. The body is the plain text `V2 backfill is no longer supported`, not JSON.","content":{"text/plain":{"schema":{"type":"string","example":"V2 backfill is no longer supported"}}}}},"deprecated":true,"x-internal":true}},"/dealEmail/message_html":{"get":{"summary":"Retrieve a deal email's HTML body","description":"Internal: backs the full email shown in the contact and deal activity streams, which load it into an iframe or the email detail view. Returns one deal email (an email synced from or sent through a connected mailbox) as a standalone HTML page. The page body is the email's HTML part; when the email has none, its plain-text part with tags stripped and line breaks turned into `<br>`. The mailbox provider's open-tracking image is removed and the HTML is XSS-purified, so displaying it is safe and does not count as an open. Other HTTP methods are answered 200 with an empty body.","operationId":"retrieve-a-deal-email-html-body","x-canonical-resource":"emailActivities","parameters":[{"name":"id","in":"query","description":"ID of the deal email.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The email as an HTML document: `<html><head></head><body style=\"...\">` around the sanitized message, styled for display in the app.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"No deal email with this `id`, or `id` is missing. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record could not be found.","example":"No Result found for DealEmail with id 1000"}}}}}}},"deprecated":false,"x-internal":true}},"/dealEmail/message_text":{"get":{"summary":"Retrieve a deal email preview","description":"Internal: backs the short email previews in the activity stream and in the notes, tasks and emails tabs. Returns the first 90 characters of one deal email's text as a standalone HTML page: the HTML part when the email has one, otherwise the plain-text part, with tags stripped before truncating, then the mailbox provider's open-tracking image removed and the result XSS-purified. When `deal_email_id` is missing, empty, `0` or the string `false`, the response is 200 with an empty body. Other HTTP methods are answered 200 with an empty body.","operationId":"retrieve-a-deal-email-preview","x-canonical-resource":"emailActivities","parameters":[{"name":"deal_email_id","in":"query","description":"ID of the deal email.","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The preview as an HTML document: `<html><head></head><body style=\"...\">` around at most 90 characters of the email's text. Empty when `deal_email_id` is missing, empty, `0` or `false`.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"No deal email with this `deal_email_id`. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record could not be found.","example":"No Result found for DealEmail with id 1000"}}}}}}},"deprecated":false,"x-internal":true}},"/dealEmail/messages":{"get":{"summary":"List a connected mailbox's messages (retired)","description":"Internal and retired. This endpoint listed a Nylas v2 mailbox connection's messages for a date range. Nylas v2 mailbox connections are no longer supported, so every request is logged as a warning and answered 404 with a plain-text message; nothing is read or changed and no parameter is read. Legacy endpoint with no method guard: any HTTP method gets the same answer; GET is the documented verb and the one the old callers used.","operationId":"list-deal-email-messages","x-canonical-resource":"emailActivities","responses":{"404":{"description":"Always. The body is the plain text `V2 connections are no longer supported`, not JSON.","content":{"text/plain":{"schema":{"type":"string","example":"V2 connections are no longer supported"}}}}},"deprecated":true,"x-internal":true}},"/dealEmail/nylasDbStatus":{"get":{"summary":"Retrieve a connected mailbox's Nylas status (retired)","description":"Internal and retired. This support endpoint returned the Nylas account and token information held for a Nylas v2 mailbox connection. Nylas v2 mailbox connections are no longer supported, so every request is logged as a warning and answered 404 with a plain-text message; nothing is read or changed and no parameter is read. Legacy endpoint with no method guard: any HTTP method gets the same answer; GET is the documented verb and the one the old callers used.","operationId":"retrieve-deal-email-nylas-status","x-canonical-resource":"emailActivities","responses":{"404":{"description":"Always. The body is the plain text `V2 connections are no longer supported`, not JSON.","content":{"text/plain":{"schema":{"type":"string","example":"V2 connections are no longer supported"}}}}},"deprecated":true,"x-internal":true}},"/dealEmail/nylasMessageSearch":{"get":{"summary":"Search a connected mailbox's Nylas messages (retired)","description":"Internal and retired. This support endpoint searched Nylas for a Nylas v2 mailbox connection's messages by date range and to, from or subject, to find emails missing from the app. Nylas v2 mailbox connections are no longer supported, so every request is logged as a warning and answered 404 with a plain-text message; nothing is read or changed and no parameter is read. Legacy endpoint with no method guard: any HTTP method gets the same answer; GET is the documented verb and the one the old callers used.","operationId":"search-deal-email-nylas-messages","x-canonical-resource":"emailActivities","responses":{"404":{"description":"Always. The body is the plain text `V2 connections are no longer supported`, not JSON.","content":{"text/plain":{"schema":{"type":"string","example":"V2 connections are no longer supported"}}}}},"deprecated":true,"x-internal":true}},"/dealEmail/sentimentFeedback":{"post":{"summary":"Send feedback on a deal email's sentiment","description":"Internal: backs the agree/disagree buttons of the sentiment feedback modal on a deal email. Queues the user's rating of the sentiment detected for one deal email, together with the email's sentiment analysis UUID, for the sentiment analysis service. The deal email itself is not changed. The fields are read from the form-encoded body or the query string; a JSON body is not read. Other HTTP methods are answered 405.","operationId":"send-deal-email-sentiment-feedback","x-canonical-resource":"emailActivities","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["dealEmailId","feedbackRating"],"properties":{"dealEmailId":{"type":"integer","description":"ID of the deal email the feedback is about. The email must have a sentiment analysis UUID.","example":1},"feedbackRating":{"type":"integer","enum":[0,1],"description":"1 when the user agrees with the detected sentiment, 0 when they disagree. Cast to an integer before it is checked, so a non-numeric value is read as 0.","example":1}}}}}},"responses":{"200":{"description":"The feedback was queued. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"integer","description":"Always 1.","example":1},"message":{"type":"string","description":"Always `Feedback sent.`","example":"Feedback sent."}}}}}},"422":{"description":"`dealEmailId` or `feedbackRating` is missing, `feedbackRating` is not 0 or 1, there is no deal email with this ID, or the deal email has no sentiment analysis UUID.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the failure.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string.","example":"422"},"detail":{"type":"string","description":"Why the request failed.","example":"DealEmail 1 does not have a sentiment uuid"}}}}}}}}},"500":{"description":"The feedback could not be sent to the sentiment analysis queue.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A generic message; the cause is only in the server log.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/dealEmail/setSentiment":{"put":{"summary":"Set a deal email's sentiment","description":"Internal: stores a sentiment result on one deal email, replacing any earlier one: the sentiment label (saved as its number: MIXED 4, POSITIVE 3, NEUTRAL 2, NEGATIVE 1, TBD 0) and the UUID of the analysis that produced it, which sentiment feedback is later sent against. Other HTTP methods are answered 200 with an empty body.","operationId":"set-a-deal-email-sentiment","x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dealEmailId","sentiment","sentiment_uuid"],"properties":{"dealEmailId":{"type":"integer","description":"ID of the deal email. A numeric string is accepted; a non-integer value returns 422 and an unknown or missing ID returns 404.","example":1},"sentiment":{"type":"string","description":"The sentiment label, case-insensitive: MIXED, POSITIVE, NEUTRAL, NEGATIVE or TBD. Any other value, including a number, returns 422.","example":"NEUTRAL"},"sentiment_uuid":{"type":"string","description":"UUID of the sentiment analysis that produced this result. Must be a JSON string.","example":"fc5812d91f034e56be68174b9167211b"}}}}}},"responses":{"200":{"description":"The sentiment was saved. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true.","example":true}}}}}},"404":{"description":"No deal email with this `dealEmailId`, or `dealEmailId` is missing. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record could not be found.","example":"No Result found for DealEmail with id 1"}}}}}},"422":{"description":"`dealEmailId` is not an integer, `sentiment` is not one of the labels, or `sentiment_uuid` is not a string. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the failure.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as a number.","example":422},"title":{"type":"string","description":"Translated name of the error class."},"detail":{"type":"string","description":"Why the request failed (translated)."}}}}}}}}}},"deprecated":false,"x-internal":true}},"/dealEmail/uniqueFromAddresses":{"get":{"summary":"List deal email sender addresses","description":"Internal: backs the sender filter of the Sales Engagement \"All one-to-one emails\" report. Returns the distinct sender addresses of the deal emails that were sent from the platform through a connected mailbox. For an email with no contact, the address of its `from` recipient is used; otherwise the email's from address. Not paged. Requires CRM on the account and the deals permission on the user's group. Only GET is routed; other methods are answered 405.","operationId":"list-deal-email-sender-addresses","x-canonical-resource":"emailActivities","parameters":[{"name":"search","in":"query","description":"Return only addresses of emails whose from address or `from` recipient address contains this text. Surrounding whitespace is trimmed.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"The sender addresses. When nothing matches, `emails` is an empty list.","content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","description":"Each distinct sender address once, in no guaranteed order.","items":{"type":["string","null"],"example":"sales@example.com"}}}}}}},"403":{"description":"The account does not have CRM (`Upgrade your account to enable the CRM`), or the user's group lacks the deals permission (`Forbidden`).","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the failure.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string.","example":"403"},"detail":{"type":"string","description":"Why the request failed.","example":"Upgrade your account to enable the CRM"}}}}}}}}}},"deprecated":false,"x-internal":true}},"/dealGroup/change_deal_group":{"post":{"summary":"Move a pipeline's stages and deals to another pipeline and delete it","description":"Internal: backs \"Move stages to a different pipeline\" when a pipeline is deleted in the app. Queues a background process that moves every stage and every deal of `fromDealGroupId` to `toDealGroupId`, then deletes `fromDealGroupId`. The two IDs are not compared, so send two different pipelines. Needs the CRM, the deals permission and both the edit-pipelines and delete-pipelines permissions. The IDs are read from the form-encoded body or the query string, not from a JSON body. Served by a legacy api/3 file that answers only POST.","operationId":"move-pipeline-stages-and-deals","x-canonical-resource":"dealGroup","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["fromDealGroupId","toDealGroupId"],"properties":{"fromDealGroupId":{"type":"integer","description":"ID of the pipeline to empty and delete","example":4},"toDealGroupId":{"type":"integer","description":"ID of the pipeline that receives the stages and deals","example":1}}},"example":{"fromDealGroupId":4,"toDealGroupId":1}}}},"responses":{"200":{"description":"The work was queued as a background process; it has not run yet.","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","description":"Outcome of queueing","properties":{"success":{"type":"boolean","description":"Always true","example":true}}}}},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the CRM, or the user lacks the deals permission or either pipeline permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Forbidden without the deals permission, \"Upgrade your account to enable the CRM\" without the CRM, otherwise the permission that is missing","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"A pipeline does not exist, or the background process could not be queued. The body is a plain-text message, not JSON: \"The pipeline with an ID of 4 does not exist.\" for `fromDealGroupId`, \"You must reassign stages and deals to an existing pipeline. The pipeline with an ID of 9 does not exist.\" for `toDealGroupId`.","content":{"text/plain":{"schema":{"type":"string"},"example":"The pipeline with an ID of 4 does not exist."}}}},"x-internal":true}},"/dealGroup/delete_deal_group":{"delete":{"summary":"Delete a pipeline with its stages and deals","description":"Internal: backs \"Delete all stages and deals\" when a pipeline is deleted in the app. Queues a background process that deletes every deal of the pipeline, then every stage, then the pipeline itself. Needs the CRM, the deals permission and the delete-pipelines permission, plus the delete-deals permission when the pipeline has deals. Served by a legacy api/3 file that answers only DELETE.","operationId":"delete-pipeline-with-stages-and-deals","x-canonical-resource":"dealGroup","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dealGroupId"],"properties":{"dealGroupId":{"type":["integer","string"],"description":"ID of the pipeline to delete; must be numeric","example":4}}},"example":{"dealGroupId":4}}}},"responses":{"200":{"description":"The work was queued as a background process; it has not run yet.","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","description":"Outcome of queueing","properties":{"success":{"type":"boolean","description":"Always true","example":true}}}}},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the CRM, or the user lacks the deals permission, the delete-pipelines permission, or the delete-deals permission while the pipeline has deals.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Forbidden without the deals permission, \"Upgrade your account to enable the CRM\" without the CRM, otherwise the permission that is missing","example":"You do not have permission to delete pipelines"}}}}}},"example":{"errors":[{"status":"403","detail":"You do not have permission to delete pipelines"}]}}}},"422":{"description":"`dealGroupId` is missing or not numeric (checked first), the pipeline does not exist, or the background process could not be queued. The body is a plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"},"example":"\"dealGroupId\" is a required parameter. No dealGroupId specified."}}}},"x-internal":true}},"/dealGroup/get_inaccessible_deal_groups":{"get":{"summary":"Retrieve inaccessible pipelines by user","description":"Retrieve pipelines that given user doesn't have access to","operationId":"retrieve-inaccessible-pipelines-by-user","x-canonical-resource":"dealGroup","parameters":[{"name":"dealIds[]","in":"query","description":"Deal Ids","required":true,"schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"userId","in":"query","description":"User's Id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"dealGroups\": [\n        {\n            \"title\": \"p1\",\n            \"currency\": \"usd\",\n            \"autoassign\": \"0\",\n            \"allusers\": \"1\",\n            \"allgroups\": \"0\",\n            \"win_probability_initialize_date\": \"0000-00-00 00:00:00\",\n            \"cdate\": \"2021-08-10T12:16:06-05:00\",\n            \"udate\": \"2021-11-09T10:09:25-06:00\",\n            \"links\": {\n                \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/1/stages\",\n                \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupUsers\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupGroups\",\n                \"winProbabilityFeatures\": \"https://:account.api-us1.com/api/3/dealGroups/1/winProbabilityFeatures\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"title\": \"p6\",\n            \"currency\": \"usd\",\n            \"autoassign\": \"0\",\n            \"allusers\": \"1\",\n            \"allgroups\": \"0\",\n            \"win_probability_initialize_date\": \"0000-00-00 00:00:00\",\n            \"cdate\": \"2021-11-09T15:14:06-06:00\",\n            \"udate\": \"2021-11-09T15:36:53-06:00\",\n            \"links\": {\n                \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/6/stages\",\n                \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/6/dealGroupUsers\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/6/dealGroupGroups\",\n                \"winProbabilityFeatures\": \"https://:account.api-us1.com/api/3/dealGroups/6/winProbabilityFeatures\"\n            },\n            \"id\": \"6\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"dealGroups":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"p1"},"currency":{"type":"string","example":"usd"},"autoassign":{"type":"string","example":"0"},"allusers":{"type":"string","example":"1"},"allgroups":{"type":"string","example":"0"},"win_probability_initialize_date":{"type":"string","example":"0000-00-00 00:00:00"},"cdate":{"type":"string","example":"2021-08-10T12:16:06-05:00"},"udate":{"type":"string","example":"2021-11-09T10:09:25-06:00"},"links":{"type":"object","properties":{"stages":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/stages"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupUsers"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupGroups"},"winProbabilityFeatures":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/winProbabilityFeatures"}}},"id":{"type":"string","example":"1"}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Missing userId parameter":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid Input Parameter\",\n            \"detail\": \"Parameter userId is required.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid Input Parameter"},"detail":{"type":"string","example":"Parameter userId is required."}}}}}}},"text/plain":{"examples":{"Missing dealIds parameter":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid Input Parameter\",\n            \"detail\": \"Parameter dealIds is required.\"\n        }\n    ]\n}"},"Non-existing user":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid Input Parameter\",\n            \"detail\": \"User was not found.\"\n        }\n    ]\n}"}},"schema":{"oneOf":[{"title":"Missing dealIds parameter","type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid Input Parameter"},"detail":{"type":"string","example":"Parameter dealIds is required."}}}}}},{"title":"Non-existing user","type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid Input Parameter"},"detail":{"type":"string","example":"User was not found."}}}}}}]}}}}},"deprecated":false,"x-readme":{"code-samples":[{"language":"text","code":"/dealGroup/get_inaccessible_deal_groups?userId=2&dealIds[]=1&dealIds[]=2&dealIds[]=3&dealIds[]=4&dealIds[]=5"}],"samples-languages":["text"]}}},"/dealGroup/get_round_robin_users":{"get":{"summary":"List the users a pipeline's round-robin assignment would use","description":"Internal: backs the round-robin user list of the pipeline editor. Returns the users that match `users` and `groups`, sorted by first name: the users listed in `users[]` when it is sent (then `groups[]` is ignored), every user of the groups in `groups[]` when only that is sent, and every user in the account when neither is. `dealGroupId` must be sent but does not change the answer. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses. The response is JSON but is not sent with a JSON Content-Type.","operationId":"list-pipeline-round-robin-users","x-canonical-resource":"dealGroup","parameters":[{"name":"dealGroupId","in":"query","description":"ID of the pipeline being edited. Required, but only checked for presence.","required":true,"schema":{"type":"integer"},"example":4},{"name":"users[]","in":"query","description":"IDs of the users to return. Must be sent as a list (users[]=); a single value fails the request.","required":false,"schema":{"type":"array","items":{"type":"integer"}},"style":"form","explode":true,"example":[1,2]},{"name":"groups[]","in":"query","description":"IDs of user groups whose users to return; ignored when users[] is sent. Must be sent as a list (groups[]=).","required":false,"schema":{"type":"array","items":{"type":"integer"}},"style":"form","explode":true,"example":[3]}],"responses":{"200":{"description":"The users, sorted by first name","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"firstName":{"type":"string","description":"First name of the user","example":"Jane"},"lastName":{"type":"string","description":"Last name of the user","example":"Doe"},"email":{"type":"string","description":"Email address of the user","example":"jane@example.com"},"emailHash":{"type":"string","description":"MD5 of the lower-cased, trimmed email address, for Gravatar images","example":"9e26471d35a78862c17e467d87cddedf"},"group":{"type":"string","description":"Name of the user's group","example":"Sales"}}}},"example":[{"firstName":"Jane","lastName":"Doe","email":"jane@example.com","emailHash":"9e26471d35a78862c17e467d87cddedf","group":"Sales"}]}}},"422":{"description":"`dealGroupId` is missing.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"422"},"detail":{"type":"string","description":"Names the missing parameter","example":"\"dealGroupId\" is a required parameter."}}}}}},"example":{"errors":[{"status":"422","detail":"\"dealGroupId\" is a required parameter."}]}}}}},"x-internal":true}},"/dealGroup/save_deal_group_relationships":{"post":{"summary":"Set a pipeline's auto-assign users and permitted user groups","description":"Internal: backs the pipeline editor. `users` are the users new deals in the pipeline may be auto-assigned to (dealGroupUsers) and `groups` the user groups that may manage it (dealGroupGroups); both are complete lists. A user or group that is listed and has no record yet gets one, a record whose user or group is not listed is deleted, and the rest are left alone; the changes are made in one transaction. Adding a user resets the pipeline's cached deal totals. Needs the CRM, the deals permission and the edit-pipelines permission. The `allusers`, `allgroups` and `autoassign` settings of the pipeline are not changed.","operationId":"set-pipeline-user-and-group-access","x-canonical-resource":"dealGroup","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dealGroup","users","groups"],"properties":{"dealGroup":{"type":"integer","description":"ID of the pipeline","example":4},"users":{"type":"array","description":"IDs of every user new deals in the pipeline may be auto-assigned to; each one without a record yet must exist","items":{"type":"integer"},"example":[1,2]},"groups":{"type":"array","description":"IDs of every user group that may manage the pipeline; each one without a record yet must exist","items":{"type":"integer"},"example":[3]}}},"example":{"dealGroup":4,"users":[1,2],"groups":[3]}}}},"responses":{"200":{"description":"The pipeline with its access records after the change","content":{"application/json":{"schema":{"type":"object","properties":{"dealGroupUsers":{"type":"array","description":"The pipeline's auto-assign user records","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the auto-assign user record","example":"12"},"dealGroup":{"type":"string","description":"ID of the pipeline","example":"4"},"user":{"type":"string","description":"ID of a user new deals may be auto-assigned to","example":"1"},"cdate":{"type":["string","null"],"description":"When the record was created, ISO 8601 with offset; null when unknown","example":"2026-10-15T10:52:26-05:00"},"links":{"type":"object","description":"URLs of the record's pipeline and user","additionalProperties":{"type":"string"}}}}},"dealGroupGroups":{"type":"array","description":"The pipeline's user group records","items":{"type":"object","properties":{"id":{"type":"string","description":"ID of the user group record","example":"7"},"d_groupid":{"type":"string","description":"ID of the pipeline (column name)","example":"4"},"groupid":{"type":"string","description":"ID of the user group (column name)","example":"3"},"dealGroup":{"type":"string","description":"ID of the pipeline","example":"4"},"group":{"type":"string","description":"ID of a user group that may manage the pipeline","example":"3"},"cdate":{"type":["string","null"],"description":"When the record was created, ISO 8601 with offset; null when unknown","example":"2026-10-15T10:52:26-05:00"},"links":{"type":"object","description":"URLs of the record's pipeline and group","additionalProperties":{"type":"string"}}}}},"dealGroup":{"type":"object","description":"The pipeline after the change","properties":{"id":{"type":"string","description":"ID of the pipeline","example":"4"},"title":{"type":"string","description":"Name of the pipeline","example":"Qualifications"},"currency":{"type":"string","description":"Default currency of new deals in the pipeline","example":"usd"},"autoassign":{"type":"string","description":"Auto-assign option for new deals: 0 off, 1 round robin, 2 by deal value","example":"1"},"allusers":{"type":"string","description":"1 when new deals are auto-assigned to every user, 0 when only to the users in dealGroupUsers","example":"0"},"allgroups":{"type":"string","description":"1 when every user group may manage the pipeline, 0 when only the groups in dealGroupGroups","example":"0"},"win_probability_initialize_date":{"type":["string","null"],"description":"When win probability was turned on for the pipeline, as stored; null while it is off","example":null},"cdate":{"type":["string","null"],"description":"When the pipeline was created, ISO 8601 with offset","example":"2017-03-30T12:11:30-05:00"},"udate":{"type":["string","null"],"description":"When the pipeline was last updated, ISO 8601 with offset","example":"2017-03-30T13:44:32-05:00"},"source":{"type":"string","description":"Where the pipeline was created: empty for the app, partner-hub for Partner Hub","example":""},"dealGroupUsers":{"type":"array","description":"IDs of the pipeline's auto-assign user records, the same as in the top-level dealGroupUsers","items":{"type":"string"},"example":["12"]},"dealGroupGroups":{"type":"array","description":"IDs of the pipeline's user group records, the same as in the top-level dealGroupGroups","items":{"type":"string"},"example":["7"]},"links":{"type":"object","description":"URLs of the pipeline's stages, dealGroupUsers, dealGroupGroups and winProbabilityFeatures","additionalProperties":{"type":"string"}}}},"meta":{"type":"object","description":"What was removed","properties":{"deletedDealGroupUsers":{"type":"array","description":"IDs of the auto-assign user records deleted","items":{"type":"string"},"example":["11"]},"deletedDealGroupGroups":{"type":"array","description":"IDs of the user group records deleted","items":{"type":"string"},"example":[]}}}}},"example":{"dealGroupUsers":[{"dealGroup":"4","user":"1","cdate":"2026-10-15T10:52:26-05:00","links":{"dealGroup":"https://:account.api-us1.com/api/3/dealGroupUsers/12/dealGroup","user":"https://:account.api-us1.com/api/3/dealGroupUsers/12/user"},"id":"12"}],"dealGroupGroups":[{"d_groupid":"4","groupid":"3","cdate":"2026-10-15T10:52:26-05:00","links":{"dealGroup":"https://:account.api-us1.com/api/3/dealGroupGroups/7/dealGroup","group":"https://:account.api-us1.com/api/3/dealGroupGroups/7/group"},"dealGroup":"4","group":"3","id":"7"}],"dealGroup":{"title":"Qualifications","currency":"usd","autoassign":"1","allusers":"0","allgroups":"0","win_probability_initialize_date":null,"cdate":"2017-03-30T12:11:30-05:00","udate":"2017-03-30T13:44:32-05:00","source":"","dealGroupUsers":["12"],"dealGroupGroups":["7"],"links":{"stages":"https://:account.api-us1.com/api/3/dealGroups/4/stages","dealGroupUsers":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupUsers","dealGroupGroups":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupGroups","winProbabilityFeatures":"https://:account.api-us1.com/api/3/dealGroups/4/winProbabilityFeatures"},"id":"4"},"meta":{"deletedDealGroupUsers":["11"],"deletedDealGroupGroups":[]}}}}},"403":{"description":"The account does not have the CRM, or the user lacks the deals permission or the edit-pipelines permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Forbidden without the deals permission, \"Upgrade your account to enable the CRM\" without the CRM, otherwise the permission that is missing","example":"You do not have permission to edit pipelines"}}}}}},"example":{"errors":[{"status":"403","detail":"You do not have permission to edit pipelines"}]}}}},"404":{"description":"The pipeline, or a listed user or group that has no record yet, does not exist. Nothing is changed.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found","example":"No Result found for DealGroup with id 99"}}}}}},"422":{"description":"`users` or `groups` is missing. Checked after the pipeline is found.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"string","description":"Names the missing field","example":"'users' required"}}},"example":{"errors":"'users' required"}}}}},"x-internal":true}},"/dealGroups":{"post":{"summary":"Create a pipeline","description":"Create a new pipeline","operationId":"create-a-pipeline","x-canonical-resource":"dealGroups","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealGroup":{"properties":{"title":{"type":"string","description":"Pipeline's title."},"currency":{"type":"string","description":"Default currency to assign to new deals that belong to this deal group."},"allgroups":{"type":"integer","description":"Whether all user groups have permission to manage this pipeline. Can be either `1` or `0`. If `1`, all user groups can manage this pipeline. If `0`, only user groups in `dealGroup.groups` parameter can manage this pipeline.","default":1,"format":"int32"},"allusers":{"type":"integer","description":"Whether new deals get auto-assigned to all users. Can be either `1` or `0`. If `1`, new deals are auto-assigned to all users unless auto-assign is disabled. If `0`, new deals are auto-assigned to only the users in `dealGroup.users` parameter.","default":0,"format":"int32"},"autoassign":{"type":"integer","description":"Deal auto-assign option. Can be one of `0`, `1`, and `2`. If `0`, auto-assign is disabled. If `1`, Round Robin method is used to auto-assign new deals. If `2`, deals are distributed based on deal values.","default":1,"format":"int32"},"users":{"type":"array","description":"List of user ids to auto-assign new deals to unless auto-assign option is disabled.","items":{"type":"string"}},"groups":{"type":"array","description":"List of user group ids to allow managing this pipeline.","items":{"type":"string"}},"source":{"type":"string","enum":["","partner-hub"]},"stages":{"type":"array","maxItems":50,"items":{"type":"object","required":["title"],"properties":{"title":{"type":"string","description":"Stage title; required, may not contain HTML."},"order":{"type":["integer","string"],"minimum":1,"description":"Positive integer; defaults to the stage's position in the array."},"color":{"type":"string","pattern":"^#?[0-9A-Fa-f]{6}$","description":"Six-digit hex colour, optional leading #; when absent the standard stage palette is cycled."}},"additionalProperties":false},"description":"Stages to create the pipeline with, in order. When absent or empty the default stages are created."}},"required":["title","currency"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealGroup":{"allgroups":1,"allusers":0,"autoassign":1,"currency":"eur","title":"Qualifications","users":["3","4"]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealGroup\": {\n    \"allgroups\": 1,\n    \"allusers\": 0,\n    \"autoassign\": 1,\n    \"cdate\": \"2017-03-30T12:12:41-05:00\",\n    \"currency\": \"eur\",\n    \"dealGroupGroups\": [],\n    \"dealGroupUsers\": [\n      \"6\",\n      \"7\"\n    ],\n    \"id\": \"5\",\n    \"links\": {\n      \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupGroups\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupUsers\",\n      \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/5/stages\"\n    },\n    \"stages\": [\n      \"12\",\n      \"13\",\n      \"14\"\n    ],\n    \"title\": \"Qualifications\",\n    \"udate\": \"2017-03-30T12:12:41-05:00\"\n  },\n  \"dealGroupGroups\": [],\n  \"dealGroupUsers\": [\n    {\n      \"cdate\": null,\n      \"dealGroup\": \"5\",\n      \"id\": \"6\",\n      \"links\": {\n        \"dealGroup\": \"https://:account.api-us1.com/api/3/dealGroupUsers/6/dealGroup\",\n        \"user\": \"https://:account.api-us1.com/api/3/dealGroupUsers/6/user\"\n      },\n      \"user\": \"3\"\n    },\n    {\n      \"cdate\": null,\n      \"dealGroup\": \"5\",\n      \"id\": \"7\",\n      \"links\": {\n        \"dealGroup\": \"https://:account.api-us1.com/api/3/dealGroupUsers/7/dealGroup\",\n        \"user\": \"https://:account.api-us1.com/api/3/dealGroupUsers/7/user\"\n      },\n      \"user\": \"4\"\n    }\n  ],\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"18D499\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"12\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/12/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"To Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"32B0FC\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"13\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/13/group\"\n      },\n      \"order\": \"2\",\n      \"title\": \"In Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"E6CE4B\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"14\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/14/group\"\n      },\n      \"order\": \"3\",\n      \"title\": \"Follow Up\",\n      \"udate\": null,\n      \"width\": \"280\"\n    }\n  ]\n}\n"}},"schema":{"type":"object","properties":{"dealGroup":{"type":"object","properties":{"allgroups":{"type":"integer","example":1,"default":0},"allusers":{"type":"integer","example":0,"default":0},"autoassign":{"type":"integer","example":1,"default":0},"cdate":{"type":"string","example":"2017-03-30T12:12:41-05:00"},"currency":{"type":"string","example":"eur"},"dealGroupGroups":{"type":"array"},"dealGroupUsers":{"type":"array","items":{"type":"string","example":"6"}},"id":{"type":"string","example":"5"},"links":{"type":"object","properties":{"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupGroups"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupUsers"},"stages":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/5/stages"}}},"stages":{"type":"array","items":{"type":"string","example":"12"}},"title":{"type":"string","example":"Qualifications"},"udate":{"type":"string","example":"2017-03-30T12:12:41-05:00"}}},"dealGroupGroups":{"type":"array"},"dealGroupUsers":{"type":"array","items":{"type":"object","properties":{"cdate":{},"dealGroup":{"type":"string","example":"5"},"id":{"type":"string","example":"6"},"links":{"type":"object","properties":{"dealGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroupUsers/6/dealGroup"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroupUsers/6/user"}}},"user":{"type":"string","example":"3"}}}},"dealStages":{"type":"array","items":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{},"color":{"type":"string","example":"18D499"},"dealOrder":{"type":"string","example":"next-action DESC"},"group":{"type":"string","example":"5"},"id":{"type":"string","example":"12"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/12/group"}}},"order":{"type":"string","example":"1"},"title":{"type":"string","example":"To Contact"},"udate":{},"width":{"type":"string","example":"280"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all pipelines","description":"Retrieve all existing pipelines","operationId":"list-all-pipelines","x-canonical-resource":"dealGroups","parameters":[{"name":"filters[title]","in":"query","description":"Filter by pipeline's title. The filter matches any pipeline titles that contain the provided title (i.e. \"Contact\" matches all of \"In Contact\", \"To Contact\", and \"Contact Pipeline\").","schema":{"type":"string"}},{"name":"filters[have_stages]","in":"query","description":"Filter by whether pipelines have deal stages. Can be either `1` or `0`. If `1`, only pipelines with at least one stage will be returned.","schema":{"type":"integer","format":"int32"}},{"name":"orders[title]","in":"query","description":"Order by Pipeline's title","schema":{"type":"string","default":"ASC"}},{"name":"orders[popular]","in":"query","description":"Order by number of deals each pipeline has. If pipelines have same number of deals, pipelines' created dates are used to determine the order.","schema":{"type":"string","default":"ASC"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealGroups\": [\n    {\n      \"allgroups\": \"1\",\n      \"allusers\": \"1\",\n      \"autoassign\": \"1\",\n      \"cdate\": \"2017-01-16T14:51:57-06:00\",\n      \"currency\": \"usd\",\n      \"id\": \"1\",\n      \"links\": {\n        \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupGroups\",\n        \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupUsers\",\n        \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/1/stages\"\n      },\n      \"stages\": [\n        \"1\",\n        \"2\"\n      ],\n      \"title\": \"Pipeline A\",\n      \"udate\": \"2017-03-01T11:06:32-06:00\"\n    },\n    {\n      \"allgroups\": \"1\",\n      \"allusers\": \"1\",\n      \"autoassign\": \"0\",\n      \"cdate\": \"2017-03-01T14:45:16-06:00\",\n      \"currency\": \"usd\",\n      \"id\": \"5\",\n      \"links\": {\n        \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupGroups\",\n        \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/5/dealGroupUsers\",\n        \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/5/stages\"\n      },\n      \"stages\": [\n        \"12\",\n        \"13\",\n        \"14\"\n      ],\n      \"title\": \"Pipeline Yesterday\",\n      \"udate\": \"2017-03-01T15:07:18-06:00\"\n    }\n  ],\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-01-20T09:27:32-06:00\",\n      \"color\": \"C481DF\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"1\",\n      \"id\": \"1\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/1/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"Stage 1\",\n      \"udate\": \"2017-03-01T11:06:14-06:00\",\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-01-20T09:27:34-06:00\",\n      \"color\": \"00ECC5\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"1\",\n      \"id\": \"2\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/2/group\"\n      },\n      \"order\": \"2\",\n      \"title\": \"Stage 2\",\n      \"udate\": \"2017-03-01T11:06:20-06:00\",\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"18D499\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"12\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/12/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"To Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"32B0FC\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"13\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/13/group\"\n      },\n      \"order\": \"2\",\n      \"title\": \"In Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"E6CE4B\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"5\",\n      \"id\": \"14\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/14/group\"\n      },\n      \"order\": \"3\",\n      \"title\": \"Follow Up\",\n      \"udate\": null,\n      \"width\": \"280\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealGroups":{"type":"array","items":{"type":"object","properties":{"allgroups":{"type":"string","example":"1"},"allusers":{"type":"string","example":"1"},"autoassign":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-01-16T14:51:57-06:00"},"currency":{"type":"string","example":"usd"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupGroups"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/dealGroupUsers"},"stages":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/1/stages"}}},"stages":{"type":"array","items":{"type":"string","example":"1"}},"title":{"type":"string","example":"Pipeline A"},"udate":{"type":"string","example":"2017-03-01T11:06:32-06:00"}}}},"dealStages":{"type":"array","items":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{"type":"string","example":"2017-01-20T09:27:32-06:00"},"color":{"type":"string","example":"C481DF"},"dealOrder":{"type":"string","example":"next-action DESC"},"group":{"type":"string","example":"1"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/1/group"}}},"order":{"type":"string","example":"1"},"title":{"type":"string","example":"Stage 1"},"udate":{"type":"string","example":"2017-03-01T11:06:14-06:00"},"width":{"type":"string","example":"280"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealGroups/{id}":{"get":{"summary":"Retrieve a pipeline","description":"Retrieve an existing pipeline","operationId":"retrieve-a-pipeline","x-canonical-resource":"dealGroups","parameters":[{"name":"id","in":"path","description":"Pipeline's id","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealGroup\": {\n    \"allgroups\": \"1\",\n    \"allusers\": \"0\",\n    \"autoassign\": \"1\",\n    \"cdate\": \"2017-03-30T12:11:30-05:00\",\n    \"currency\": \"eur\",\n    \"id\": \"4\",\n    \"links\": {\n      \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupGroups\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupUsers\",\n      \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/4/stages\"\n    },\n    \"stages\": [\n      \"9\",\n      \"10\",\n      \"11\"\n    ],\n    \"title\": \"Qualifications\",\n    \"udate\": \"2017-03-30T13:44:32-05:00\"\n  },\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"18D499\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"4\",\n      \"id\": \"9\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/9/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"To Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"32B0FC\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"4\",\n      \"id\": \"10\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/10/group\"\n      },\n      \"order\": \"2\",\n      \"title\": \"In Contact\",\n      \"udate\": null,\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": null,\n      \"color\": \"E6CE4B\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"4\",\n      \"id\": \"11\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/11/group\"\n      },\n      \"order\": \"3\",\n      \"title\": \"Follow Up\",\n      \"udate\": null,\n      \"width\": \"280\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"dealGroup":{"type":"object","properties":{"allgroups":{"type":"string","example":"1"},"allusers":{"type":"string","example":"0"},"autoassign":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-03-30T12:11:30-05:00"},"currency":{"type":"string","example":"eur"},"id":{"type":"string","example":"4"},"links":{"type":"object","properties":{"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupGroups"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupUsers"},"stages":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/stages"}}},"stages":{"type":"array","items":{"type":"string","example":"9"}},"title":{"type":"string","example":"Qualifications"},"udate":{"type":"string","example":"2017-03-30T13:44:32-05:00"}}},"dealStages":{"type":"array","items":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{},"color":{"type":"string","example":"18D499"},"dealOrder":{"type":"string","example":"next-action DESC"},"group":{"type":"string","example":"4"},"id":{"type":"string","example":"9"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/9/group"}}},"order":{"type":"string","example":"1"},"title":{"type":"string","example":"To Contact"},"udate":{},"width":{"type":"string","example":"280"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a pipeline","description":"Update an existing pipeline","operationId":"update-a-pipeline","x-canonical-resource":"dealGroups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Pipeline's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealGroup":{"properties":{"title":{"type":"string","description":"Pipeline's title"},"currency":{"type":"string","description":"Default currency to assign to new deals that belong to this deal group."},"allgroups":{"type":"integer","description":"Whether all user groups have permission to manage this pipeline. Can be either `1` or `0`. If `1`, all user groups can manage this pipeline. If `0`, only user groups in `dealGroup.groups` parameter can manage this pipeline.","default":1,"format":"int32"},"allusers":{"type":"integer","description":"Whether new deals get auto-assigned to all users. Can be either `1` or `0`. If `1`, new deals are auto-assigned to all users unless auto-assign is disabled. If `0`, new deals are auto-assigned to only the users in `dealGroup.users` parameter.","default":0,"format":"int32"},"autoassign":{"type":"integer","description":"Deal auto-assign option. Can be one of `0`, `1`, and `2`. If `0`, auto-assign is disabled. If `1`, Round Robin method is used to auto-assign new deals. If `2`, deals are distributed based on deal values.","default":1,"format":"int32"},"users":{"type":"array","description":"List of user ids to auto-assign new deals to unless auto-assign option is disabled.","items":{"type":"string"}},"groups":{"type":"array","description":"List of user group ids to allow managing this pipeline.","items":{"type":"string"}},"source":{"type":"string","enum":["","partner-hub"]}},"required":[],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealGroup":{"allgroups":1,"allusers":0,"autoassign":1,"currency":"eur","title":"Qualifications","users":["3"],"groups":[]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealGroup\": {\n    \"allgroups\": 1,\n    \"allusers\": 0,\n    \"autoassign\": 1,\n    \"cdate\": \"2017-03-30T12:11:30-05:00\",\n    \"currency\": \"eur\",\n    \"dealGroupGroups\": [],\n    \"dealGroupUsers\": [\n      \"4\"\n    ],\n    \"id\": \"4\",\n    \"links\": {\n      \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupGroups\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupUsers\",\n      \"stages\": \"https://:account.api-us1.com/api/3/dealGroups/4/stages\"\n    },\n    \"title\": \"Qualifications\",\n    \"udate\": \"2017-03-30T13:44:32-05:00\"\n  },\n  \"dealGroupGroups\": [],\n  \"dealGroupUsers\": [\n    {\n      \"cdate\": null,\n      \"dealGroup\": \"4\",\n      \"id\": \"4\",\n      \"links\": {\n        \"dealGroup\": \"https://:account.api-us1.com/api/3/dealGroupUsers/4/dealGroup\",\n        \"user\": \"https://:account.api-us1.com/api/3/dealGroupUsers/4/user\"\n      },\n      \"user\": \"3\"\n    }\n  ]\n}\n"}},"schema":{"type":"object","properties":{"dealGroup":{"type":"object","properties":{"allgroups":{"type":"integer","example":1,"default":0},"allusers":{"type":"integer","example":0,"default":0},"autoassign":{"type":"integer","example":1,"default":0},"cdate":{"type":"string","example":"2017-03-30T12:11:30-05:00"},"currency":{"type":"string","example":"eur"},"dealGroupGroups":{"type":"array"},"dealGroupUsers":{"type":"array","items":{"type":"string","example":"4"}},"id":{"type":"string","example":"4"},"links":{"type":"object","properties":{"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupGroups"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/dealGroupUsers"},"stages":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroups/4/stages"}}},"title":{"type":"string","example":"Qualifications"},"udate":{"type":"string","example":"2017-03-30T13:44:32-05:00"}}},"dealGroupGroups":{"type":"array"},"dealGroupUsers":{"type":"array","items":{"type":"object","properties":{"cdate":{},"dealGroup":{"type":"string","example":"4"},"id":{"type":"string","example":"4"},"links":{"type":"object","properties":{"dealGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroupUsers/4/dealGroup"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/dealGroupUsers/4/user"}}},"user":{"type":"string","example":"3"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a pipeline","description":"Delete an existing pipeline","operationId":"delete-a-pipeline","x-canonical-resource":"dealGroups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Pipeline's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"deals exist":{"value":""}}}}}},"deprecated":false}},"/dealRoles":{"get":{"summary":"List all deal roles","description":"","operationId":"list-all-deal-roles","x-canonical-resource":"dealRoles","parameters":[{"name":"search","in":"query","description":"(optional string used to search for matching titles)","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n   \"dealRoles\":[\n      {\n         \"title\":\"Contributor\",\n         \"created_timestamp\":\"2019-09-10T13:01:49-05:00\",\n         \"updated_timestamp\":\"2019-09-10T13:01:49-05:00\",\n         \"links\":{\n            \"contactDeals\":\"https://example.activehosted.com/api/3/dealRoles/2/contactDeals\"\n         },\n         \"id\":\"2\"\n      },\n      {\n         \"title\":\"Decision Maker\",\n         \"created_timestamp\":\"2019-09-10T13:01:49-05:00\",\n         \"updated_timestamp\":\"2019-09-10T13:01:49-05:00\",\n         \"links\":{\n            \"contactDeals\":\"https://example.activehosted.com/api/3/dealRoles/1/contactDeals\"\n         },\n         \"id\":\"1\"\n      }\n   ],\n   \"meta\":{\n      \"total\":\"2\"\n   }\n}"}},"schema":{"type":"object","properties":{"dealRoles":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","examples":["Contributor"]},"created_timestamp":{"type":"string","examples":["2019-09-10T13:01:49-05:00"]},"updated_timestamp":{"type":"string","examples":["2019-09-10T13:01:49-05:00"]},"links":{"type":"object","properties":{"contactDeals":{"type":"string","examples":["https://example.activehosted.com/api/3/dealRoles/2/contactDeals"]}}},"id":{"type":"string","examples":["2"]}}}},"meta":{"type":"object","properties":{"total":{"type":"string","examples":["2"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_deal_roles","title":"List Deal Roles","description":"List the deal roles a contact can be assigned on a deal (the account starts with Contributor and Decision Maker, plus any roles it added), with their ids.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}},"post":{"summary":"Create a deal role","description":"","operationId":"create-a-deal-role","x-canonical-resource":"dealRoles","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealRole":{"type":"object","properties":{"title":{"type":"string","maxLength":64,"description":"Role title; HTML is reduced to plain text."}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealRole\":{\n    \"title\":\"Finance\",\n    \"created_timestamp\":\"2021-04-14T21:34:55-05:00\",\n    \"updated_timestamp\":\"2021-04-14T21:34:55-05:00\",\n    \"links\":{\"contactDeals\":\"https://example.activehosted.com/api/3/dealRoles/3/contactDeals\"},\n    \"id\":\"3\"\n  }\n}\n"}},"schema":{"type":"object","properties":{"dealRole":{"type":"object","properties":{"title":{"type":"string","example":"Finance"},"created_timestamp":{"type":"string","example":"2021-04-14T21:34:55-05:00"},"updated_timestamp":{"type":"string","example":"2021-04-14T21:34:55-05:00"},"links":{"type":"object","properties":{"contactDeals":{"type":"string","example":"https://example.activehosted.com/api/3/dealRoles/3/contactDeals"}}},"id":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealRoles/{id}":{"delete":{"summary":"Delete a deal role","description":"","operationId":"delete-a-deal-role","x-canonical-resource":"dealRoles","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal role's id","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealStage/change_deal_stage":{"post":{"summary":"Delete a deal stage and move its deals to another stage","description":"Internal: backs the delete-stage dialog of the deals board in the app when the user keeps the stage's deals. Queues a background job that moves every deal in stage `fromId` to stage `toId`, and to the pipeline `toId` belongs to, so the target stage may be in another pipeline, and then deletes stage `fromId`. The response only confirms that the job was queued: the deals are moved and the stage is deleted afterwards. `fromId` and `toId` are read from a form-encoded body, which is what the app sends, or from the query string; a JSON body is not read. The two IDs are not required to differ. Requires the CRM on the account and the deals permission. Only POST is accepted; other methods get 405.","operationId":"delete-a-deal-stage-and-move-its-deals","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["fromId","toId"],"properties":{"fromId":{"type":"integer","description":"ID of the stage to delete. Its deals are moved to `toId`.","example":4},"toId":{"type":"integer","description":"ID of the stage that receives the deals. Its pipeline becomes the deals' pipeline.","example":7}}},"example":{"fromId":4,"toId":7}}}},"responses":{"200":{"description":"The background job was queued. The body only confirms that; it does not report the job's outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageJobQueued"},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the CRM (`Upgrade your account to enable the CRM`), or the user does not have the deals permission (`Forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageErrorResponse"},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable the CRM"}]}}}},"422":{"description":"Nothing was queued: stage `fromId` does not exist (`The deal stage with an ID of 4 does not exist.`; a missing `fromId` reads as 0), stage `toId` does not exist (`You must reassign deals to an existing stage. The deal stage with an ID of 7 does not exist.`), or the job could not be created (`Bulk update for moving deals to a new deal stage failed to run because an error occurred. Please try again.`). The body is the plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/dealStage/delete_deal_stage":{"delete":{"summary":"Delete a deal stage and all of its deals","description":"Internal: backs the delete-stage dialog of the deals board in the app when the user deletes the stage's deals with it. Queues a background job that deletes every deal in stage `stageId` and then deletes the stage. The response only confirms that the job was queued: the deals and the stage are deleted afterwards. Requires the CRM on the account, the deals permission and the permission to edit pipelines, plus the permission to delete deals when the stage has any. Only DELETE is accepted; other methods get 405.","operationId":"delete-a-deal-stage-and-its-deals","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"stageId","in":"query","description":"ID of the stage to delete together with its deals.","required":true,"schema":{"type":"integer"},"example":4}],"responses":{"200":{"description":"The background job was queued. The body only confirms that; it does not report the job's outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageJobQueued"},"example":{"meta":{"success":true}}}}},"403":{"description":"The account does not have the CRM (`Upgrade your account to enable the CRM`), the user does not have the deals permission (`Forbidden`), may not edit pipelines (`You do not have permission to delete stages`), or the stage has deals and the user may not delete deals (`You do not have permission to delete deals`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageErrorResponse"},"example":{"errors":[{"status":"403","detail":"You do not have permission to delete stages"}]}}}},"422":{"description":"Nothing was queued: stage `stageId` does not exist (`The deal stage with an ID of 4 does not exist.`; a missing `stageId` reads as 0), or the job could not be created (`Bulk delete for removing deals associated with the target deal stage failed to run because an error occurred. Please try again.`). The body is the plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/dealStage/update_deal_stage_order":{"post":{"summary":"Reorder deal stages","description":"Internal: backs dragging a stage column on the deals board in the app. Sets the `order` of each stage in `ids` to its position in the list, counting from 1, so the caller sends all of a pipeline's stages in their new order. Stages left out keep their `order`, and the IDs are not required to belong to one pipeline. Stages are saved one at a time as the list is read: when an ID is not found the request stops with 422, and the stages listed before it have already been changed. Requires the CRM on the account, the deals permission and the permission to edit pipelines. Only POST is accepted; other methods get 405 with an empty body.","operationId":"reorder-deal-stages","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageOrderRequest"},"example":{"ids":["3","1","2"]}}}},"responses":{"200":{"description":"The stages were reordered. `dealStages` lists them in the order sent, with their new `order`. An empty `ids` changes nothing and returns an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageOrderResult"}}}},"403":{"description":"The account does not have the CRM (`Upgrade your account to enable the CRM`), the user does not have the deals permission (`Forbidden`), or may not edit pipelines (`You do not have permission to reorder stages`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealStageErrorResponse"},"example":{"errors":[{"status":"403","detail":"You do not have permission to reorder stages"}]}}}},"422":{"description":"An ID in `ids` is not a stage (`No result found for stage with id 9`). The stages listed before it have already been changed. The body is the plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/dealStages":{"post":{"summary":"Create a stage","description":"Create a new stage for a pipeline","operationId":"create-a-deal-stage","x-canonical-resource":"dealStages","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"reorder","in":"query","description":"Whether to reorder stages within the pipeline after creating a new deal stage. Can be one of `0` and `1`. If set to `1`, new order values will be assigned to all stages within the same pipeline. If deal stages with the same order exists, the stage with the highest `id` will be assigned with the lowest `order`","schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealStage":{"properties":{"title":{"type":"string","description":"Deal stage's title"},"group":{"type":"string","description":"Deal stage's pipeline id"},"order":{"type":"integer","description":"Order of the deal stage. If more than one deal stage share the same order value, the order of those deal stages may not be always the same. If `dealStage.order` is not provided, the order is assigned with `(the highest order of deal stages within the same pipeline) + 1`","format":"int32"},"dealOrder":{"type":"string","description":"Option and direction to be used to sort deals in the deal stage. The option and direction should be delimited by a space. Direction can be either \"ASC\" or \"DESC\". See [available options](#section-deal-stage-parameters-available-values)","default":"next-action DESC"},"cardRegion1":{"type":"string","description":"What to show in upper-left corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)","default":"title"},"cardRegion2":{"type":"string","description":"What to show in upper-right corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)","default":"next-action"},"cardRegion3":{"type":"string","description":"Whether to show the avatar in Deal Cards. Can be one of `show-avatar` and `hide-avatar`. If set to `show-avatar`, deal cards will show the avatars. If set to `hide-avatar`, deal cards will hide the avatars","default":"show-avatar"},"cardRegion4":{"type":"string","description":"What to show next to the avatar in Deal Cards. See [available values](#section-deal-stage-parameters-available-values)","default":"contact-fullname-orgname"},"cardRegion5":{"type":"string","description":"What to show in lower-right corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)","default":"value"},"color":{"type":"string","description":"Deal Stage's color. 6-character HEX color code without the hashtag. e.g. \"434343\" to assign the hex color value \"#434343\"","default":"3f3f3f"},"width":{"type":"integer","description":"Deal stage's width in pixels, without `px` unit","default":280,"format":"int32"}},"required":["title","group"],"type":"object"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealStage":{"cardRegion1":"title","cardRegion2":"next-action","cardRegion3":"show-avatar","cardRegion4":"contact-fullname-orgname","cardRegion5":"value","color":"32B0FC","dealOrder":"next-action DESC","group":"4","order":1,"title":"Initial Contact","width":360}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealStage\": {\n    \"cardRegion1\": \"title\",\n    \"cardRegion2\": \"next-action\",\n    \"cardRegion3\": \"show-avatar\",\n    \"cardRegion4\": \"contact-fullname-orgname\",\n    \"cardRegion5\": \"value\",\n    \"cdate\": \"2017-03-01T15:55:58-06:00\",\n    \"color\": \"32B0FC\",\n    \"dealOrder\": \"next-action DESC\",\n    \"group\": \"4\",\n    \"id\": \"16\",\n    \"links\": {\n      \"group\": \"https://:account.api-us1.com/api/3/dealStages/16/group\"\n    },\n    \"order\": 1,\n    \"title\": \"Initial Contact\",\n    \"udate\": \"2017-03-01T15:55:58-06:00\",\n    \"width\": 280\n  }\n}"}},"schema":{"type":"object","properties":{"dealStage":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{"type":"string","example":"2017-03-01T15:55:58-06:00"},"color":{"type":"string","example":"32B0FC"},"dealOrder":{"type":"string","example":"next-action DESC"},"group":{"type":"string","example":"4"},"id":{"type":"string","example":"16"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/16/group"}}},"order":{"type":"integer","example":1,"default":0},"title":{"type":"string","example":"Initial Contact"},"udate":{"type":"string","example":"2017-03-01T15:55:58-06:00"},"width":{"type":"integer","example":280,"default":0}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all stages","description":"Retrieve all existing stages","operationId":"list-all-deal-stages","x-canonical-resource":"dealStages","parameters":[{"name":"filters[title]","in":"query","description":"Filter by deal stages' titles. Any stages whose titles partial-match the filter value are returned","schema":{"type":"string"}},{"name":"filters[d_groupid]","in":"query","description":"Filter by pipeline's id","schema":{"type":"string"}},{"name":"orders[title]","in":"query","description":"Order by deal stage's title","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-03-01T15:52:42-06:00\",\n      \"color\": \"32B0FC\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"4\",\n      \"id\": \"15\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/15/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"Initial Contact\",\n      \"udate\": \"2017-03-01T15:52:42-06:00\",\n      \"width\": \"280\"\n    },\n    {\n      \"cardRegion1\": \"contact-orgname\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"hide-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-03-01T15:55:58-06:00\",\n      \"color\": \"696969\",\n      \"dealOrder\": \"title ASC\",\n      \"group\": \"4\",\n      \"id\": \"16\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/16/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"Qualifications - Low\",\n      \"udate\": \"2017-03-01T16:03:57-06:00\",\n      \"width\": \"270\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealStages":{"type":"array","items":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{"type":"string","example":"2017-03-01T15:52:42-06:00"},"color":{"type":"string","example":"32B0FC"},"dealOrder":{"type":"string","example":"next-action DESC"},"group":{"type":"string","example":"4"},"id":{"type":"string","example":"15"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/15/group"}}},"order":{"type":"string","example":"1"},"title":{"type":"string","example":"Initial Contact"},"udate":{"type":"string","example":"2017-03-01T15:52:42-06:00"},"width":{"type":"string","example":"280"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealStages/{id}":{"get":{"summary":"Retrieve a stage","description":"Retrieve an existing stage","operationId":"retrieve-a-deal-stage","x-canonical-resource":"dealStages","parameters":[{"name":"id","in":"path","description":"Deal stage's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealStage\": {\n    \"cardRegion1\": \"title\",\n    \"cardRegion2\": \"next-action\",\n    \"cardRegion3\": \"show-avatar\",\n    \"cardRegion4\": \"contact-fullname-orgname\",\n    \"cardRegion5\": \"value\",\n    \"cdate\": \"2017-01-20T09:27:32-06:00\",\n    \"color\": \"C481DF\",\n    \"dealOrder\": \"score DESC\",\n    \"group\": \"1\",\n    \"id\": \"1\",\n    \"links\": {\n      \"group\": \"https://:account.api-us1.com/api/3/dealStages/1/group\"\n    },\n    \"order\": \"1\",\n    \"title\": \"Stage 1\",\n    \"udate\": \"2017-03-02T11:41:01-06:00\",\n    \"width\": \"280\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealStage":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"title"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"show-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{"type":"string","example":"2017-01-20T09:27:32-06:00"},"color":{"type":"string","example":"C481DF"},"dealOrder":{"type":"string","example":"score DESC"},"group":{"type":"string","example":"1"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/1/group"}}},"order":{"type":"string","example":"1"},"title":{"type":"string","example":"Stage 1"},"udate":{"type":"string","example":"2017-03-02T11:41:01-06:00"},"width":{"type":"string","example":"280"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a stage","description":"Update an existing stage","operationId":"update-a-deal-stage","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal stage's id","schema":{"type":"integer","format":"int32"},"required":true},{"name":"reorder","in":"query","description":"Whether to reorder stages within the pipeline after creating a new deal stage. Can be one of `0` and `1`. If set to `1`, new order values will be assigned to all stages within the same pipeline. If deal stages with the same order exists, the stage with the highest `id` will be assigned with the lowest `order`","schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealStage":{"properties":{"title":{"type":"string","description":"Deal stage's title"},"group":{"type":"string","description":"Deal stage's pipeline id"},"order":{"type":"integer","description":"Order of the deal stage. If more than one deal stage share the same order value, the order of those deal stages may not be always the same","format":"int32"},"dealOrder":{"type":"string","description":"Option and direction to be used to sort deals in the deal stage. The option and direction should be delimited by a space. Direction can be either \"ASC\" or \"DESC\". See [available options](#section-deal-stage-parameters-available-values)"},"cardRegion1":{"type":"string","description":"What to show in upper-left corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)"},"cardRegion2":{"type":"string","description":"What to show in upper-right corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)"},"cardRegion3":{"type":"string","description":"Whether to show the avatar in Deal Cards. Can be one of `show-avatar` and `hide-avatar`. If set to `show-avatar`, deal cards will show the avatars. If set to `hide-avatar`, deal cards will hide the avatars"},"cardRegion4":{"type":"string","description":"What to show next to the avatar in Deal Cards. See [available values](#section-deal-stage-parameters-available-values)"},"cardRegion5":{"type":"string","description":"What to show in lower-right corner of Deal Cards. See [available values](#section-deal-stage-parameters-available-values)"},"color":{"type":"string","description":"Deal Stage's color. 6-character HEX color code without the hashtag. e.g. \"434343\" to assign the hex color value \"#434343\""},"width":{"type":"integer","description":"Deal stage's width in pixels, without `px` unit","format":"int32"}},"required":[],"type":"object"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealStage":{"cardRegion1":"contact-orgname","cardRegion2":"next-action","cardRegion3":"hide-avatar","cardRegion4":"contact-fullname-orgname","cardRegion5":"value","color":"696969","dealOrder":"title ASC","group":"4","order":1,"title":"Qualifications - Low","width":270}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealStage\": {\n    \"cardRegion1\": \"contact-orgname\",\n    \"cardRegion2\": \"next-action\",\n    \"cardRegion3\": \"hide-avatar\",\n    \"cardRegion4\": \"contact-fullname-orgname\",\n    \"cardRegion5\": \"value\",\n    \"cdate\": \"2017-03-01T15:55:58-06:00\",\n    \"color\": \"696969\",\n    \"dealOrder\": \"title ASC\",\n    \"group\": \"4\",\n    \"id\": \"16\",\n    \"links\": {\n      \"group\": \"https://:account.api-us1.com/api/3/dealStages/16/group\"\n    },\n    \"order\": 1,\n    \"title\": \"Qualifications - Low\",\n    \"udate\": \"2017-03-01T16:03:57-06:00\",\n    \"width\": 270\n  }\n}"}},"schema":{"type":"object","properties":{"dealStage":{"type":"object","properties":{"cardRegion1":{"type":"string","example":"contact-orgname"},"cardRegion2":{"type":"string","example":"next-action"},"cardRegion3":{"type":"string","example":"hide-avatar"},"cardRegion4":{"type":"string","example":"contact-fullname-orgname"},"cardRegion5":{"type":"string","example":"value"},"cdate":{"type":"string","example":"2017-03-01T15:55:58-06:00"},"color":{"type":"string","example":"696969"},"dealOrder":{"type":"string","example":"title ASC"},"group":{"type":"string","example":"4"},"id":{"type":"string","example":"16"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/dealStages/16/group"}}},"order":{"type":"integer","example":1,"default":0},"title":{"type":"string","example":"Qualifications - Low"},"udate":{"type":"string","example":"2017-03-01T16:03:57-06:00"},"width":{"type":"integer","example":270,"default":0}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a stage","description":"Delete an existing stage","operationId":"delete-a-deal-stage","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal stage's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealStages/{id}/deals":{"put":{"summary":"Move deals to another stage","description":"Move all deals in one stage to another stage","operationId":"move-deals-to-another-deal-stage","x-canonical-resource":"dealStages","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"id","in":"path","description":"Deal stage's id whose deals are to be moved to another deal stage","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deal":{"properties":{"stage":{"type":"string","description":"Target deal stage's id to move deals to"}},"required":[],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"deal":{"stage":"3"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"deals\": [\n    {\n      \"activitycount\": \"1\",\n      \"cdate\": \"2017-05-19T16:21:47-05:00\",\n      \"contact\": \"1\",\n      \"currency\": \"usd\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"group\": \"1\",\n      \"hash\": \"6faccb2d\",\n      \"id\": \"1\",\n      \"links\": {\n        \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/1/dealActivities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/1/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/1/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/1/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/1/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/1/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/1/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/1/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/1/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/1/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/1/tasks\"\n      },\n      \"mdate\": \"2017-05-19T16:21:47-05:00\",\n      \"nextTask\": null,\n      \"nextdealid\": \"2\",\n      \"nexttaskid\": \"0\",\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"3\",\n      \"status\": \"0\",\n      \"title\": \"Another Deal\",\n      \"value\": \"10000\"\n    },\n    {\n      \"activitycount\": \"1\",\n      \"cdate\": \"2017-05-19T16:23:01-05:00\",\n      \"contact\": \"2\",\n      \"currency\": \"usd\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"group\": \"1\",\n      \"hash\": \"fe7cc4f3\",\n      \"id\": \"2\",\n      \"links\": {\n        \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/2/dealActivities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/2/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/2/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/2/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/2/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/2/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/2/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/2/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/2/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/2/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/2/tasks\"\n      },\n      \"mdate\": \"2017-05-19T16:23:01-05:00\",\n      \"nextTask\": null,\n      \"nextdealid\": \"1\",\n      \"nexttaskid\": \"0\",\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"3\",\n      \"status\": \"0\",\n      \"title\": \"Urgent Deal\",\n      \"value\": \"10000\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"activitycount":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2017-05-19T16:21:47-05:00"},"contact":{"type":"string","example":"1"},"currency":{"type":"string","example":"usd"},"edate":{"type":"string","example":"0000-00-00 00:00:00"},"group":{"type":"string","example":"1"},"hash":{"type":"string","example":"6faccb2d"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/dealActivities"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contact"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contactDeals"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/group"},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/nextTask"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/notes"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/organization"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/owner"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/scoreValues"},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/stage"},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/tasks"}}},"mdate":{"type":"string","example":"2017-05-19T16:21:47-05:00"},"nextTask":{},"nextdealid":{"type":"string","example":"2"},"nexttaskid":{"type":"string","example":"0"},"organization":{},"owner":{"type":"string","example":"1"},"percent":{"type":"string","example":"0"},"stage":{"type":"string","example":"3"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"Another Deal"},"value":{"type":"string","example":"10000"}}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Different pipeline":{"value":"{\n  \"errors\": [\n    {\n      \"detail\": \"Target stage does not belong to same pipeline\",\n      \"source\": {\n        \"pointer\": \"/data/attributes/stage\"\n      },\n      \"status\": 422,\n      \"title\": \"Invalid attribute\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"detail":{"type":"string","example":"Target stage does not belong to same pipeline"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/stage"}}},"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid attribute"}}}}}}}}}},"deprecated":false}},"/dealTasks":{"post":{"summary":"Create a task","description":"Create a new task","operationId":"create-task","x-canonical-resource":"deal_task","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealTask":{"properties":{"title":{"type":"string","description":"The title to be assigned to the task"},"ownerType":{"type":"string","description":"The name of the relating object. Valid values are `contact` or `deal`. (see relationships table)","default":"deal"},"relid":{"type":"integer","description":"The id of the relational object for this task","format":"int32"},"status":{"type":"integer","description":"Task status means complete or incomplete. 1 is complete and 0 is incomplete.","format":"int32"},"note":{"type":"string","description":"The content describing the task"},"duedate":{"type":"string","description":"Due date of the task","format":"date"},"edate":{"type":"string","description":"End date of the task. Must not be earlier than `duedate`. When the task has no `edate`, it is set to `duedate` plus 15 minutes.","examples":["2017-02-25T12:15:00-06:00"]},"dealTasktype":{"type":"integer","description":"The type of the task based on the available Task Types in the account","format":"int32"},"assignee":{"type":"integer","description":"The id of an user the task will be assigned to","format":"int32"},"triggerAutomationOnCreate":{"type":"integer","description":"Id of an automation that will be triggered when the task is created.","format":"int32"},"doneAutomation":{"type":"integer","description":"Id of an automation that will be triggered when the task is completed.","format":"int32"},"outcomeId":{"type":"integer","description":"ID of a task outcome associated with the task's task type."},"outcomeInfo":{"type":"string","maxLength":4096},"automation":{"type":"integer"},"owner":{"type":"integer","description":"ID of the record the task belongs to; replaces relid when present."},"reltype":{"type":"string","description":"Owner class name, Deal or Subscriber (CustomerAccount when account tasks are enabled). Replaced by ownerType when ownerType is deal, contact or account, and set to Deal when ownerType is absent."}},"required":["relid","duedate","dealTasktype"],"type":"object"},"shouldValidateAssignee":{"type":"boolean","description":"When true, the assignee must be an existing user."}}},"examples":{"Request Example":{"value":{"dealTask":{"title":null,"ownerType":"contact","relid":"7","status":0,"note":"Testing Task","duedate":"2017-02-25T12:00:00-06:00","edate":"2017-02-25T12:15:00-06:00","dealTasktype":"1","assignee":2,"triggerAutomationOnCreate":100,"doneAutomation":101}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"schema":{"type":"object","properties":{"dealTask":{"type":"object","properties":{"relid":{"type":"string","examples":["5"]},"reltype":{"type":"string","examples":["Deal"]},"dealTasktype":{"type":"string","examples":["1"]},"user":{"type":"string","examples":["1"]},"assignee":{"type":"string","examples":["2"]},"automation":{},"cdate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"duedate":{"type":"string","examples":["2017-02-28T12:00:00-06:00"]},"edate":{"type":"string","examples":["2017-02-28T12:15:00-06:00"]},"duration":{"type":"string","examples":["0"]},"status":{"type":"string","examples":["0"]},"title":{"type":"string","examples":[""]},"note":{"type":"string","examples":["Deal task title!"]},"donedate":{},"doneAutomation":{},"udate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"owner":{"type":"object","properties":{"type":{"type":"string","examples":["deal"]},"id":{"type":"string","examples":["5"]}}},"id":{"type":"string","examples":["1"]},"outcomeId":{"type":"integer","default":0,"examples":[91]},"outcomeInfo":{"type":"string","examples":["More details about the outcome"]},"links":{"type":"object","properties":{"activities":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities"]},"automation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation"]},"dealTasktype":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype"]},"doneAutomation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation"]},"notes":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes"]},"owner":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner"]},"taskNotifications":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications"]},"user":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/user"]},"assignee":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee"]}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"create_task","title":"Create Task","description":"Create a CRM task on a deal or a contact. Set ownerType to deal or contact and relid to its id, plus a title, a due date and a task type id from list_task_types. Assign it with an assignee user id.","annotations":{"readOnlyHint":false,"idempotentHint":false,"openWorldHint":false}}},"get":{"summary":"List all tasks","description":"Retrieve a list of existing tasks","operationId":"list-all-tasks","x-canonical-resource":"deal_task","parameters":[{"name":"filters[title]","in":"query","description":"The title to be assigned to the task","schema":{"type":"string"}},{"name":"filters[reltype]","in":"query","description":"The name of the relating object (see relationships table)","schema":{"type":"string"}},{"name":"filters[relid]","in":"query","description":"The id of the relational object for this task","schema":{"type":"integer","format":"int32"}},{"name":"filters[status]","in":"query","description":"Task status means complete or incomplete. 1 is complete and 0 is incomplete.","schema":{"type":"integer","format":"int32"}},{"name":"filters[note]","in":"query","description":"The content describing the task","schema":{"type":"string"}},{"name":"filters[duedate]","in":"query","description":"Due date of the task","schema":{"type":"string","format":"date"}},{"name":"filters[d_tasktypeid]","in":"query","description":"The type of the task based on the available Task Types in the account","schema":{"type":"integer","format":"int32"}},{"name":"filters[userid]","in":"query","description":"User ID this task belongs to","schema":{"type":"integer","format":"int32"}},{"name":"filters[due_after]","in":"query","description":"Filter deal tasks that are due after a specific date","schema":{"type":"string"}},{"name":"filters[due_before]","in":"query","description":"Filter deal tasks that are due before a specific date","schema":{"type":"string"}},{"name":"filters[duedate_range]","in":"query","description":"Filter deal tasks that are due between specific date range (YYYY-MM-DD+YYYY-MM-DD format) or get categorized tasks (upcoming, scheduled, overdue values)","schema":{"type":"string"}},{"name":"filters[assignee_userid]","in":"query","description":"The id of the user a task is assigned to","schema":{"type":"integer","format":"int32"}},{"name":"filters[outcome_id]","in":"query","description":"The id of a task outcome that the task belongs to.","schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasks\": [{\n    \"id\":\"1\",\n    \"duedate\":\"2017-02-25T12:00:00-06:00\",\n    \"edate\":\"2017-02-25T12:15:00-06:00\",\n    \"status\":0,\n    \"title\":null,\n    \"note\":\"Testing Task\",\n    \"relid\":\"7\",\n    \"reltype\":\"Subscriber\",\n    \"dealTasktype\":\"1\",\n    \"cdate\":\"2017-02-24T13:21:56-06:00\",\n    \"udate\":\"2017-02-24T13:21:56-06:00\",\n    \"automation\":null,\n    \"doneAutomation\":null,\n    \"user\":\"1\",\n    \"assignee\":\"2\",\n    \"owner\":{\n      \"type\":\"contact\",\n      \"id\":\"7\"\n    },\n    \"outcomeId\": null,\n\t\t\"outcomeInfo\": null,\n    \"links\": {\n      \"activities\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities\",\n      \"automation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation\",\n      \"dealTasktype\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype\",\n      \"doneAutomation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation\",\n      \"notes\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes\",\n      \"owner\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner\",\n      \"taskNotifications\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications\",\n      \"user\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/user\",\n      \"assignee\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee\"\n    }\n  },\n  {\n    \"id\":\"2\",\n    \"duedate\":\"2017-02-25T12:00:00-06:00\",\n    \"edate\":\"2017-02-25T12:15:00-06:00\",\n    \"status\":0,\n    \"title\":null,\n    \"note\":\"Testing Task 2\",\n    \"relid\":\"8\",\n    \"reltype\":\"Deal\",\n    \"dealTasktype\":\"1\",\n    \"cdate\":\"2017-02-24T13:21:56-06:00\",\n    \"udate\":\"2017-02-24T13:21:56-06:00\",\n    \"automation\":null,\n    \"doneAutomation\":null,\n    \"user\":\"1\",\n    \"assignee\":\"2\",\n    \"owner\":{\n      \"type\":\"deal\",\n      \"id\":\"5\"\n    },\n    \"outcomeId\": 91,\n\t\t\"outcomeInfo\": \"More details about the outcome\",\n    \"links\": {\n      \"activities\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/activities\",\n      \"automation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/automation\",\n      \"dealTasktype\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/dealTasktype\",\n      \"doneAutomation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/doneAutomation\",\n      \"notes\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/notes\",\n      \"owner\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/owner\",\n      \"taskNotifications\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/taskNotifications\",\n      \"user\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/user\",\n      \"assignee\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/2/assignee\"\n    }\n  }],\n  \"meta\":{\n    \"total\":\"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealTasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["1"]},"duedate":{"type":"string","examples":["2017-02-25T12:00:00-06:00"]},"edate":{"type":"string","examples":["2017-02-25T12:15:00-06:00"]},"status":{"type":"integer","default":0,"examples":[0]},"title":{},"note":{"type":"string","examples":["Testing Task"]},"relid":{"type":"string","examples":["7"]},"reltype":{"type":"string","examples":["Subscriber"]},"dealTasktype":{"type":"string","examples":["1"]},"cdate":{"type":"string","examples":["2017-02-24T13:21:56-06:00"]},"udate":{"type":"string","examples":["2017-02-24T13:21:56-06:00"]},"automation":{},"doneAutomation":{},"user":{"type":"string","examples":["1"]},"assignee":{"type":"string","examples":["2"]},"owner":{"type":"object","properties":{"type":{"type":"string","examples":["contact"]},"id":{"type":"string","examples":["7"]}}},"outcomeId":{},"outcomeInfo":{},"links":{"type":"object","properties":{"activities":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities"]},"automation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation"]},"dealTasktype":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype"]},"doneAutomation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation"]},"notes":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes"]},"owner":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner"]},"taskNotifications":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications"]},"user":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/user"]},"assignee":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee"]}}}}}},"meta":{"type":"object","properties":{"total":{"type":"string","examples":["2"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_tasks","title":"List Tasks","description":"List CRM tasks (contact tasks and deal tasks). Filter by what the task is related to (reltype Deal, or Subscriber for a contact, with its relid), by status (0 Incomplete, 1 Complete), by assignee user id, by task type, or by due date range. Use it to find what a rep has to do next.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/dealTasks/{id}":{"get":{"summary":"Retrieve a task","description":"Retrieve an existing task","operationId":"get-task","x-canonical-resource":"deal_task","parameters":[{"name":"id","in":"path","description":"The ID of the task","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTask\": {\n    \"relid\":\"5\",\n    \"reltype\":\"Deal\",\n    \"dealTasktype\":\"1\",\n    \"user\":\"1\",\n    \"assignee\": \"2\",\n    \"automation\":null,\n    \"cdate\":\"2017-02-24T15:01:37-06:00\",\n    \"duedate\":\"2017-02-28T12:00:00-06:00\",\n    \"edate\":\"2017-02-28T12:15:00-06:00\",\n    \"duration\":\"0\",\n    \"status\":\"0\",\n    \"title\":\"\",\n    \"note\":\"Deal task title!\",\n    \"donedate\":null,\n    \"doneAutomation\":null,\n    \"udate\":\"2017-02-24T15:01:37-06:00\",\n    \"owner\":{\n      \"type\":\"deal\",\n      \"id\":\"5\"\n    },\n    \"id\":\"1\",\n    \"outcomeId\": 91,\n\t\t\"outcomeInfo\": \"More details about the outcome\",\n    \"links\": {\n      \"activities\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities\",\n      \"automation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation\",\n      \"dealTasktype\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype\",\n      \"doneAutomation\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation\",\n      \"notes\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes\",\n      \"owner\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner\",\n      \"taskNotifications\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications\",\n      \"user\":\"https://yourAccountName.api-us1.com/api/3/dealTasks/1/user\",\n      \"assignee\": \"https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee\"\n    }\n  }\n}"}},"schema":{"type":"object","properties":{"dealTask":{"type":"object","properties":{"relid":{"type":"string","examples":["5"]},"reltype":{"type":"string","examples":["Deal"]},"dealTasktype":{"type":"string","examples":["1"]},"user":{"type":"string","examples":["1"]},"assignee":{"type":"string","examples":["2"]},"automation":{},"cdate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"duedate":{"type":"string","examples":["2017-02-28T12:00:00-06:00"]},"edate":{"type":"string","examples":["2017-02-28T12:15:00-06:00"]},"duration":{"type":"string","examples":["0"]},"status":{"type":"string","examples":["0"]},"title":{"type":"string","examples":[""]},"note":{"type":"string","examples":["Deal task title!"]},"donedate":{},"doneAutomation":{},"udate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"owner":{"type":"object","properties":{"type":{"type":"string","examples":["deal"]},"id":{"type":"string","examples":["5"]}}},"id":{"type":"string","examples":["1"]},"outcomeId":{"type":"integer","default":0,"examples":[91]},"outcomeInfo":{"type":"string","examples":["More details about the outcome"]},"links":{"type":"object","properties":{"activities":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities"]},"automation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation"]},"dealTasktype":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype"]},"doneAutomation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation"]},"notes":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes"]},"owner":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner"]},"taskNotifications":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications"]},"user":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/user"]},"assignee":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee"]}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"get_task","title":"Get Task","description":"Get one CRM task by its id: title, description (the note field), due date, status, assignee, task type and outcome.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}},"put":{"summary":"Update a task","description":"Update an existing task","operationId":"update-task","x-canonical-resource":"deal_task","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The ID of the task","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealTask":{"properties":{"title":{"type":"string","description":"The title to be assigned to the task"},"relid":{"type":"integer","description":"The id of the relational object for this task","format":"int32"},"status":{"type":"integer","description":"Task status means complete or incomplete. 1 is complete and 0 is incomplete.","format":"int32"},"note":{"type":"string","description":"The content describing the task"},"duedate":{"type":"string","description":"Due date of the task. Moving it to after the task's current `edate` requires sending `edate` too, or the update is rejected.","format":"date"},"edate":{"type":"string","description":"End date of the task. Must not be earlier than `duedate`. When the task has no `edate`, it is set to `duedate` plus 15 minutes.","examples":["2017-02-25T12:15:00-06:00"]},"dealTasktype":{"type":"integer","description":"The type of the task based on the available Task Types in the account","format":"int32"},"assignee":{"type":"integer","description":"The id of an user the task will be assigned to","format":"int32"},"outcomeId":{"type":"integer","description":"The id of the task outcome. On an account with task outcomes enabled, it is required whenever the task is complete after the update (`status` 1, sent in the request or already stored), and must be an outcome allowed for the task's type (see `tasktypeOutcomeRels`), which is checked again when `dealTasktype` changes.","format":"int32"},"outcomeInfo":{"type":"string","description":"More information about task completion with the outcome selection."},"triggerAutomationOnCreate":{"type":"integer"}},"required":[],"type":"object"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"dealTask":{"type":"object","properties":{"relid":{"type":"string","examples":["5"]},"reltype":{"type":"string","examples":["Deal"]},"dealTasktype":{"type":"string","examples":["1"]},"user":{"type":"string","examples":["1"]},"assignee":{"type":"string","examples":["2"]},"automation":{},"cdate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"duedate":{"type":"string","examples":["2017-02-28T12:00:00-06:00"]},"edate":{"type":"string","examples":["2017-02-28T12:15:00-06:00"]},"duration":{"type":"string","examples":["0"]},"status":{"type":"string","examples":["0"]},"title":{"type":"string","examples":[""]},"note":{"type":"string","examples":["Deal task title!"]},"donedate":{},"doneAutomation":{},"udate":{"type":"string","examples":["2017-02-24T15:01:37-06:00"]},"owner":{"type":"object","properties":{"type":{"type":"string","examples":["deal"]},"id":{"type":"string","examples":["5"]}}},"id":{"type":"string","examples":["1"]},"outcomeId":{"type":"integer","default":0,"examples":[91]},"outcomeInfo":{"type":"string","examples":["More details about the outcome"]},"links":{"type":"object","properties":{"activities":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/activities"]},"automation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/automation"]},"dealTasktype":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/dealTasktype"]},"doneAutomation":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/doneAutomation"]},"notes":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/notes"]},"owner":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/owner"]},"taskNotifications":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/taskNotifications"]},"user":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/user"]},"assignee":{"type":"string","examples":["https://yourAccountName.api-us1.com/api/3/dealTasks/1/assignee"]}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"update_task","title":"Update Task","description":"Change a CRM task: title, description (note), due date, assignee or task type. Mark it complete by setting status to 1. When Task Outcomes are turned on, completing a task requires an outcome: pass an outcomeId from list_task_outcomes that is assigned to the task's type.","annotations":{"readOnlyHint":false,"idempotentHint":true,"openWorldHint":false}}},"delete":{"summary":"Delete a task","description":"Delete an existing task","operationId":"delete-task","x-canonical-resource":"deal_task","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The task id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/dealTasktypes":{"post":{"summary":"Create a task type","description":"Create a new task type","operationId":"create-a-deal-task-type","x-canonical-resource":"dealTasktypes","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealTasktype":{"properties":{"title":{"type":"string","description":"Deal task type's title. The title should be unique among deal task types."},"status":{"type":["integer","string"],"description":"0 - Active status, 1 - Disabled status","enum":[0,1,"0","1"]},"defduration":{"type":"integer","minimum":0}},"required":["title"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealTasktype":{"title":"Skype","status":0}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasktype\": {\n    \"cdate\": \"2017-03-02T14:28:53-06:00\",\n    \"defduration\": \"0\",\n    \"id\": \"7\",\n    \"links\": [],\n    \"status\": \"0\",\n    \"title\": \"Skype\",\n    \"udate\": \"2017-03-02T14:28:53-06:00\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealTasktype":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-03-02T14:28:53-06:00"},"defduration":{"type":"string","example":"0"},"id":{"type":"string","example":"7"},"links":{"type":"array"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"Skype"},"udate":{"type":"string","example":"2017-03-02T14:28:53-06:00"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all task types","description":"Retrieve all existing task types","operationId":"list-all-deal-task-types","x-canonical-resource":"dealTasktypes","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasktypes\": [\n    {\n      \"cdate\": null,\n      \"defduration\": \"0\",\n      \"id\": \"1\",\n      \"links\": [],\n      \"status\": \"0\",\n      \"title\": \"Call\",\n      \"udate\": null\n    },\n    {\n      \"cdate\": null,\n      \"defduration\": \"0\",\n      \"id\": \"2\",\n      \"links\": [],\n      \"status\": \"0\",\n      \"title\": \"Email\",\n      \"udate\": null\n    },\n    {\n      \"cdate\": null,\n      \"defduration\": \"0\",\n      \"id\": \"3\",\n      \"links\": [],\n      \"status\": \"0\",\n      \"title\": \"Lunch\",\n      \"udate\": null\n    },\n    {\n      \"cdate\": null,\n      \"defduration\": \"0\",\n      \"id\": \"4\",\n      \"links\": [],\n      \"status\": \"0\",\n      \"title\": \"Meeting\",\n      \"udate\": null\n    }\n  ],\n  \"meta\": {\n    \"total\": \"4\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealTasktypes":{"type":"array","items":{"type":"object","properties":{"cdate":{},"defduration":{"type":"string","examples":["0"]},"id":{"type":"string","examples":["1"]},"links":{"type":"array"},"status":{"type":"string","examples":["0"]},"title":{"type":"string","examples":["Call"]},"udate":{}}}},"meta":{"type":"object","properties":{"total":{"type":"string","examples":["4"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_task_types","title":"List Task Types","description":"List the account's CRM task types (for example Call, Email, Meeting) with their ids, for create_task and update_task.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/dealTasktypes/bulkUpsert":{"patch":{"summary":"Replace the account's task types","description":"Internal: saves the whole task type list in one request. Makes the account's task types exactly the entries in `dealTasktypes`: an entry with the `id` of an existing task type updates that task type, an entry without `id`, or whose `id` matches no task type, creates one, and every existing task type left out of the list is deleted. Tasks of a deleted task type are not moved or deleted. When the account's task outcomes setting is on, each entry's `outcomes` becomes that task type's outcome list: links are added, reordered and removed to match; when the setting is off, `outcomes` is ignored and the existing links are kept. An entry with `status` 1 (disabled) and `taskTypeIdToMigrateTasks` also moves the task type's open tasks to that task type. The whole request is checked before anything is saved, but the saves are not one transaction. Requires the deals permission. Only PATCH is routed; other methods get 405.","operationId":"bulk-upsert-deal-task-types","x-canonical-resource":"dealTasktypes","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesBulkUpsertRequest"},"example":{"dealTasktypes":[{"id":"1","title":"Call","display_order":1,"status":0,"outcomes":[{"id":1,"display_order":1},{"id":2,"display_order":2}]},{"id":"2","title":"Lunch","display_order":2,"status":1,"taskTypeIdToMigrateTasks":"1","outcomes":[{"id":1,"display_order":1}]},{"title":"Meeting","display_order":3,"outcomes":[{"id":1,"display_order":1}]}]}}}},"responses":{"200":{"description":"The task types were saved. The body is the list GET /dealTasktypes returns without parameters: the first 20 task types ordered by `display_order` and then `title`, each with its outcomes, and the number of task types in `meta.total`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesBulkUpsertResult"}}}},"403":{"description":"The user does not have the deals permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesErrorResponse"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"Nothing was changed: `taskTypeIdToMigrateTasks` on a disabled entry names no task type.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found","example":"No Result found for DealTasktype with id 99"}}}}}},"422":{"description":"Nothing was changed. The body is empty or not JSON (`Invalid payload.`), `dealTasktypes` is missing, not an array or empty, an entry has neither `id` nor `title`, two entries share a title, `taskTypeIdToMigrateTasks` names a disabled task type, or, with task outcomes on, an entry's `outcomes` is missing, not an array, empty or longer than 100, or an outcome has no `id` or is not an enabled outcome. Most checks stop at the first problem and return one error; the outcome checks return one error per bad outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesBulkUpsertErrors"},"example":{"errors":[{"status":422,"title":"Please provide 'id' of each dealTasktype if it exists. Provide 'title' if it is a new dealTasktype."}]}}}}},"deprecated":false,"x-internal":true}},"/dealTasktypes/{id}":{"get":{"summary":"Retrieve a task type","description":"Retrieve an existing task type","operationId":"retrieve-a-deal-task-type","x-canonical-resource":"dealTasktypes","parameters":[{"name":"id","in":"path","description":"Deal task type's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasktype\": {\n    \"cdate\": \"2017-03-02T14:22:51-06:00\",\n    \"defduration\": \"0\",\n    \"id\": \"5\",\n    \"links\": [],\n    \"status\": \"0\",\n    \"title\": \"Skype\",\n    \"udate\": \"2017-03-02T14:22:51-06:00\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealTasktype":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-03-02T14:22:51-06:00"},"defduration":{"type":"string","example":"0"},"id":{"type":"string","example":"5"},"links":{"type":"array"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"Skype"},"udate":{"type":"string","example":"2017-03-02T14:22:51-06:00"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a task type","description":"Update an existing task type","operationId":"update-a-deal-task-type","x-canonical-resource":"dealTasktypes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal task type's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealTasktype":{"properties":{"title":{"type":"string","description":"Deal task type's title. The title should be unique among deal task types."},"status":{"type":["integer","string"],"description":"0 - Active status, 1 - Disabled status","default":0,"enum":[0,1,"0","1"]},"defduration":{"type":"integer","minimum":0}},"required":[],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealTasktype":{"title":"Meet in person","status":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasktype\": {\n    \"cdate\": \"2017-03-02T14:28:53-06:00\",\n    \"defduration\": \"0\",\n    \"id\": \"7\",\n    \"links\": [],\n    \"status\": \"1\",\n    \"title\": \"Meet in person\",\n    \"udate\": \"2017-03-02T14:32:20-06:00\"\n  }\n}"}},"schema":{"type":"object","properties":{"dealTasktype":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-03-02T14:28:53-06:00"},"defduration":{"type":"string","example":"0"},"id":{"type":"string","example":"7"},"links":{"type":"array"},"status":{"type":"string","example":"1"},"title":{"type":"string","example":"Meet in person"},"udate":{"type":"string","example":"2017-03-02T14:32:20-06:00"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a task type","description":"Delete an existing task type","operationId":"delete-a-deal-task-type","x-canonical-resource":"dealTasktypes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal task type's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"patch":{"summary":"Update a task type (PATCH)","description":"Internal: the PATCH form of PUT /dealTasktypes/{id}. Both verbs are served by the same handler and behave the same way. Changes the fields sent in `dealTasktype` and keeps the others; only `title`, `status` and `defduration` can be changed, and other keys are ignored. The title must stay non-empty and must not be used by another task type. Does not change the task type's outcomes and does not move its tasks: PATCH /dealTasktypes/bulkUpsert does both, and PUT /dealTasktypes/{id}/dealTasks moves all of a task type's tasks. Requires the deals permission.","operationId":"patch-a-deal-task-type","x-canonical-resource":"dealTasktypes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the task type to change","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dealTasktype"],"properties":{"dealTasktype":{"$ref":"#/components/schemas/DealTasktypesPatchFields"}}},"example":{"dealTasktype":{"title":"Meet in person","status":1}}}}},"responses":{"200":{"description":"The task type after the change. Its outcomes are not included; GET /dealTasktypes/{id} returns them.","content":{"application/json":{"schema":{"type":"object","properties":{"dealTasktype":{"$ref":"#/components/schemas/DealTasktypesTaskType"}}}}}},"403":{"description":"The user does not have the deals permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesErrorResponse"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No task type with this ID","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found","example":"No Result found for DealTasktype with id 99"}}}}}},"422":{"description":"Nothing was changed: the title would be empty (code `field_missing`), or another task type already has it (code `duplicate`, `The task type already exists in the system.`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTasktypesValidationErrors"},"example":{"errors":[{"title":"The task type already exists in the system.","detail":"","code":"duplicate","error":"dealTasktype_already_exists_in_the_system","source":{"pointer":"/data/attributes/title"}}]}}}}},"deprecated":false,"x-internal":true}},"/dealTasktypes/{id}/dealTasks":{"put":{"summary":"Move tasks to another task type","description":"Move tasks to a different task type","operationId":"move-deal-tasks-to-another-deal-task-type","x-canonical-resource":"dealTasktypes","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"id","in":"path","description":"Deal task type's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dealTask":{"properties":{"dealTasktype":{"type":"string","description":"Deal task type's id to move deal tasks to"}},"required":[],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"dealTask":{"dealTasktype":"2"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"dealTasks\": [\n    {\n      \"automation\": null,\n      \"cdate\": \"2017-06-01T15:08:55-05:00\",\n      \"dealTasktype\": \"2\",\n      \"doneAutomation\": null,\n      \"donedate\": null,\n      \"duedate\": \"2017-06-02T12:00:00-05:00\",\n      \"duration\": \"0\",\n      \"edate\": \"2017-06-02T12:15:00-05:00\",\n      \"id\": \"1\",\n      \"links\": {\n        \"activities\": \"https://:account.api-us1.com/api/3/dealTasks/1/activities\",\n        \"automation\": \"https://:account.api-us1.com/api/3/dealTasks/1/automation\",\n        \"dealTasktype\": \"https://:account.api-us1.com/api/3/dealTasks/1/dealTasktype\",\n        \"doneAutomation\": \"https://:account.api-us1.com/api/3/dealTasks/1/doneAutomation\",\n        \"notes\": \"https://:account.api-us1.com/api/3/dealTasks/1/notes\",\n        \"owner\": \"https://:account.api-us1.com/api/3/dealTasks/1/owner\",\n        \"taskNotifications\": \"https://:account.api-us1.com/api/3/dealTasks/1/taskNotifications\",\n        \"user\": \"https://:account.api-us1.com/api/3/dealTasks/1/user\"\n      },\n      \"note\": \"Call Steve\",\n      \"owner\": {\n        \"id\": \"1\",\n        \"type\": \"deal\"\n      },\n      \"relid\": \"1\",\n      \"reltype\": \"Deal\",\n      \"status\": \"0\",\n      \"title\": \"\",\n      \"udate\": \"2017-06-01T15:08:55-05:00\",\n      \"user\": \"1\"\n    }\n  ],\n  \"deals\": [\n    {\n      \"activitycount\": \"2\",\n      \"cdate\": \"2017-06-01T15:08:41-05:00\",\n      \"contact\": \"1\",\n      \"currency\": \"usd\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"group\": \"1\",\n      \"hash\": \"3abd127b\",\n      \"id\": \"1\",\n      \"links\": {\n        \"activities\": \"https://:account.api-us1.com/api/3/deals/1/activities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/1/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/1/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/1/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/1/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/1/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/1/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/1/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/1/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/1/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/1/tasks\"\n      },\n      \"mdate\": \"2017-06-01T15:08:55-05:00\",\n      \"nextTask\": \"1\",\n      \"nextdate\": \"2017-06-02T12:00:00-05:00\",\n      \"nextdealid\": \"1\",\n      \"nexttaskid\": \"1\",\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"1\",\n      \"status\": \"0\",\n      \"title\": \"New deal\",\n      \"value\": \"10000\"\n    }\n  ]\n}"}},"schema":{"type":"object","properties":{"dealTasks":{"type":"array","items":{"type":"object","properties":{"automation":{},"cdate":{"type":"string","example":"2017-06-01T15:08:55-05:00"},"dealTasktype":{"type":"string","example":"2"},"doneAutomation":{},"donedate":{},"duedate":{"type":"string","example":"2017-06-02T12:00:00-05:00"},"duration":{"type":"string","example":"0"},"edate":{"type":"string","example":"2017-06-02T12:15:00-05:00"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/activities"},"automation":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/automation"},"dealTasktype":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/dealTasktype"},"doneAutomation":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/doneAutomation"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/notes"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/owner"},"taskNotifications":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/taskNotifications"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/dealTasks/1/user"}}},"note":{"type":"string","example":"Call Steve"},"owner":{"type":"object","properties":{"id":{"type":"string","example":"1"},"type":{"type":"string","example":"deal"}}},"relid":{"type":"string","example":"1"},"reltype":{"type":"string","example":"Deal"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":""},"udate":{"type":"string","example":"2017-06-01T15:08:55-05:00"},"user":{"type":"string","example":"1"}}}},"deals":{"type":"array","items":{"type":"object","properties":{"activitycount":{"type":"string","example":"2"},"cdate":{"type":"string","example":"2017-06-01T15:08:41-05:00"},"contact":{"type":"string","example":"1"},"currency":{"type":"string","example":"usd"},"edate":{"type":"string","example":"0000-00-00 00:00:00"},"group":{"type":"string","example":"1"},"hash":{"type":"string","example":"3abd127b"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/activities"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contact"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contactDeals"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/group"},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/nextTask"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/notes"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/organization"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/owner"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/scoreValues"},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/stage"},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/tasks"}}},"mdate":{"type":"string","example":"2017-06-01T15:08:55-05:00"},"nextTask":{"type":"string","example":"1"},"nextdate":{"type":"string","example":"2017-06-02T12:00:00-05:00"},"nextdealid":{"type":"string","example":"1"},"nexttaskid":{"type":"string","example":"1"},"organization":{},"owner":{"type":"string","example":"1"},"percent":{"type":"string","example":"0"},"stage":{"type":"string","example":"1"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"New deal"},"value":{"type":"string","example":"10000"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/deals":{"post":{"summary":"Create a deal","description":"Create a new deal","operationId":"create-a-deal-new","x-canonical-resource":"deal","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deal":{"properties":{"title":{"type":"string","description":"Deal's title."},"description":{"type":"string","description":"Deal's description"},"account":{"type":"string","description":"Deal’s account id. Required if `deal.contact` is not provided."},"contact":{"type":"string","description":"Deal's primary contact's id. Required if `deal.account` is not provided."},"value":{"type":"integer","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"currency":{"type":"string","description":"Deal's currency in 3-digit ISO format, lowercased."},"group":{"type":"string","description":"Deal's pipeline id. Required if `deal.stage` is not provided. If `deal.group` is not provided, the stage's pipeline will be assigned to the deal automatically."},"stage":{"type":"string","description":"Deal's stage id. Required if `deal.group` is not provided. If `deal.stage` is not provided, the deal will be assigned with the first stage in the pipeline provided in `deal.group`."},"owner":{"type":"string","description":"Deal's owner id. Required if pipeline's auto-assign option is disabled."},"percent":{"type":"integer","description":"Deal's percentage.","format":"int32"},"status":{"type":"integer","description":"Deal's status. See [available values](ref:deal).","default":0,"format":"int32"},"fields":{"type":"array","description":"Deal's custom field values `{customFieldId: string, fieldValue: string, fieldCurrency?:string}[]`","items":{"properties":{"customFieldId":{"type":"integer","description":"Field ID, ID of the Custom Field Meta Data","format":"int32"},"fieldValue":{"type":"string","description":"Updated field value. For `currency` field, this needs to be in cents not dollars (or 100 x Base Unit)."},"fieldCurrency":{"type":"string","description":"Required only for the `currency` field type. The three letter currency code for the currency value"}},"required":["customFieldId","fieldValue"],"type":"object"}},"customerAccount":{"type":"string","description":"Alternative to account: ID of the account (organization) the deal belongs to."},"organization":{"type":"string","description":"Alternative to account: ID of the account (organization) the deal belongs to."},"firstName":{"type":"string","description":"First name for the contact created when contact is an email address that matches no existing contact; ignored otherwise."},"lastName":{"type":"string","description":"Last name for the contact created when contact is an email address that matches no existing contact; ignored otherwise."},"phone":{"type":"string","description":"Phone for the contact created when contact is an email address that matches no existing contact; ignored otherwise."},"winProbability":{"type":["number","null"],"description":"Win probability score; null means it has not been calculated."}},"required":["title","account","contact","value","currency","group","stage","owner"],"type":"object"},"useDefaults":{"type":"boolean","description":"Read but has no effect."},"validateData":{"type":"boolean","description":"true validates the custom field values in deal.fields before the deal is saved."}},"additionalProperties":false},"examples":{"POST /deals (Example REQUEST)":{"value":{"deal":{"contact":"51","account":"45","description":"This deal is an important deal","currency":"usd","group":"1","owner":"1","percent":null,"stage":"1","status":0,"title":"AC Deal","value":45600,"fields":[{"customFieldId":1,"fieldValue":"First field value"},{"customFieldId":2,"fieldValue":"2008-01-20"},{"customFieldId":3,"fieldValue":5500,"fieldCurrency":"EUR"}]}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"contacts\": [\n    {\n      \"adate\": \"2017-02-06 15:50:11\",\n      \"bounced_date\": \"0000-00-00\",\n      \"bounced_hard\": \"0\",\n      \"bounced_soft\": \"0\",\n      \"cdate\": \"2017-02-03T11:26:41-06:00\",\n      \"deleted\": \"0\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"email\": \"johndoe@example.com\",\n      \"email_domain\": \"\",\n      \"email_local\": \"\",\n      \"firstName\": \"\",\n      \"gravatar\": \"1\",\n      \"hash\": \"e1705a92f24edf5313ed21df44d6ff5f\",\n      \"id\": \"51\",\n      \"ip\": \"0\",\n      \"lastName\": \"\",\n      \"links\": {\n        \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/51/bounceLogs\",\n        \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/51/contactAutomations\",\n        \"contactData\": \"https://:account.api-us1.com/api/3/contacts/51/contactData\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/51/contactDeals\",\n        \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/51/contactGoals\",\n        \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/51/contactLists\",\n        \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/51/contactLogs\",\n        \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/51/contactTags\",\n        \"deals\": \"https://:account.api-us1.com/api/3/contacts/51/deals\",\n        \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/51/fieldValues\",\n        \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/51/geoIps\",\n        \"notes\": \"https://:account.api-us1.com/api/3/contacts/51/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/contacts/51/organization\",\n        \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/51/plusAppend\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/51/scoreValues\",\n        \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/51/trackingLogs\"\n      },\n      \"organization\": null,\n      \"orgid\": \"0\",\n      \"phone\": \"\",\n      \"rating_tstamp\": \"0000-00-00\",\n      \"segmentio_id\": \"\",\n      \"sentcnt\": \"0\",\n      \"socialdata_lastcheck\": \"0000-00-00 00:00:00\",\n      \"ua\": \"\",\n      \"udate\": \"2017-02-03T11:26:41-06:00\"\n    }\n  ],\n    \"deal\": {\n        \"description\": \"This deal is an important deal\",\n        \"currency\": \"usd\",\n        \"percent\": null,\n        \"status\": 0,\n        \"title\": \"AC Deal\",\n        \"value\": 45600,\n        \"organization\": 45,\n        \"contact\": 1,\n        \"group\": \"1\",\n        \"owner\": \"1\",\n        \"stage\": \"1\",\n        \"cdate\": \"2019-12-09T12:29:33-06:00\",\n        \"mdate\": \"2019-12-09T12:29:33-06:00\",\n        \"nextdate\": null,\n        \"hash\": \"c3a5497c\",\n        \"winProbability\": null,\n        \"winProbabilityMdate\": null,\n        \"links\": {\n            \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/51/dealActivities\",\n            \"contact\": \"https://:account.api-us1.com/api/3/deals/51/contact\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/51/contactDeals\",\n            \"group\": \"https://:account.api-us1.com/api/3/deals/51/group\",\n            \"nextTask\": \"https://:account.api-us1.com/api/3/deals/51/nextTask\",\n            \"notes\": \"https://:account.api-us1.com/api/3/deals/51/notes\",\n            \"account\": \"https://:account.api-us1.com/api/3/deals/51/account\",\n            \"customerAccount\": \"https://:account.api-us1.com/api/3/deals/51/customerAccount\",\n            \"organization\": \"https://:account.api-us1.com/api/3/deals/51/organization\",\n            \"owner\": \"https://:account.api-us1.com/api/3/deals/51/owner\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/51/scoreValues\",\n            \"stage\": \"https://:account.api-us1.com/api/3/deals/51/stage\",\n            \"tasks\": \"https://:account.api-us1.com/api/3/deals/51/tasks\",\n            \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/51/dealCustomFieldData\"\n        },\n        \"fields\": [\n            {\n                \"customFieldId\": 1,\n                \"fieldValue\": \"First field value\",\n                \"dealId\": \"51\"\n            },\n            {\n                \"customFieldId\": 2,\n                \"fieldValue\": \"2008-01-20\",\n                \"dealId\": \"51\"\n            },\n            {\n                \"customFieldId\": 3,\n                \"fieldValue\": 5500,\n                \"fieldCurrency\": \"EUR\",\n              \t\"dealId\": \"51\"\n            }\n        ],\n        \"id\": \"51\",\n        \"isDisabled\": false,\n        \"account\": 45,\n        \"customerAccount\": 45\n    },\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-01-20T09:27:32-06:00\",\n      \"color\": \"C481DF\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"1\",\n      \"id\": \"1\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/1/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"To Contact\",\n      \"udate\": \"2017-01-20T09:27:32-06:00\",\n      \"width\": \"280\"\n    }\n  ]\n}\n"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all deals","description":"Retrieve all existing deals","operationId":"list-all-deals","x-canonical-resource":"deal","parameters":[{"name":"filters[search]","in":"query","description":"Search text to use with `search_field` parameter.","schema":{"type":"string"}},{"name":"filters[search_field]","in":"query","description":"Field to search for. See [available values](https://developers.activecampaign.com/reference/deal#deals-parameters-available-values).","schema":{"type":"string"}},{"name":"filters[title]","in":"query","description":"Filter by deal's title","schema":{"type":"string"}},{"name":"filters[stage]","in":"query","description":"Filter by deal's stage","schema":{"type":"integer","format":"int32"}},{"name":"filters[group]","in":"query","description":"Filter by deal's pipeline","schema":{"type":"integer","format":"int32"}},{"name":"filters[status]","in":"query","description":"Filter by deal's status.  See [available values](https://developers.activecampaign.com/reference/deal#deals-parameters-available-values)","schema":{"type":"integer","format":"int32"}},{"name":"filters[owner]","in":"query","description":"Filter by deal's owner","schema":{"type":"integer","format":"int32"}},{"name":"filters[nextdate_range]","in":"query","description":"Filter by deal's tasks due dates. See [available values](https://developers.activecampaign.com/reference/deal#deals-parameters-available-values)","schema":{"type":"string"}},{"name":"filters[tag]","in":"query","description":"Filter by tag names associated with deal's primary contact. See [available values](https://developers.activecampaign.com/reference/deal#deals-parameters-available-values).","schema":{"type":"string"}},{"name":"filters[tasktype]","in":"query","description":"Filter by deals that have tasks with given type","schema":{"type":"string"}},{"name":"filters[created_before]","in":"query","description":"Returns deals that are created less than given date","schema":{"type":"string","format":"date"}},{"name":"filters[created_after]","in":"query","description":"Returns deals that are created greater than or equal to given date","schema":{"type":"string","format":"date"}},{"name":"filters[updated_before]","in":"query","description":"Returns deals that are updated less than given date","schema":{"type":"string","format":"date"}},{"name":"filters[updated_after]","in":"query","description":"Returns deals that are updated greater than or equal to given date","schema":{"type":"string","format":"date"}},{"name":"filters[organization]","in":"query","description":"Filter by deal's primary contact's organization's id","schema":{"type":"integer","format":"int32"}},{"name":"filters[minimum_value]","in":"query","description":"In USD with dollar portion. Returns deals whose values are greater than or equal to given value","schema":{"type":"integer","format":"int32"}},{"name":"filters[maximum_value]","in":"query","description":"In USD with dollar portion. Returns deals whose values are less than or equal to given value","schema":{"type":"integer","format":"int32"}},{"name":"filters[score_greater_than]","in":"query","description":"In a format of `<score_id>:<score_value>`. Returns deals whose score value is greater than given value","schema":{"type":"string"}},{"name":"filters[score_less_than]","in":"query","description":"In a format of `<score_id>:<score_value>`. Returns deals whose score value is less than given value","schema":{"type":"string"}},{"name":"filters[score]","in":"query","description":"In a format of `<score_id>:<score_value>`. Returns deals whose score value is equal to given value","schema":{"type":"string"}},{"name":"orders[title]","in":"query","description":"Order by deal's title.","schema":{"type":"string","default":"ASC"}},{"name":"orders[value]","in":"query","description":"Order by deal's value.","schema":{"type":"string","default":"ASC"}},{"name":"orders[cdate]","in":"query","description":"Order by deal's created date.","schema":{"type":"string","default":"ASC"}},{"name":"orders[contact_name]","in":"query","description":"Order by deal's primary contact's first name.","schema":{"type":"string","default":"ASC"}},{"name":"orders[contact_orgname]","in":"query","description":"Order by deal's primary contact's organization name.","schema":{"type":"string","default":"ASC"}},{"name":"orders[next-action]","in":"query","description":"Order by deal's next task's due date first. Then append deals with no next task. Lastly append deals with overdue tasks. If dates are the same, order by deal's id.","schema":{"type":"string","default":"ASC"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"deals\": [\n    {\n      \"owner\": \"1\",\n      \"contact\": \"39\",\n      \"organization\": \"20\",\n      \"group\": \"1\",\n      \"stage\": \"2\",\n      \"title\": \"Able Hyena\",\n      \"description\": \"Article do skill hope.\",\n      \"percent\": \"0\",\n      \"cdate\": \"2019-09-06T11:29:48-05:00\",\n      \"mdate\": \"2019-09-06T11:29:48-05:00\",\n      \"nextdate\": null,\n      \"nexttaskid\": null,\n      \"value\": \"1872151\",\n      \"currency\": \"usd\",\n      \"winProbability\": 44,\n      \"winProbabilityMdate\": \"2019-10-05T12:27:22-05:00\",\n      \"status\": \"0\",\n      \"activitycount\": \"1\",\n      \"nextdealid\": \"46\",\n      \"edate\": \"2019-11-22 14:15:37\",\n      \"links\": {\n      \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/46/dealActivities\",\n      \"contact\":\"https://:account.api-us1.com/api/3/deals/46/contact\",\n      \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/46/contactDeals\",\n      \"group\": \"https://:account.api-us1.com/api/3/deals/46/group\",\n      \"nextTask\": \"https://:account.api-us1.com/api/3/deals/46/nextTask\",\n      \"notes\": \"https://:account.api-us1.com/api/3/deals/46/notes\",\n      \"account\": \"https://:account.api-us1.com/api/3/deals/46/account\",\n      \"customerAccount\": \"https://:account.api-us1.com/api/3/deals/46/customerAccount\",\n      \"organization\": \"https://:account.api-us1.com/api/3/deals/46/organization\",\n      \"owner\": \"https://:account.api-us1.com/api/3/deals/46/owner\",\n      \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/46/scoreValues\",\n      \"stage\": \"https://:account.api-us1.com/api/3/deals/46/stage\",\n      \"tasks\": \"https://:account.api-us1.com/api/3/deals/46/tasks\",\n      \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/46/dealCustomFieldData\"\n\t\t},\n    \"id\": \"46\",\n    \"isDisabled\": false,\n    \"account\": \"20\",\n    \"customerAccount\": \"20\"\n\t\t},\n    {\n      \"activitycount\": \"62\",\n      \"cdate\": \"2017-01-20T09:28:02-06:00\",\n      \"contact\": \"44\",\n      \"currency\": \"usd\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"group\": \"2\",\n      \"hash\": \"d6ca7d0b\",\n      \"id\": \"1\",\n      \"links\": {\n        \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/1/dealActivities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/1/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/1/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/1/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/1/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/1/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/1/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/1/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/1/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/1/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/1/tasks\"\n      },\n      \"mdate\": \"2017-02-06T12:21:12-06:00\",\n      \"nextTask\": \"2\",\n      \"nextdate\": \"2017-02-06T12:00:00-06:00\",\n      \"nextdealid\": \"1\",\n      \"nexttaskid\": \"2\",\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"3\",\n      \"status\": \"1\",\n      \"title\": \"Test Deal\",\n      \"description\": \"A deal that will make a big difference\",\n      \"value\": \"10000\"\n    },\n    {\n        \"id\": \"2\",\n        \"isDisabled\": 1,\n        \"title\": \"Demo Requested\"\n    }\n  ],\n  \"meta\": {\n    \"currencies\": {\n      \"USD\": {\n        \"currency\": \"USD\",\n        \"total\": \"3\",\n        \"value\": \"30000\"\n      }\n    },\n    \"total\": 3\n  }\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"owner":{"type":"string","example":"1"},"contact":{"type":"string","example":"39"},"organization":{"type":"string","example":"20"},"group":{"type":"string","example":"1"},"stage":{"type":"string","example":"2"},"title":{"type":"string","example":"Able Hyena"},"description":{"type":"string","example":"Article do skill hope."},"percent":{"type":"string","example":"0"},"cdate":{"type":"string","example":"2019-09-06T11:29:48-05:00"},"mdate":{"type":"string","example":"2019-09-06T11:29:48-05:00"},"nextdate":{},"nexttaskid":{},"value":{"type":"string","example":"1872151"},"currency":{"type":"string","example":"usd"},"winProbability":{"type":"integer","example":44,"default":0},"winProbabilityMdate":{"type":"string","example":"2019-10-05T12:27:22-05:00"},"status":{"type":"string","example":"0"},"activitycount":{"type":"string","example":"1"},"nextdealid":{"type":"string","example":"46"},"edate":{"type":"string","example":"2019-11-22 14:15:37"},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/dealActivities"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/contact"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/contactDeals"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/group"},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/nextTask"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/notes"},"account":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/account"},"customerAccount":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/customerAccount"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/organization"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/owner"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/scoreValues"},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/stage"},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/tasks"},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/46/dealCustomFieldData"}}},"id":{"type":"string","example":"46"},"isDisabled":{"type":"boolean","example":false,"default":true},"account":{"type":"string","example":"20"},"customerAccount":{"type":"string","example":"20"}}}},"meta":{"type":"object","properties":{"currencies":{"type":"object","properties":{"USD":{"type":"object","properties":{"currency":{"type":"string","example":"USD"},"total":{"type":"string","example":"3"},"value":{"type":"string","example":"30000"}}}}},"total":{"type":"integer","example":3,"default":0}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/deals/bulkUpdate":{"patch":{"summary":"Bulk Update Deal Owners","description":"Update an existing deal","operationId":"bulk-update-deal-owners","x-canonical-resource":"deal","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"properties":{"id":{"type":"string","description":"id of the Deal"},"ownerId":{"type":"string","description":"id of the Deal's Owner"}},"type":"object","additionalProperties":false}},"validationOnly":{"type":"boolean","description":"true validates the items and returns without updating any deal."}}},"examples":{"Correct request":{"value":{"deals":[{"id":1,"ownerId":1},{"id":2,"ownerId":1},{"id":3,"ownerId":1}]}},"Missing ownerId":{"value":{"deals":[{"id":1},{"id":2,"ownerId":2}]}},"Non-existing deal id":{"value":{"deals":[{"id":99999999,"ownerId":2}]}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"success\": [\n        \"1\",\n        \"2\"\n    ],\n    \"nochange\": [\n        \"3\"\n    ],\n    \"failed\": []\n}"}},"schema":{"type":"object","properties":{"success":{"type":"array","items":{"type":"string","example":"1"}},"nochange":{"type":"array","items":{"type":"string","example":"3"}},"failed":{"type":"array"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Mandatory ownerId":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"ownerId is required for a deal '1'.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"ownerId is required for a deal '1'."}}}}}}},"text/plain":{"examples":{"Non-existing ownerId":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Owner(user) with id '999999' was not found for a deal '1'.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Owner(user) with id '999999' was not found for a deal '1'."}}}}}}}}}},"deprecated":false,"x-readme":{"code-samples":[{"language":"text","code":"{\n    \"deals\": [\n        {\n            \"id\": 1,\n            \"ownerId\": 999999\n        }\n    ]\n}","name":"Non-existing ownerId"}],"samples-languages":["text"]}}},"/deals/dealDuplicates":{"get":{"summary":"List possible duplicate deals for a contact","description":"Internal: backs the duplicate-deal warning on the contact page. Returns up to 10 open deals, newest first, whose primary contact is another contact with the same email domain as the contact in subscriberid, so the user can spot a deal that already exists for the same company. Returns an empty list when the account does not have the duplicate-deal check turned on, when the contact has no email address, when its email domain is gmail.com, yahoo.com, live.com or outlook.com, or when nothing matches. Only GET is accepted; other methods get 405.","operationId":"list-deal-duplicates","x-canonical-resource":"deal","parameters":[{"name":"subscriberid","in":"query","description":"ID of the contact to find possible duplicate deals for. Required when the duplicate-deal check is on: missing or 0 is a 400.","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Up to 10 open deals, newest first, each with its primary contact. An empty list when nothing matches or the check does not apply.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"dealName":{"type":"string","description":"Title of the deal."},"contactName":{"type":"string","description":"First and last name of the deal's primary contact, joined by a space."},"contactEmail":{"type":"string","description":"Email address of the deal's primary contact."}}}},"example":[{"dealName":"Acme renewal","contactName":"Jane Doe","contactEmail":"jane@acme.example"}]}}},"400":{"description":"The duplicate-deal check is on and subscriberid is missing or 0.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string."},"detail":{"type":"string","description":"What was wrong."}}}}}},"example":{"errors":[{"status":"400","detail":"Please provide a subscriberid"}]}}}},"403":{"description":"The API user may not use deals, or the account has neither deals nor the CRM.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string."},"detail":{"type":"string","description":"What was wrong."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No contact with that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the id."}}},"example":{"message":"No Result found for Subscriber with id 12"}}}},"405":{"description":"A method other than GET. The Allow header says GET.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code."},"title":{"type":"string","description":"The error title."}}}}}},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}}},"deprecated":false,"x-internal":true}},"/deals/dealFieldValues":{"get":{"summary":"List distinct deal field values starting with a prefix","description":"Internal: backs autocomplete on deal filters. Returns the distinct values of one standard deal field (title, value or winProbability) that start with filters[value], across the account's deals. Blank values are left out. With limit the values are sorted in ascending order and cut to that many; without it every match comes back in no particular order. The prefix is matched with SQL LIKE, so % and _ in it act as wildcards. Legacy endpoint with no method guard: any HTTP method is answered the same way, always from the query string; GET is the documented verb and the one the app uses.","operationId":"list-deal-field-values","x-canonical-resource":"deal","parameters":[{"name":"filters[field]","in":"query","description":"The deal field to read: title, value (the deal value in cents) or winProbability (whole percent).","required":true,"schema":{"type":"string","enum":["title","value","winProbability"]}},{"name":"filters[value]","in":"query","description":"Prefix the values must start with. May be empty, which matches every value.","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Most values to return, sorted in ascending order. Leave out, or send 0, for every match unsorted. Otherwise it is read as a whole number, and anything that reads as less than 1 (a negative number, or text that is not a number) is a 422.","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"The matching values, as strings.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","description":"One distinct value of the field."}},"example":["Acme renewal","Acme upsell"]}}},"403":{"description":"The API user may not use deals, or the account has neither deals nor the CRM.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string."},"detail":{"type":"string","description":"What was wrong."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"filters[field] or filters[value] is missing, filters[field] is not title, value or winProbability, or limit is not a whole number of 1 or more.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string."},"detail":{"type":"string","description":"What was wrong."}}}}}}}}}},"deprecated":false,"x-internal":true}},"/deals/{id}":{"get":{"summary":"Retrieve a deal","description":"One deal by its id: its title, value and currency, the pipeline (group) and stage it is in, its owner, its primary contact and account, and its status (0 open, 1 won, 2 lost). A user who is not allowed to see all deals can read only the deals they own and gets 403 for any other. A deal in a pipeline the user cannot see comes back with isDisabled true and only its id, title and status. Returns 404 if the deal does not exist, or if it has neither a primary contact nor an account. To list the deals on which one contact is the primary contact, use GET /contacts/{id}/deals; to find deals by status, stage, pipeline or owner, use GET /deals.","operationId":"retrieve-a-deal","x-canonical-resource":"deal","parameters":[{"name":"id","in":"path","description":"The Deal's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"with pipeline permission":{"value":"{\n  \"deal\": {\n    \"owner\": \"1\",\n    \"contact\": \"39\",\n    \"organization\": \"20\",\n    \"group\": \"1\",\n    \"stage\": \"2\",\n    \"title\": \"Able Hyena\",\n    \"description\": \"Article do skill hope.\",\n    \"percent\": \"0\",\n    \"cdate\": \"2019-09-06T11:29:48-05:00\",\n    \"mdate\": \"2019-09-06T11:29:48-05:00\",\n    \"nextdate\": null,\n    \"nexttaskid\": null,\n    \"value\": \"1872151\",\n    \"currency\": \"usd\",\n    \"winProbability\": 44,\n    \"winProbabilityMdate\": \"2019-10-05T12:27:22-05:00\",\n    \"status\": \"0\",\n    \"activitycount\": \"1\",\n    \"nextdealid\": \"46\",\n    \"edate\": \"2019-11-22 14:15:37\",\n    \"links\": {\n    \t\"dealActivities\": \"https://:account.api-us1.com/api/3/deals/46/dealActivities\",\n    \t\"contact\": \"https://:account.api-us1.com/api/3/deals/46/contact\",\n    \t\"contactDeals\": \"https://:account.api-us1.com/api/3/deals/46/contactDeals\",\n    \t\"group\": \"https://:account.api-us1.com/api/3/deals/46/group\",\n    \t\"nextTask\": \"https://:account.api-us1.com/api/3/deals/46/nextTask\",\n    \t\"notes\": \"https://:account.api-us1.com/api/3/deals/46/notes\",\n    \t\"account\": \"https://:account.api-us1.com/api/3/deals/46/account\",\n    \t\"customerAccount\": \"https://:account.api-us1.com/api/3/deals/46/customerAccount\",\n    \t\"organization\": \"https://:account.api-us1.com/api/3/deals/46/organization\",\n    \t\"owner\": \"https://:account.api-us1.com/api/3/deals/46/owner\",\n    \t\"scoreValues\": \"https://:account.api-us1.com/api/3/deals/46/scoreValues\",\n    \t\"stage\": \"https://:account.api-us1.com/api/3/deals/46/stage\",\n    \t\"tasks\": \"https://:account.api-us1.com/api/3/deals/46/tasks\",\n    \t\"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/46/dealCustomFieldData\"\n    },\n    \"id\": \"46\",\n    \"isDisabled\": false,\n    \"account\": \"20\",\n    \"customerAccount\": \"20\"\n    }\n}"},"without pipeline permission":{"value":"{\n  \"deal\": {\n    \"id\": \"2\",\n    \"isDisabled\": true,\n    \"title\": \"Demo Requested\"\n  }\n}"}},"schema":{"type":"object","properties":{"deal":{"type":"object","properties":{"hash":{"type":"string","example":"8be32as98","description":"Random eight-character code given to the deal when it was created."},"owner":{"type":["string","null"],"example":"8","description":"Deal's owner id. Null when the deal has no owner."},"contact":{"type":["string","null"],"example":"8","description":"Deal's primary contact id. Null when the deal has an account and no primary contact."},"organization":{"type":["string","null"],"example":"5","description":"Deal's account id. Null when the deal has no account. Same value as account and customerAccount."},"group":{"type":"string","example":"1","description":"Deal's pipeline id."},"stage":{"type":"string","example":"4","description":"Deal's stage id."},"title":{"type":"string","example":"Acme Corp","description":"Deal's title."},"description":{"type":"string","example":"","description":"Deal's description. Empty when none."},"percent":{"type":"string","example":"0","description":"Deal's percentage."},"cdate":{"type":"string","example":"2021-06-30T15:27:44-05:00","description":"When the deal was created."},"mdate":{"type":"string","example":"2021-06-30T15:27:44-05:00","description":"When the deal was last changed, including when an activity was added to it."},"nextdate":{"type":["string","null"],"description":"Due date of the deal's next open task. Null when there is none."},"nexttaskid":{"type":["string","null"],"description":"Id of the deal's next open task. Null (0 on older deals) when there is none."},"value":{"type":"string","example":"494227","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero."},"currency":{"type":"string","example":"usd","description":"Deal's currency in 3-digit ISO format, lowercased."},"winProbability":{"type":["number","null"],"description":"Predicted chance of winning the deal, as a whole percentage rounded up. Returned as a number, not a string. Null when the account does not have win probability or it has not been calculated yet."},"winProbabilityMdate":{"type":["string","null"],"description":"When winProbability was last updated. Null when it has never been calculated or the account does not have win probability."},"status":{"type":"string","example":"2","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")."},"activitycount":{"type":"string","example":"1","description":"Number of activities recorded on the deal."},"nextdealid":{"type":"string","example":"3060","description":"Internal pointer used to order the pipeline's open deals: the id of the deal that follows this one. 0 when there is none."},"edate":{"type":["string","null"],"description":"When email activity was last gathered for the deal. Null when it never was. Returned as YYYY-MM-DD HH:MM:SS, not in ISO 8601 format."},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/dealActivities","description":"URL to list the deal's activities."},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/contact","description":"URL to the deal's primary contact."},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/contactDeals","description":"URL to list the links between the deal and its contacts."},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/group","description":"URL to the deal's pipeline."},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/nextTask","description":"URL to the deal's next open task."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/notes","description":"URL to list the deal's notes."},"account":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/account","description":"URL to the deal's account."},"customerAccount":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/customerAccount","description":"URL to the deal's account (same as account)."},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/organization","description":"URL to the deal's account (same as account)."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/owner","description":"URL to the deal's owner."},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/scoreValues","description":"URL to list the deal's score values."},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/stage","description":"URL to the deal's stage."},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/tasks","description":"URL to list the deal's tasks."},"dealCustomFieldData":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/3057/dealCustomFieldData","description":"URL to list the deal's custom field values."}},"description":"URLs of the deal's related resources."},"id":{"type":"string","example":"3057","description":"Id of the deal."},"isDisabled":{"type":"boolean","example":false,"default":false,"description":"True when the deal is in a pipeline the current user cannot see. Such a deal comes back with only id, title, status and isDisabled."},"nextTask":{"type":["string","null"],"description":"Id of the deal's next open task, as a relationship key. Same as nexttaskid when there is one; null on older deals whose nexttaskid is 0; absent when nexttaskid is null."},"account":{"type":["string","null"],"example":"5","description":"Deal's account id. Null when the deal has no account. Same value as customerAccount and organization."},"customerAccount":{"type":["string","null"],"example":"5","description":"Deal's account id, under another name. Null when the deal has no account. Same value as account and organization."}},"description":"The deal."}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Deal with id 100\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Deal with id 100","description":"Why the request failed."}}}}}}},"deprecated":false},"put":{"summary":"Update a deal","description":"Update an existing deal","operationId":"update-a-deal-new","x-canonical-resource":"deal","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The Deal's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deal":{"properties":{"title":{"type":"string","description":"Deal's title."},"description":{"type":"string","description":"Deal's description"},"account":{"type":"string","description":"Deal's account id"},"contact":{"type":"string","description":"Deal's primary contact id."},"value":{"type":"integer","description":"Deal's value in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"currency":{"type":"string","description":"Deal's currency in 3-digit ISO format, lowercased."},"group":{"type":"string","description":"Deal's pipeline id. Deal's stage or `deal.stage` should belong to `deal.group`."},"stage":{"type":"string","description":"Deal's stage id. `deal.stage` should belong to Deal's pipeline or `deal.group`.","default":"0"},"owner":{"type":"string","description":"Deal's owner id."},"percent":{"type":"integer","description":"Deal's percentage.","format":"int32"},"status":{"type":"integer","description":"Deal's status (0=\"open\", 1=\"won\", or 2=\"lost\")","default":0,"format":"int32"},"fields":{"type":"array","description":"Deal's custom field values `{customFieldId: string, fieldValue: string, fieldCurrency?:string}[]`","items":{"properties":{"customFieldId":{"type":"integer","description":"Field ID, ID of the Custom Field Meta Data","format":"int32"},"fieldValue":{"type":"string","description":"Updated field value. For `currency` field, this needs to be in cents not dollars (or 100 x Base Unit)."},"fieldCurrency":{"type":"string","description":"Required only for the `currency` field type. The three letter currency code for the currency value"}},"required":["customFieldId","fieldValue"],"type":"object"}},"customerAccount":{"type":"string","description":"Alternative to account: ID of the account (organization) the deal belongs to."},"organization":{"type":"string","description":"Alternative to account: ID of the account (organization) the deal belongs to."},"winProbability":{"type":["number","null"],"description":"Win probability score; null means it has not been calculated."},"locked":{"type":"integer","enum":[0,1]}},"required":[],"type":"object"},"saveDirtyFieldsOnly":{"type":"boolean","description":"true writes only the columns the request changed instead of every column of the deal."},"useDefaults":{"type":"boolean","description":"Read but has no effect."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"deal":{"contact":"51","account":"45","description":"This deal is an important deal","currency":"usd","group":"1","owner":"1","percent":null,"stage":"1","status":0,"title":"AC Deal","value":45600,"fields":[{"customFieldId":1,"fieldValue":"First field value"},{"customFieldId":2,"fieldValue":"2008-01-20"},{"customFieldId":3,"fieldValue":8800,"fieldCurrency":"USD"}]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"contacts\": [\n    {\n      \"adate\": \"2017-02-06 15:50:11\",\n      \"bounced_date\": \"0000-00-00\",\n      \"bounced_hard\": \"0\",\n      \"bounced_soft\": \"0\",\n      \"cdate\": \"2017-02-03T11:26:41-06:00\",\n      \"deleted\": \"0\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"email\": \"johndoe@example.com\",\n      \"email_domain\": \"\",\n      \"email_local\": \"\",\n      \"firstName\": \"\",\n      \"gravatar\": \"1\",\n      \"hash\": \"e1705a92f24edf5313ed21df44d6ff5f\",\n      \"id\": \"51\",\n      \"ip\": \"0\",\n      \"lastName\": \"\",\n      \"links\": {\n        \"bounceLogs\": \"https://:account.api-us1.com/api/3/contacts/51/bounceLogs\",\n        \"contactAutomations\": \"https://:account.api-us1.com/api/3/contacts/51/contactAutomations\",\n        \"contactData\": \"https://:account.api-us1.com/api/3/contacts/51/contactData\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/contacts/51/contactDeals\",\n        \"contactGoals\": \"https://:account.api-us1.com/api/3/contacts/51/contactGoals\",\n        \"contactLists\": \"https://:account.api-us1.com/api/3/contacts/51/contactLists\",\n        \"contactLogs\": \"https://:account.api-us1.com/api/3/contacts/51/contactLogs\",\n        \"contactTags\": \"https://:account.api-us1.com/api/3/contacts/51/contactTags\",\n        \"deals\": \"https://:account.api-us1.com/api/3/contacts/51/deals\",\n        \"fieldValues\": \"https://:account.api-us1.com/api/3/contacts/51/fieldValues\",\n        \"geoIps\": \"https://:account.api-us1.com/api/3/contacts/51/geoIps\",\n        \"notes\": \"https://:account.api-us1.com/api/3/contacts/51/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/contacts/51/organization\",\n        \"plusAppend\": \"https://:account.api-us1.com/api/3/contacts/51/plusAppend\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/contacts/51/scoreValues\",\n        \"trackingLogs\": \"https://:account.api-us1.com/api/3/contacts/51/trackingLogs\"\n      },\n      \"organization\": null,\n      \"orgid\": \"0\",\n      \"phone\": \"\",\n      \"rating_tstamp\": \"0000-00-00\",\n      \"segmentio_id\": \"\",\n      \"sentcnt\": \"0\",\n      \"socialdata_lastcheck\": \"0000-00-00 00:00:00\",\n      \"ua\": \"\",\n      \"udate\": \"2017-02-03T11:26:41-06:00\"\n    }\n  ],\n    \"deal\": {\n        \"description\": \"This deal is an important deal\",\n        \"currency\": \"usd\",\n        \"percent\": null,\n        \"status\": 0,\n        \"title\": \"AC Deal\",\n        \"value\": 45600,\n        \"organization\": 45,\n        \"contact\": 1,\n        \"group\": \"1\",\n        \"owner\": \"1\",\n        \"stage\": \"1\",\n        \"cdate\": \"2019-12-09T12:29:33-06:00\",\n        \"mdate\": \"2019-12-09T12:29:33-06:00\",\n        \"nextdate\": null,\n        \"hash\": \"c3a5497c\",\n        \"winProbability\": null,\n        \"winProbabilityMdate\": null,\n        \"links\": {\n            \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/51/dealActivities\",\n            \"contact\": \"https://:account.api-us1.com/api/3/deals/51/contact\",\n            \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/51/contactDeals\",\n            \"group\": \"https://:account.api-us1.com/api/3/deals/51/group\",\n            \"nextTask\": \"https://:account.api-us1.com/api/3/deals/51/nextTask\",\n            \"notes\": \"https://:account.api-us1.com/api/3/deals/51/notes\",\n            \"account\": \"https://:account.api-us1.com/api/3/deals/51/account\",\n            \"customerAccount\": \"https://:account.api-us1.com/api/3/deals/51/customerAccount\",\n            \"organization\": \"https://:account.api-us1.com/api/3/deals/51/organization\",\n            \"owner\": \"https://:account.api-us1.com/api/3/deals/51/owner\",\n            \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/51/scoreValues\",\n            \"stage\": \"https://:account.api-us1.com/api/3/deals/51/stage\",\n            \"tasks\": \"https://:account.api-us1.com/api/3/deals/51/tasks\",\n            \"dealCustomFieldData\": \"https://:account.api-us1.com/api/3/deals/51/dealCustomFieldData\"\n        },\n        \"fields\": [\n            {\n                \"customFieldId\": 1,\n                \"fieldValue\": \"First field value\",\n                \"dealId\": \"51\"\n            },\n            {\n                \"customFieldId\": 2,\n                \"fieldValue\": \"2008-01-20\",\n                \"dealId\": \"51\"\n            },\n            {\n                \"customFieldId\": 3,\n                \"fieldValue\": 8800,\n                \"fieldCurrency\": \"USD\",\n              \t\"dealId\": \"51\"\n            }\n        ],\n        \"id\": \"51\",\n        \"isDisabled\": false,\n        \"account\": 45,\n        \"customerAccount\": 45\n    },\n  \"dealStages\": [\n    {\n      \"cardRegion1\": \"title\",\n      \"cardRegion2\": \"next-action\",\n      \"cardRegion3\": \"show-avatar\",\n      \"cardRegion4\": \"contact-fullname-orgname\",\n      \"cardRegion5\": \"value\",\n      \"cdate\": \"2017-01-20T09:27:32-06:00\",\n      \"color\": \"C481DF\",\n      \"dealOrder\": \"next-action DESC\",\n      \"group\": \"1\",\n      \"id\": \"1\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/dealStages/1/group\"\n      },\n      \"order\": \"1\",\n      \"title\": \"To Contact\",\n      \"udate\": \"2017-01-20T09:27:32-06:00\",\n      \"width\": \"280\"\n    }\n  ]\n}\n"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a deal","description":"Delete an existing deal","operationId":"delete-a-deal","x-canonical-resource":"deal","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The Deal's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"patch":{"summary":"Update a deal (PATCH)","description":"The PATCH form of PUT /deals/{id} (update-a-deal-new): the same handler, body and response. Changes the fields sent under deal and leaves the rest as they are; custom field values sent under deal.fields are created or updated, and the deal update webhook fires once they are saved. A user who may not see all deals may only update deals they own, and changing the owner needs the deal reassign permission. On the ActiveCampaign company account a deal marked won or lost is locked, and only an admin can unlock it; on every other account locked is ignored. Returns 404 when the deal does not exist; 403 when the API user may not use deals, the account has neither deals nor the CRM, the user may not manage this deal, or the owner changes without permission to reassign deals; and 422 when the title contains emoji or other 4-byte characters or the deal fails validation (for example an unknown owner, pipeline or stage, a stage outside the pipeline, a negative value, or a description over 1000 characters).","operationId":"patch-a-deal","parameters":[{"name":"id","in":"path","description":"ID of the deal to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"deal":{"description":"The fields to change.","properties":{"title":{"description":"Title of the deal. Emoji and other 4-byte characters are refused, as are HTML tags.","type":"string"},"description":{"description":"Description of the deal, at most 1000 characters.","type":"string"},"account":{"description":"ID of the account (organization) the deal belongs to.","type":"string"},"contact":{"description":"ID of the deal's primary contact.","type":"string"},"value":{"description":"Value of the deal in cents, 0 or more.","type":"integer"},"currency":{"description":"Three-letter currency code, lower case.","type":"string"},"group":{"description":"ID of the pipeline. The stage must belong to it.","type":"string"},"stage":{"description":"ID of the stage. It must belong to the deal's pipeline.","type":"string"},"owner":{"description":"ID of the account user who owns the deal. Changing it needs the deal reassign permission.","type":"string"},"percent":{"description":"Percentage to show on the deal.","type":"integer"},"status":{"description":"0 open, 1 won, 2 lost.","type":"integer","enum":[0,1,2]},"locked":{"description":"0 or 1. Only read on the ActiveCampaign company account, where a non-admin cannot unlock a deal; ignored elsewhere.","type":"integer","enum":[0,1]},"fields":{"description":"Custom field values to create or update on the deal.","type":"array","items":{"required":["customFieldId","fieldValue"],"properties":{"customFieldId":{"description":"ID of the deal custom field.","type":"integer"},"fieldValue":{"description":"The value. For a currency field, in cents.","type":"string"},"fieldCurrency":{"description":"Three-letter currency code; only for a currency field.","type":"string"}},"type":"object"}}},"type":"object"},"saveDirtyFieldsOnly":{"description":"true writes only the columns the request changed instead of every column of the deal, so a concurrent change to another field is not overwritten. Defaults to false.","type":"boolean"}},"type":"object"},"example":{"deal":{"title":"AC Deal","value":45600,"currency":"usd","stage":"1","status":0}}}}},"responses":{"200":{"description":"The deal after the change, under deal.","content":{"application/json":{"schema":{"properties":{"deal":{"description":"The deal. Numbers come back as strings, except fields the request just set, which keep the type they were sent with.","properties":{"id":{"description":"ID of the deal.","type":"string","example":"51"},"hash":{"description":"Short random identifier of the deal.","type":"string","example":"c3a5497c"},"title":{"description":"Title of the deal.","type":"string","example":"AC Deal"},"description":{"description":"Description of the deal.","type":"string","example":"This deal is an important deal"},"owner":{"description":"ID of the account user who owns the deal.","type":"string","example":"1"},"contact":{"description":"ID of the deal's primary contact; 0 when it has none.","type":"string","example":"51"},"organization":{"description":"ID of the account (organization) the deal belongs to; 0 when it has none.","type":"string","example":"45"},"group":{"description":"ID of the deal's pipeline.","type":"string","example":"1"},"stage":{"description":"ID of the deal's stage.","type":"string","example":"1"},"value":{"description":"Value of the deal in cents.","type":"string","example":"45600"},"currency":{"description":"Three-letter currency code, lower case.","type":"string","example":"usd"},"percent":{"description":"Percentage the user set on the deal.","type":"string","example":"0"},"status":{"description":"0 open, 1 won, 2 lost.","type":"string","example":"0"},"locked":{"description":"Whether a won or lost deal is locked against changes. Only used on the ActiveCampaign company account; null elsewhere.","type":["string","null"],"example":null},"winProbability":{"description":"Calculated chance of winning the deal, in percent, rounded up; null when it has not been calculated or the feature is off for the account.","type":["number","null"],"example":null},"winProbabilityMdate":{"description":"When winProbability was last calculated; null when never or when the feature is off.","type":["string","null"],"example":null},"nextdate":{"description":"Due date of the deal's next task; null when it has none.","type":["string","null"],"example":null},"nexttaskid":{"description":"ID of the deal's next task; null when it has none.","type":["string","null"],"example":null},"activitycount":{"description":"Number of activities recorded on the deal.","type":"string","example":"0"},"nextdealid":{"description":"Maintained by the server for the legacy deal views; 0 when unset.","type":"string","example":"0"},"edate":{"description":"The deal's edate column as stored; null when unset.","type":["string","null"],"example":null},"cdate":{"description":"When the deal was created, as a date and time with UTC offset.","type":"string","example":"2019-12-09T12:29:33-06:00"},"mdate":{"description":"When the deal was last changed, as a date and time with UTC offset.","type":"string","example":"2019-12-09T12:29:33-06:00"},"fields":{"description":"The custom field values sent in the request, each with the deal id added. Empty when none were sent.","type":"array","items":{"properties":{"customFieldId":{"description":"ID of the deal custom field.","type":"integer","example":1},"fieldValue":{"description":"The value as sent.","type":"string","example":"First field value"},"fieldCurrency":{"description":"Currency of a currency field value, as sent.","type":"string","example":"USD"},"dealId":{"description":"ID of the deal.","type":"string","example":"51"}},"type":"object"}},"customFieldSaveStatus":{"description":"Whether the custom field values were saved. The deal itself is saved even when they were not.","properties":{"status":{"description":"success or failed.","type":"string","enum":["success","failed"],"example":"success"},"error":{"description":"Why saving the custom field values failed. Only when status is failed.","type":"string"},"details":{"description":"Further detail from the custom field service when saving failed; may be null.","type":["object","null"]}},"type":"object"},"links":{"description":"URLs of the records related to the deal, one per relationship: dealActivities, contact, contactDeals, group, nextTask, notes, account, customerAccount, organization, owner, scoreValues, stage, tasks and dealCustomFieldData.","type":"object","additionalProperties":{"type":"string"}}},"type":"object"}},"type":"object"}}}},"403":{"description":"The API user may not use deals, the account has neither deals nor the CRM, the user may not see all deals and does not own this one, or the owner changes without permission to reassign deals. Body: errors, a list with one item carrying status and detail."},"404":{"description":"No deal with that id. Body: message, a sentence naming the id."},"422":{"description":"The title contains emoji or other 4-byte characters, or the deal fails validation. Body: errors, a list with one item per problem carrying title, detail, code and, for field errors, source.pointer."}},"x-canonical-resource":"deal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/deals/{id}/notes":{"post":{"summary":"Create a deal note","description":"Create a new note for a deal","operationId":"create-a-deal-note","x-canonical-resource":"deal","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The Deal's id to assign new note to","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"The Deal note's content"},"is_draft":{"type":"integer","description":"0 or 1. 1 marks the note as a draft, 0 as fully created."}},"required":["note"],"type":"object","additionalProperties":false}}},"examples":{"Request Example":{"value":{"note":{"note":"Note for the deal"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"deals\": [\n    {\n      \"activitycount\": \"2\",\n      \"cdate\": \"2017-05-25T12:01:01-05:00\",\n      \"contact\": \"1\",\n      \"currency\": \"usd\",\n      \"edate\": null,\n      \"group\": \"1\",\n      \"hash\": \"e42436fc\",\n      \"id\": \"1\",\n      \"links\": {\n        \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/1/dealActivities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/1/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/1/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/1/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/1/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/1/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/1/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/1/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/1/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/1/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/1/tasks\"\n      },\n      \"mdate\": \"2017-05-25T12:17:23-05:00\",\n      \"nextdate\": null,\n      \"nextdealid\": \"1\",\n      \"nexttaskid\": null,\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"1\",\n      \"status\": \"0\",\n      \"title\": \"New Deal\",\n      \"value\": \"10000\"\n    }\n  ],\n  \"note\": {\n    \"cdate\": \"2017-05-31T09:54:30-05:00\",\n    \"id\": \"2\",\n    \"links\": {\n      \"activities\": \"https://:account.api-us1.com/api/3/notes/2/activities\",\n      \"mentions\": \"https://:account.api-us1.com/api/3/notes/2/mentions\",\n      \"notes\": \"https://:account.api-us1.com/api/3/notes/2/notes\",\n      \"owner\": \"https://:account.api-us1.com/api/3/notes/2/owner\",\n      \"user\": \"https://:account.api-us1.com/api/3/notes/2/user\"\n    },\n    \"mdate\": \"2017-05-31T09:54:30-05:00\",\n    \"note\": \"Note for the deal\",\n    \"owner\": {\n      \"id\": \"1\",\n      \"type\": \"deal\"\n    },\n    \"relid\": \"1\",\n    \"reltype\": \"Deal\",\n    \"user\": \"1\",\n    \"userid\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"activitycount":{"type":"string","example":"2"},"cdate":{"type":"string","example":"2017-05-25T12:01:01-05:00"},"contact":{"type":"string","example":"1"},"currency":{"type":"string","example":"usd"},"edate":{},"group":{"type":"string","example":"1"},"hash":{"type":"string","example":"e42436fc"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/dealActivities"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contact"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contactDeals"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/group"},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/nextTask"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/notes"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/organization"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/owner"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/scoreValues"},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/stage"},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/tasks"}}},"mdate":{"type":"string","example":"2017-05-25T12:17:23-05:00"},"nextdate":{},"nextdealid":{"type":"string","example":"1"},"nexttaskid":{},"organization":{},"owner":{"type":"string","example":"1"},"percent":{"type":"string","example":"0"},"stage":{"type":"string","example":"1"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"New Deal"},"value":{"type":"string","example":"10000"}}}},"note":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-05-31T09:54:30-05:00"},"id":{"type":"string","example":"2"},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/activities"},"mentions":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/mentions"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/notes"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/owner"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/user"}}},"mdate":{"type":"string","example":"2017-05-31T09:54:30-05:00"},"note":{"type":"string","example":"Note for the deal"},"owner":{"type":"object","properties":{"id":{"type":"string","example":"1"},"type":{"type":"string","example":"deal"}}},"relid":{"type":"string","example":"1"},"reltype":{"type":"string","example":"Deal"},"user":{"type":"string","example":"1"},"userid":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/deals/{id}/notes/{noteId}":{"put":{"summary":"Update a deal note","description":"Update an existing note for a deal","operationId":"update-a-deal-note","x-canonical-resource":"deal","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Deal's id to assign new note to","schema":{"type":"string"},"required":true},{"name":"noteId","in":"path","description":"Deal note's id to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"Deal note's content"},"is_draft":{"type":"integer","description":"0 or 1. 1 marks the note as a draft, 0 as fully created."}},"required":["note"],"type":"object","additionalProperties":false}}},"examples":{"Request Example":{"value":{"note":{"note":"Update with more info"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"deals\": [\n    {\n      \"activitycount\": \"3\",\n      \"cdate\": \"2017-06-01T13:40:04-05:00\",\n      \"contact\": \"1\",\n      \"currency\": \"usd\",\n      \"edate\": \"0000-00-00 00:00:00\",\n      \"group\": \"1\",\n      \"hash\": \"5604d5b5\",\n      \"id\": \"1\",\n      \"links\": {\n        \"dealActivities\": \"https://:account.api-us1.com/api/3/deals/1/dealActivities\",\n        \"contact\": \"https://:account.api-us1.com/api/3/deals/1/contact\",\n        \"contactDeals\": \"https://:account.api-us1.com/api/3/deals/1/contactDeals\",\n        \"group\": \"https://:account.api-us1.com/api/3/deals/1/group\",\n        \"nextTask\": \"https://:account.api-us1.com/api/3/deals/1/nextTask\",\n        \"notes\": \"https://:account.api-us1.com/api/3/deals/1/notes\",\n        \"organization\": \"https://:account.api-us1.com/api/3/deals/1/organization\",\n        \"owner\": \"https://:account.api-us1.com/api/3/deals/1/owner\",\n        \"scoreValues\": \"https://:account.api-us1.com/api/3/deals/1/scoreValues\",\n        \"stage\": \"https://:account.api-us1.com/api/3/deals/1/stage\",\n        \"tasks\": \"https://:account.api-us1.com/api/3/deals/1/tasks\"\n      },\n      \"mdate\": \"2017-06-01T13:41:57-05:00\",\n      \"nextTask\": \"1\",\n      \"nextdate\": \"2017-06-02T12:00:00-05:00\",\n      \"nextdealid\": \"1\",\n      \"nexttaskid\": \"1\",\n      \"organization\": null,\n      \"owner\": \"1\",\n      \"percent\": \"0\",\n      \"stage\": \"1\",\n      \"status\": \"0\",\n      \"title\": \"New deal\",\n      \"value\": \"10000\"\n    }\n  ],\n  \"note\": {\n    \"cdate\": \"2017-06-01T13:42:13-05:00\",\n    \"id\": \"2\",\n    \"links\": {\n      \"activities\": \"https://:account.api-us1.com/api/3/notes/2/activities\",\n      \"mentions\": \"https://:account.api-us1.com/api/3/notes/2/mentions\",\n      \"notes\": \"https://:account.api-us1.com/api/3/notes/2/notes\",\n      \"owner\": \"https://:account.api-us1.com/api/3/notes/2/owner\",\n      \"user\": \"https://:account.api-us1.com/api/3/notes/2/user\"\n    },\n    \"mdate\": \"2017-06-01T13:42:13-05:00\",\n    \"note\": \"Update with more info\",\n    \"owner\": {\n      \"id\": \"1\",\n      \"type\": \"deal\"\n    },\n    \"relid\": \"1\",\n    \"reltype\": \"Deal\",\n    \"user\": \"1\",\n    \"userid\": \"1\"\n  }\n}\n"}},"schema":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"activitycount":{"type":"string","example":"3"},"cdate":{"type":"string","example":"2017-06-01T13:40:04-05:00"},"contact":{"type":"string","example":"1"},"currency":{"type":"string","example":"usd"},"edate":{"type":"string","example":"0000-00-00 00:00:00"},"group":{"type":"string","example":"1"},"hash":{"type":"string","example":"5604d5b5"},"id":{"type":"string","example":"1"},"links":{"type":"object","properties":{"dealActivities":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/dealActivities"},"contact":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contact"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/contactDeals"},"group":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/group"},"nextTask":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/nextTask"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/notes"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/organization"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/owner"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/scoreValues"},"stage":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/stage"},"tasks":{"type":"string","example":"https://:account.api-us1.com/api/3/deals/1/tasks"}}},"mdate":{"type":"string","example":"2017-06-01T13:41:57-05:00"},"nextTask":{"type":"string","example":"1"},"nextdate":{"type":"string","example":"2017-06-02T12:00:00-05:00"},"nextdealid":{"type":"string","example":"1"},"nexttaskid":{"type":"string","example":"1"},"organization":{},"owner":{"type":"string","example":"1"},"percent":{"type":"string","example":"0"},"stage":{"type":"string","example":"1"},"status":{"type":"string","example":"0"},"title":{"type":"string","example":"New deal"},"value":{"type":"string","example":"10000"}}}},"note":{"type":"object","properties":{"cdate":{"type":"string","example":"2017-06-01T13:42:13-05:00"},"id":{"type":"string","example":"2"},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/activities"},"mentions":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/mentions"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/notes"},"owner":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/owner"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/notes/2/user"}}},"mdate":{"type":"string","example":"2017-06-01T13:42:13-05:00"},"note":{"type":"string","example":"Update with more info"},"owner":{"type":"object","properties":{"id":{"type":"string","example":"1"},"type":{"type":"string","example":"deal"}}},"relid":{"type":"string","example":"1"},"reltype":{"type":"string","example":"Deal"},"user":{"type":"string","example":"1"},"userid":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/deductEmailTestCredit":{"put":{"summary":"Deduct an email test credit","description":"Takes one email test (inbox preview) credit from the account's balance. The balance never goes below 0: at 0 the call still succeeds and changes nothing. Internal: part of the bridge the campaigns service uses for email tests. No request body is read.","operationId":"deduct-email-test-credit","responses":{"200":{"description":"Done, including when the balance was already 0. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomCustomerProps/sync":{"post":{"summary":"Apply a store change to an ecommerce customer","description":"Applies one change a store reported for one of its customers. Deep Data, the ecommerce data service, calls it. `data.action` says which change: `CUSTOMER_TAGS_ADDED` adds the tags in `data.tags` to the customer's contact, creating any tag that does not exist yet; `CUSTOMER_TAGS_REMOVED` removes them from the contact, ignoring names that match no tag; `CUSTOMERS_MARKETING_CONSENT_UPDATE` stores the SMS consent in `data.consent` on the customer, and on the contact when it changes the contact's SMS consent. The customer is found by the connection's `externalid` (`data.conn`) and the customer's `externalid` (`data.externalId`).\n\n`data.action` must be present: a body without it is not answered with 400 but fails as a server error.","operationId":"sync-ecom-customer-props","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"description":"The change","required":["action","conn","externalId"],"properties":{"action":{"description":"Which change to apply. Any other value is refused with 400.","type":"string","enum":["CUSTOMER_TAGS_ADDED","CUSTOMER_TAGS_REMOVED","CUSTOMERS_MARKETING_CONSENT_UPDATE"],"example":"CUSTOMER_TAGS_ADDED"},"conn":{"description":"The connection's `externalid`, such as the Shopify shop domain","type":"string","example":"example.myshopify.com"},"externalId":{"description":"The customer's ID in the store","type":"string","example":"56789"},"tags":{"description":"Names of the tags to add or remove, for the two tag actions","type":"array","items":{"type":"string"},"example":["vip"]},"consent":{"description":"The SMS consent, for `CUSTOMERS_MARKETING_CONSENT_UPDATE`","properties":{"state":{"description":"The consent state, in any case: `SUBSCRIBED` gives SMS consent, `UNSUBSCRIBED` and `REDACTED` take it away. Any other value changes nothing and is still answered 200.","type":"string","example":"SUBSCRIBED"},"opt_in_level":{"description":"The opt-in level, stored on the customer as the store reports it. Required with a known `state`.","type":"string"},"consent_updated_at":{"description":"When the consent changed, stored on the customer and the contact as the store reports it. Required with a known `state`.","type":"string"}},"type":"object"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The change is applied","content":{"application/json":{"schema":{"properties":{"status":{"description":"Always `ok`","type":"string","example":"ok"}},"type":"object"}}}},"400":{"description":"Nothing is changed. An unknown `action` is answered with an empty JSON list. Otherwise the body names the problem: `conn` is missing (No connection external ID provided), no connection has that `externalid` (Connection not found), the connection has no customer with that `externalId` (Ecom customer not found), or, for the tag actions, the customer has no contact (Subscriber not found).","content":{"application/json":{"schema":{"oneOf":[{"description":"For an unknown `action`: always an empty list","type":"array","items":{},"maxItems":0},{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status","type":"integer","example":400},"title":{"description":"Name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong","type":"string","example":"Ecom customer not found"}},"type":"object"}}},"type":"object"}]}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomCustomers":{"post":{"summary":"Create a customer","description":"Create a new e-commerce customer resource.","operationId":"create-customer","x-canonical-resource":"ecomCustomers","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ecomCustomer":{"properties":{"connectionid":{"type":"string","description":"The id of the connection object for the service where the customer originates."},"externalid":{"type":"string","description":"The id of the customer in the external service."},"email":{"type":"string","description":"The email address of the customer."},"acceptsMarketing":{"type":"string","description":"Indication of whether customer has opt-ed in to marketing communications. 0 = not opted-in, 1 = opted-in. A value of 0 means the contact will match the \"Has not opted in to marketing\" segment condition and a value of 1 means the contact will match the \"Has opted in to marketing\" segment condition."},"connection":{"type":["integer","string"]},"phone":{"type":"string","maxLength":50},"sms_marketing_state":{"type":["string","null"]},"sms_opt_in_level":{"type":["string","null"]},"sms_consent_updated_at":{"type":["string","null"]},"firstName":{"type":"string"},"lastName":{"type":"string"}},"required":["connectionid","externalid","email"],"type":"object"}}},"examples":{"JSON":{"value":{"ecomCustomer":{"connectionid":"1","externalid":"56789","email":"alice@example.com","acceptsMarketing":"1"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"ecomCustomer\": {\n    \"connectionid\": \"1\",\n    \"externalid\": \"56789\",\n    \"email\": \"alice@example.com\",\n    \"links\": {\n      \"connection\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/connection\",\n      \"orders\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/orders\"\n    },\n    \"id\": \"1\",\n    \"connection\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"ecomCustomer":{"type":"object","properties":{"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"56789"},"email":{"type":"string","example":"alice@example.com"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/connection"},"orders":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/orders"}}},"id":{"type":"string","example":"1"},"connection":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all customers","description":"List all e-commerce customer resources.","operationId":"list-all-customers","x-canonical-resource":"ecomCustomers","parameters":[{"name":"filters[email]","in":"query","description":"Filter by the email address of a customer.","schema":{"type":"string"}},{"name":"filters[externalid]","in":"query","description":"Filter by the id of the customer in the external service.","schema":{"type":"string"}},{"name":"filters[connectionid]","in":"query","description":"Filter by the id of the connection object for the service where the customer originates.","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"GET /ecomCustomers (Example RESPONSE)":{"value":"{\n  \"ecomCustomers\": [\n    {\n      \"connectionid\": \"1\",\n      \"externalid\": \"56789\",\n      \"email\": \"alice@example.com\",\n      \"totalRevenue\": \"3280\",\n      \"totalOrders\": \"2\",\n      \"totalProducts\": \"2\",\n      \"avgRevenuePerOrder\": \"2285\",\n      \"avgProductCategory\": \"Electronics\",\n      \"tstamp\": \"2017-02-06T14:05:31-06:00\",\n      \"links\": {\n        \"connection\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/connection\",\n        \"orders\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/orders\"\n      },\n      \"id\": \"1\",\n      \"connection\": \"1\"\n    },\n    {\n      \"connectionid\": \"2\",\n      \"externalid\": \"44322\",\n      \"email\": \"alice@example.com\",\n      \"totalRevenue\": \"7599\",\n      \"totalOrders\": \"1\",\n      \"totalProducts\": \"1\",\n      \"avgRevenuePerOrder\": \"7599\",\n      \"avgProductCategory\": \"Books\",\n      \"tstamp\": \"2016-12-13T18:02:07-06:00\",\n      \"links\": {\n        \"connection\": \"https://:account.api-us1.com/api/3/ecomCustomers/3/connection\",\n        \"orders\": \"https://:account.api-us1.com/api/3/ecomCustomers/3/orders\"\n      },\n      \"id\": \"3\",\n      \"connection\": \"2\"\n    },\n    {\n      \"connectionid\": \"0\",\n      \"externalid\": \"0\",\n      \"email\": \"alice@example.com\",\n      \"totalRevenue\": \"10879\",\n      \"totalOrders\": \"3\",\n      \"totalProducts\": \"3\",\n      \"avgRevenuePerOrder\": \"3626\",\n      \"avgProductCategory\": \"Electronics\",\n      \"tstamp\": \"2017-02-06T14:05:31-06:00\",\n      \"links\": {\n        \"connection\": \"https://:account.api-us1.com/api/3/ecomCustomers/2/connection\",\n        \"orders\": \"https://:account.api-us1.com/api/3/ecomCustomers/2/orders\"\n      },\n      \"id\": \"2\",\n      \"connection\": null\n    }\n  ],\n  \"meta\": {\n    \"total\": \"3\"\n  }\n}"}},"schema":{"type":"object","properties":{"ecomCustomers":{"type":"array","items":{"type":"object","properties":{"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"56789"},"email":{"type":"string","example":"alice@example.com"},"totalRevenue":{"type":"string","example":"3280"},"totalOrders":{"type":"string","example":"2"},"totalProducts":{"type":"string","example":"2"},"avgRevenuePerOrder":{"type":"string","example":"2285"},"avgProductCategory":{"type":"string","example":"Electronics"},"tstamp":{"type":"string","example":"2017-02-06T14:05:31-06:00"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/connection"},"orders":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/orders"}}},"id":{"type":"string","example":"1"},"connection":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"3"}}}}}}}}},"deprecated":false}},"/ecomCustomers/sync":{"post":{"summary":"Create or update a customer and its contact","description":"Internal: used by the ecommerce integrations to sync a store customer. Finds the customer on the connection by email, then by externalid, then by phone (where phone-only contacts are enabled), and updates it, or creates one when none matches. The matching contact is then found by email or phone and updated, or created, with the name, phone and organisation fields; tags in tags or customer_tags are added to it and never removed; acceptsMarketing true adds it to the connection's ecommerce list. Fields take the stored snake_case names; the camelCase names the response uses are accepted too. Refused with 403 when the account has no Deep Data.","operationId":"sync-customer","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomCustomer"],"properties":{"ecomCustomer":{"description":"The customer to sync","required":["connectionid"],"properties":{"connectionid":{"description":"ID of the connection the customer belongs to; must exist","type":"integer","example":3},"externalid":{"description":"ID of the customer in the external store. An empty string is ignored.","type":"string","example":"56789"},"email":{"description":"Email address of the customer and its contact. Required unless the account has phone-only contacts enabled, in which case email or a valid phone is required. A contact is only synced when email or phone is given.","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer and its contact; normalised before it is stored","type":"string","example":"+1 555 555 0100"},"first_name":{"description":"First name, written to the contact only. firstName is accepted too.","type":"string","example":"Alice"},"last_name":{"description":"Last name, written to the contact only. lastName is accepted too.","type":"string","example":"Smith"},"orgname":{"description":"Name of the contact's account (organisation); created when no account has this name","type":"string","example":"Acme Inc"},"accepts_marketing":{"description":"Stored on the customer as 1 or 0. Ignored when acceptsMarketing is sent. Left out, with no acceptsMarketing either, the stored flag is set to 0.","type":"boolean","example":true},"acceptsMarketing":{"description":"When true, adds the contact to the connection's ecommerce list, or re-activates its membership there; false or left out never removes it. Also stored on the customer, in place of accepts_marketing.","type":"boolean","example":true},"sms_marketing_state":{"description":"SMS marketing state from the store, stored as given","type":"string","example":"SUBSCRIBED"},"sms_opt_in_level":{"description":"SMS opt-in level from the store, stored as given","type":"string","example":"SINGLE_OPT_IN"},"sms_consent_updated_at":{"description":"When the SMS consent last changed; an empty value is ignored","type":"string","example":"2026-10-01 12:00:00"},"customer_tags":{"description":"Store tags of the customer, as an array or a comma-separated string. Stored on the customer and added to the contact.","example":"vip, wholesale","oneOf":[{"type":"array","items":{"type":"string"}},{"type":"string"}]},"tags":{"description":"Tags to add to the contact. Takes precedence over customer_tags for the contact.","type":"array","items":{"type":"string"},"example":["vip"]},"total_revenue":{"description":"Lifetime revenue in cents; 0 for a new customer when left out","type":"integer","example":3280},"total_orders":{"description":"Number of orders; 0 for a new customer when left out","type":"integer","example":2},"total_products":{"description":"Number of products ordered; 0 for a new customer when left out","type":"integer","example":2},"avg_revenue_per_order":{"description":"Average revenue per order in cents; 0 for a new customer when left out","type":"integer","example":1640}},"type":"object"}},"type":"object"},"example":{"ecomCustomer":{"connectionid":3,"externalid":"56789","email":"alice@example.com","first_name":"Alice","last_name":"Smith","accepts_marketing":true,"acceptsMarketing":true}}}}},"responses":{"200":{"description":"The customer as stored. When a contact was synced, ecomCustomer.contactId is its ID.","content":{"application/json":{"schema":{"properties":{"ecomCustomer":{"description":"The customer as stored. Numbers come back as strings.","properties":{"id":{"description":"ID of the customer","type":"string","example":"12"},"connectionid":{"description":"ID of the connection the customer belongs to","type":"string","example":"3"},"externalid":{"description":"ID of the customer in the external store","type":"string","example":"56789"},"email":{"description":"Email address of the customer","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer, normalised","type":"string","example":"+15555550100"},"acceptsMarketing":{"description":"1 when the customer accepts marketing, else 0","type":"string","example":"1"},"totalRevenue":{"description":"Lifetime revenue in cents","type":"string","example":"3280"},"totalOrders":{"description":"Number of orders","type":"string","example":"2"},"totalProducts":{"description":"Number of products ordered","type":"string","example":"2"},"avgRevenuePerOrder":{"description":"Average revenue per order in cents","type":"string","example":"1640"},"tstamp":{"description":"When the customer was last written, ISO 8601","type":"string","example":"2026-10-15T09:30:00-05:00"},"links":{"description":"URLs of the related connection and orders","type":"object","example":{"connection":"https://:account.api-us1.com/api/3/ecomCustomers/12/connection","orders":"https://:account.api-us1.com/api/3/ecomCustomers/12/orders"}},"connection":{"description":"ID of the connection","type":"string","example":"3"},"contactId":{"description":"ID of the synced contact. Absent when neither email nor phone was given.","type":"integer","example":41}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body has no ecomCustomer object, or it is empty.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Empty ecomCustomer object\"","type":"string","example":"Empty ecomCustomer object"}},"type":"object"},"example":{"error":"Empty ecomCustomer object"}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Upgrade your account to enable Deep Data\"","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"422":{"description":"The customer failed validation: connectionid is missing or names no connection, or email is missing or invalid (with phone-only contacts enabled: neither email nor a valid phone is given). The body is the validation errors.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed rule","type":"array","items":{"properties":{"title":{"description":"What failed","type":"string","example":"The ecomCustomer connectionid was not provided."},"detail":{"description":"More detail; often empty","type":"string","example":""},"code":{"description":"field_missing, related_missing, duplicate or field_invalid","type":"string","example":"field_missing"},"error":{"description":"Machine-readable error name; often empty","type":"string","example":""},"source":{"description":"Which field failed","properties":{"pointer":{"description":"JSON pointer to the field","type":"string","example":"/data/attributes/connectionid"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomCustomers/{id}":{"get":{"summary":"Retrieve a customer","description":"Retrieve an existing e-commerce customer resource.","operationId":"get-customer","x-canonical-resource":"ecomCustomers","parameters":[{"name":"id","in":"path","description":"The id of the customer to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"ecomCustomer\": {\n        \"connectionid\": \"3\",\n        \"externalid\": \"1440117293120\",\n        \"email\": \"john.doe@example.com\",\n        \"totalRevenue\": \"150761\",\n        \"totalOrders\": \"1\",\n        \"totalProducts\": \"3\",\n        \"avgRevenuePerOrder\": \"150761\",\n        \"avgProductCategory\": \"Musical Instrument\",\n        \"tstamp\": \"2019-01-01T10:23:22-06:00\",\n        \"acceptsMarketing\": \"0\",\n        \"links\": {\n            \"connection\": \"https://:account.api-us1.com/api/:version/ecomCustomers/15/connection\",\n            \"orders\": \"https://:account.api-us1.com/api/:version/ecomCustomers/15/orders\"\n        },\n        \"id\": \"15\",\n        \"connection\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"ecomCustomer":{"type":"object","properties":{"connectionid":{"type":"string","example":"3"},"externalid":{"type":"string","example":"1440117293120"},"email":{"type":"string","example":"john.doe@example.com"},"totalRevenue":{"type":"string","example":"150761"},"totalOrders":{"type":"string","example":"1"},"totalProducts":{"type":"string","example":"3"},"avgRevenuePerOrder":{"type":"string","example":"150761"},"avgProductCategory":{"type":"string","example":"Musical Instrument"},"tstamp":{"type":"string","example":"2019-01-01T10:23:22-06:00"},"acceptsMarketing":{"type":"string","example":"0"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://:account.api-us1.com/api/:version/ecomCustomers/15/connection"},"orders":{"type":"string","example":"https://:account.api-us1.com/api/:version/ecomCustomers/15/orders"}}},"id":{"type":"string","example":"15"},"connection":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a customer","description":"Update an existing e-commerce customer resource.","operationId":"update-customer","x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The id of the customer to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ecomCustomer":{"properties":{"externalid":{"type":"string","description":"The id of the customer in the external service."},"connectionid":{"type":"string","description":"The id of the connection object for the service where the customer originates."},"email":{"type":"string","description":"The email address of the customer."},"acceptsMarketing":{"type":"string","description":"Indication of whether customer has opt-ed in to marketing communications. 0 = not opted-in, 1 = opted-in. A value of 0 means the contact will match the \"Has not opted in to marketing\" segment condition and a value of 1 means the contact will match the \"Has opted in to marketing\" segment condition."},"connection":{"type":["integer","string"]},"phone":{"type":"string","maxLength":50},"sms_marketing_state":{"type":["string","null"]},"sms_opt_in_level":{"type":["string","null"]},"sms_consent_updated_at":{"type":["string","null"]},"totalRevenue":{"type":"integer"},"totalOrders":{"type":"integer"},"totalProducts":{"type":"integer"},"avgRevenuePerOrder":{"type":"integer"}},"required":[],"type":"object"}}},"examples":{"JSON":{"value":{"ecomCustomer":{"externalid":"98765"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"ecomCustomer\": {\n    \"connectionid\": \"1\",\n    \"externalid\": \"98765\",\n    \"email\": \"alice@example.com\",\n    \"totalRevenue\": \"3280\",\n    \"totalOrders\": \"2\",\n    \"totalProducts\": \"2\",\n    \"avgRevenuePerOrder\": \"2285\",\n    \"avgProductCategory\": \"Electronics\",\n    \"tstamp\": \"2017-02-06T14:05:31-06:00\",\n    \"links\": {\n      \"connection\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/connection\",\n      \"orders\": \"https://:account.api-us1.com/api/3/ecomCustomers/1/orders\"\n    },\n    \"id\": \"1\",\n    \"connection\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"ecomCustomer":{"type":"object","properties":{"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"98765"},"email":{"type":"string","example":"alice@example.com"},"totalRevenue":{"type":"string","example":"3280"},"totalOrders":{"type":"string","example":"2"},"totalProducts":{"type":"string","example":"2"},"avgRevenuePerOrder":{"type":"string","example":"2285"},"avgProductCategory":{"type":"string","example":"Electronics"},"tstamp":{"type":"string","example":"2017-02-06T14:05:31-06:00"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/connection"},"orders":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomCustomers/1/orders"}}},"id":{"type":"string","example":"1"},"connection":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a customer","description":"Delete an existing e-commerce customer resource.","operationId":"delete-customer","x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The id of the customer to delete.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"patch":{"summary":"Update a customer (PATCH)","description":"Internal: the PATCH form of PUT /ecomCustomers/{id}, which it shares a handler with. Only the fields sent are changed. The customer must be one the current user can access. Writing a customer of the aggregate connection (connectionid 0) is refused with 403. Refused with 403 too when the account has no Deep Data.","operationId":"patch-customer","parameters":[{"name":"id","in":"path","description":"ID of the customer to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomCustomer"],"properties":{"ecomCustomer":{"description":"The fields to change","properties":{"connectionid":{"description":"ID of the connection the customer belongs to; must exist. 0, the aggregate connection, is refused.","type":"string","example":"3"},"externalid":{"description":"ID of the customer in the external store","type":"string","example":"98765"},"email":{"description":"Email address of the customer","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer; normalised before it is stored","type":"string","example":"+1 555 555 0100"},"acceptsMarketing":{"description":"1 when the customer has opted in to marketing, 0 when not","type":"string","example":"1"}},"type":"object"}},"type":"object"},"example":{"ecomCustomer":{"externalid":"98765"}}}}},"responses":{"200":{"description":"The customer as stored after the update","content":{"application/json":{"schema":{"properties":{"ecomCustomer":{"description":"The customer as stored. Numbers come back as strings.","properties":{"id":{"description":"ID of the customer","type":"string","example":"12"},"connectionid":{"description":"ID of the connection the customer belongs to","type":"string","example":"3"},"externalid":{"description":"ID of the customer in the external store","type":"string","example":"56789"},"email":{"description":"Email address of the customer","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer, normalised","type":"string","example":"+15555550100"},"acceptsMarketing":{"description":"1 when the customer accepts marketing, else 0","type":"string","example":"1"},"totalRevenue":{"description":"Lifetime revenue in cents","type":"string","example":"3280"},"totalOrders":{"description":"Number of orders","type":"string","example":"2"},"totalProducts":{"description":"Number of products ordered","type":"string","example":"2"},"avgRevenuePerOrder":{"description":"Average revenue per order in cents","type":"string","example":"1640"},"tstamp":{"description":"When the customer was last written, ISO 8601","type":"string","example":"2026-10-15T09:30:00-05:00"},"links":{"description":"URLs of the related connection and orders","type":"object","example":{"connection":"https://:account.api-us1.com/api/3/ecomCustomers/12/connection","orders":"https://:account.api-us1.com/api/3/ecomCustomers/12/orders"}},"connection":{"description":"ID of the connection","type":"string","example":"3"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The account has no Deep Data, the current user may not access this customer, or the body sets connectionid to 0. The detail is \"Upgrade your account to enable Deep Data\" or \"Forbidden\".","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"\"Upgrade your account to enable Deep Data\" or \"Forbidden\"","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Upgrade your account to enable Deep Data"}]}}}},"404":{"description":"No customer has this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the model and the ID","type":"string","example":"No Result found for EcomCustomer with id 12"}},"type":"object"},"example":{"message":"No Result found for EcomCustomer with id 12"}}}},"422":{"description":"The updated customer failed validation, for example connectionid names no connection. The body is the validation errors.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed rule","type":"array","items":{"properties":{"title":{"description":"What failed","type":"string","example":"The ecomCustomer connectionid was not provided."},"detail":{"description":"More detail; often empty","type":"string","example":""},"code":{"description":"field_missing, related_missing, duplicate or field_invalid","type":"string","example":"field_missing"},"error":{"description":"Machine-readable error name; often empty","type":"string","example":""},"source":{"description":"Which field failed","properties":{"pointer":{"description":"JSON pointer to the field","type":"string","example":"/data/attributes/connectionid"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomData/bulkSync":{"put":{"summary":"Queue a bulk sync of ecommerce customers and their orders (PUT)","description":"Checks a batch of up to 250 customers of one store connection, then queues a background job that syncs each one the way POST /ecomData/sync does, and answers 202 before any of them is saved. The ecommerce integration service calls it to push many customers at once. A customer that fails in the job is logged and skipped; the response cannot report it.\n\nThe same operation as POST /ecomData/bulkSync, under another verb.","operationId":"bulk-sync-ecom-data-via-put","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomData"],"properties":{"ecomData":{"description":"The connection and its customers. `connectionid` or `externalid` is required.","required":["customers"],"properties":{"connectionid":{"description":"ID of the connection (the store) the data belongs to. Takes precedence over `externalid`.","type":"integer","example":1},"externalid":{"description":"The connection's `externalid`, such as the Shopify shop domain. Used when `connectionid` is not sent.","type":"string","example":"example.myshopify.com"},"customers":{"description":"The customers, at most 250","type":"array","items":{"$ref":"#/components/schemas/EcomDataSyncCustomer"}}},"type":"object"}},"type":"object"}}}},"responses":{"202":{"description":"The batch passed the checks and the job is queued. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"400":{"description":"The payload failed validation, and nothing is saved. `errors` names each problem by the field it is about, plus `error_code`: `error code 2` when the connection is missing or not found (then it is the only problem reported), `error code 1` for any other problem.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Bulk ecom data sync payload validation failed"},"errors":{"description":"Error messages keyed by the path of the field they are about, such as `ecomData.connectionid`, plus `error_code`","type":"object","example":{"ecomData.customers":"Missing ecomData.customers.email on customer","error_code":"error code 1"},"additionalProperties":{"type":"string"}}},"type":"object"}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"413":{"description":"More than 250 customers were sent. Nothing is queued.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Batch size validation failed"}},"type":"object"}}}},"500":{"description":"The job could not be queued. The error is logged and nothing is saved.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Error while processing ecomData bulk sync"}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":true,"x-internal":true},"post":{"summary":"Queue a bulk sync of ecommerce customers and their orders","description":"Checks a batch of up to 250 customers of one store connection, then queues a background job that syncs each one the way POST /ecomData/sync does, and answers 202 before any of them is saved. The ecommerce integration service calls it to push many customers at once. A customer that fails in the job is logged and skipped; the response cannot report it.\n\nPUT /ecomData/bulkSync is the same operation under another verb.","operationId":"bulk-sync-ecom-data","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomData"],"properties":{"ecomData":{"description":"The connection and its customers. `connectionid` or `externalid` is required.","required":["customers"],"properties":{"connectionid":{"description":"ID of the connection (the store) the data belongs to. Takes precedence over `externalid`.","type":"integer","example":1},"externalid":{"description":"The connection's `externalid`, such as the Shopify shop domain. Used when `connectionid` is not sent.","type":"string","example":"example.myshopify.com"},"customers":{"description":"The customers, at most 250","type":"array","items":{"$ref":"#/components/schemas/EcomDataSyncCustomer"}}},"type":"object"}},"type":"object"}}}},"responses":{"202":{"description":"The batch passed the checks and the job is queued. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"400":{"description":"The payload failed validation, and nothing is saved. `errors` names each problem by the field it is about, plus `error_code`: `error code 2` when the connection is missing or not found (then it is the only problem reported), `error code 1` for any other problem.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Bulk ecom data sync payload validation failed"},"errors":{"description":"Error messages keyed by the path of the field they are about, such as `ecomData.connectionid`, plus `error_code`","type":"object","example":{"ecomData.customers":"Missing ecomData.customers.email on customer","error_code":"error code 1"},"additionalProperties":{"type":"string"}}},"type":"object"}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"413":{"description":"More than 250 customers were sent. Nothing is queued.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Batch size validation failed"}},"type":"object"}}}},"500":{"description":"The job could not be queued. The error is logged and nothing is saved.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Error while processing ecomData bulk sync"}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/ecomData/connectionDataRedaction":{"post":{"summary":"Redact the ecommerce data of a Shopify store","description":"Starts erasing everything a Shopify store connection brought in, for a Shopify request to erase a shop's data, and answers as soon as the work is queued. Background jobs delete the connection's customers 500 at a time, with their orders, the orders' products and the order activity, and then delete the connection itself. Contacts are not deleted by these jobs.\n\nServed by a legacy file, `api/3/ecomData/connectionDataRedaction.php`; the router accepts only POST and answers any other method with 405.","operationId":"redact-ecom-connection-data","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["externalConnectionId"],"properties":{"externalConnectionId":{"type":"string","description":"The connection's `externalid`: the Shopify shop domain","example":"example.myshopify.com"}}}}}},"responses":{"200":{"description":"The redaction is queued","content":{"application/json":{"schema":{"type":"object","properties":{"connectionExternalId":{"type":"string","description":"The `externalConnectionId` that was sent","example":"example.myshopify.com"},"status":{"type":"string","description":"Always this text followed by the connection's `externalid`","example":"Shopify shop/redact request received and processing for: example.myshopify.com"}}}}}},"400":{"description":"`externalConnectionId` is missing or empty, or the connection is not a Shopify store. Nothing is queued.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status","type":"integer","example":400},"title":{"description":"Name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong","type":"string","example":"Connection data redaction request must include the connection ID in the URI."}}}}}}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is queued.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}}}}}}}}},"404":{"description":"No connection has that `externalid`. Nothing is queued.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"type":"object","properties":{"status":{"description":"The HTTP status","type":"integer","example":404},"title":{"description":"Name of the HTTP status","type":"string","example":"Not Found"},"detail":{"description":"What went wrong","type":"string","example":"Connection 'example.myshopify.com' not found."}}}}}}}}}},"x-internal":true}},"/ecomData/create_ecom_coupon":{"post":{"summary":"Create a coupon in a connected store","description":"Asks Deep Data, the ecommerce data service, to create a discount coupon in a connected store, for the coupon block of the automation builder. Hosted forwards the five body fields to Deep Data and does not check them against the connections of the account; any other field is dropped. Only an empty body is refused here: a body without some of the fields is forwarded with those fields as null.","operationId":"create-ecom-coupon","requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"account_id":{"description":"ID of the ActiveCampaign account the store is connected to","type":"string","example":"1234"},"account_name":{"description":"Name of that ActiveCampaign account","type":"string","example":"example"},"service":{"description":"The connection's service, such as `shopify`","type":"string","example":"shopify"},"external_id":{"description":"The connection's `externalid`, such as the Shopify shop domain","type":"string","example":"example.myshopify.com"},"coupon_params":{"description":"The coupon to create, forwarded to Deep Data as it is sent","type":"object","additionalProperties":true}},"type":"object"}}}},"responses":{"200":{"description":"Deep Data's response body, passed through unchanged; its shape is Deep Data's. When Deep Data answers with a 4xx or 5xx error, its error body is passed through the same way and the status is still 200.","content":{"application/json":{"schema":{"description":"The body Deep Data returned"}}}},"400":{"description":"The body is empty, an empty object, or not JSON. Nothing is sent to Deep Data.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always the same text","type":"string","example":"Empty payload object"}},"type":"object"}}}}},"x-canonical-resource":"connections","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ecomData/customerRedaction":{"post":{"summary":"Redact a Shopify customer","description":"Erases one customer of a Shopify store connection, for a Shopify request to erase a customer's data: deletes the customer, their orders, the orders' products and the order activity. When that connection is where the customer's contact came from, the contact is deleted as well; otherwise the contact is kept. The customer is found on the connection by `email`, then by `phone` (phone only when the account has phone-only contacts).","operationId":"redact-ecom-customer","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["externalConnectionId"],"properties":{"externalConnectionId":{"description":"The connection's `externalid`: the Shopify shop domain","type":"string","example":"example.myshopify.com"},"email":{"description":"The customer's email address. `email` or `phone` is required.","type":"string","example":"alice@example.com"},"phone":{"description":"The customer's phone number, used when no customer matches `email`","type":"string","example":"+15555550123"}},"type":"object"}}}},"responses":{"200":{"description":"The customer is erased","content":{"application/json":{"schema":{"properties":{"customer":{"description":"The customer's email address, or their phone number when they have no email","type":"string","example":"alice@example.com"},"status":{"description":"`CUSTOMER_AND_CONTACT_DATA_REDACTED` when the connection is where the contact came from, so the contact was deleted too; `ONE_CUSTOMER_DATA_REDACTED` when only the customer was","type":"string","enum":["CUSTOMER_AND_CONTACT_DATA_REDACTED","ONE_CUSTOMER_DATA_REDACTED"],"example":"ONE_CUSTOMER_DATA_REDACTED"}},"type":"object"}}}},"400":{"description":"`externalConnectionId` is missing, `email` and `phone` are both missing, or the connection is not a Shopify store. Nothing is deleted.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status","type":"integer","example":400},"title":{"description":"Name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong","type":"string","example":"Customer redaction request must include the connection ID and customer email or phone."}},"type":"object"}}},"type":"object"}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is deleted.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"404":{"description":"No customer of that connection has that email or phone, or no connection has that `externalid`.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status","type":"integer","example":404},"title":{"description":"Name of the HTTP status","type":"string","example":"Not Found"},"detail":{"description":"What went wrong","type":"string","example":"Customer with identifier: alice@example.com not found for connection example.myshopify.com."}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomData/get_ecom_coupons":{"get":{"summary":"List a connected store's coupons","description":"Asks Deep Data, the ecommerce data service, for the discount coupons of a connected store, for the coupon block of the automation builder. Hosted forwards the four query parameters to Deep Data as strings, an empty string for each one left out, and does not check them against the connections of the account.","operationId":"list-ecom-coupons","parameters":[{"name":"account_id","in":"query","description":"ID of the ActiveCampaign account the store is connected to","required":false,"schema":{"type":"string"},"example":"1234"},{"name":"account_name","in":"query","description":"Name of that ActiveCampaign account","required":false,"schema":{"type":"string"},"example":"example"},{"name":"service","in":"query","description":"The connection's service, such as `shopify`","required":false,"schema":{"type":"string"},"example":"shopify"},{"name":"external_id","in":"query","description":"The connection's `externalid`, such as the Shopify shop domain","required":false,"schema":{"type":"string"},"example":"example.myshopify.com"}],"responses":{"200":{"description":"Deep Data's response body, passed through unchanged; its shape is Deep Data's. When Deep Data answers with a 4xx error, its error body is passed through the same way and the status is still 200.","content":{"application/json":{"schema":{"description":"The body Deep Data returned"}}}}},"x-canonical-resource":"connections","x-internal":true}},"/ecomData/sync":{"put":{"summary":"Sync one ecommerce customer and their orders (PUT)","description":"Creates or updates one customer of a store connection, then creates or updates the orders sent with them, before it answers. The ecommerce integration service calls it to push store data into ActiveCampaign. Creating a customer also creates their contact when none exists; see `EcomDataSyncCustomer` for how customers and orders are matched. The customer is saved before the orders, and the orders one at a time, so a failure part way leaves what was saved before it.\n\nThe same operation as POST /ecomData/sync, under another verb.","operationId":"sync-ecom-data-via-put","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomData"],"properties":{"ecomData":{"description":"The connection and the customer. `connectionid` or `externalid` is required.","required":["customer"],"properties":{"connectionid":{"description":"ID of the connection (the store) the data belongs to. Takes precedence over `externalid`.","type":"integer","example":1},"externalid":{"description":"The connection's `externalid`, such as the Shopify shop domain. Used when `connectionid` is not sent.","type":"string","example":"example.myshopify.com"},"customer":{"$ref":"#/components/schemas/EcomDataSyncCustomer"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The customer and orders are saved. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"400":{"description":"The payload failed validation, and nothing is saved. `errors` names each problem by the field it is about, plus `error_code`: `error code 2` when the connection is missing or not found (then it is the only problem reported), `error code 1` for any other problem.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Ecom data sync payload validation failed"},"errors":{"description":"Error messages keyed by the path of the field they are about, such as `ecomData.connectionid`, plus `error_code`","type":"object","example":{"ecomData.customer.email":"Missing ecomData.customer.email on customer","error_code":"error code 1"},"additionalProperties":{"type":"string"}}},"type":"object"}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"The customer or one of the orders failed validation when it was saved, for example an order without `currency`. Anything saved before it stays saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per problem","type":"array","items":{"properties":{"title":{"description":"What is wrong","type":"string"},"detail":{"description":"More detail; often empty","type":"string"},"code":{"description":"Kind of problem, such as `field_missing`","type":"string"},"error":{"description":"A further error identifier; may be empty","type":"string"},"source":{"description":"Which field","properties":{"pointer":{"description":"The field, as `/data/attributes/<field>`","type":"string","example":"/data/attributes/currency"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"Saving failed for another reason, such as two requests creating the same order at the same moment. The error is logged; part of the data may already be saved.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Error while processing ecomData sync"}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"post":{"summary":"Sync one ecommerce customer and their orders","description":"Creates or updates one customer of a store connection, then creates or updates the orders sent with them, before it answers. The ecommerce integration service calls it to push store data into ActiveCampaign. Creating a customer also creates their contact when none exists; see `EcomDataSyncCustomer` for how customers and orders are matched. The customer is saved before the orders, and the orders one at a time, so a failure part way leaves what was saved before it.\n\nPUT /ecomData/sync is the same operation under another verb.","operationId":"sync-ecom-data","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomData"],"properties":{"ecomData":{"description":"The connection and the customer. `connectionid` or `externalid` is required.","required":["customer"],"properties":{"connectionid":{"description":"ID of the connection (the store) the data belongs to. Takes precedence over `externalid`.","type":"integer","example":1},"externalid":{"description":"The connection's `externalid`, such as the Shopify shop domain. Used when `connectionid` is not sent.","type":"string","example":"example.myshopify.com"},"customer":{"$ref":"#/components/schemas/EcomDataSyncCustomer"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The customer and orders are saved. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"400":{"description":"The payload failed validation, and nothing is saved. `errors` names each problem by the field it is about, plus `error_code`: `error code 2` when the connection is missing or not found (then it is the only problem reported), `error code 1` for any other problem.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Ecom data sync payload validation failed"},"errors":{"description":"Error messages keyed by the path of the field they are about, such as `ecomData.connectionid`, plus `error_code`","type":"object","example":{"ecomData.customer.email":"Missing ecomData.customer.email on customer","error_code":"error code 1"},"additionalProperties":{"type":"string"}}},"type":"object"}}}},"403":{"description":"The account does not have Deep Data, the ecommerce data feature. Nothing is saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error","type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"403"},"detail":{"description":"What went wrong","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"The customer or one of the orders failed validation when it was saved, for example an order without `currency`. Anything saved before it stays saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per problem","type":"array","items":{"properties":{"title":{"description":"What is wrong","type":"string"},"detail":{"description":"More detail; often empty","type":"string"},"code":{"description":"Kind of problem, such as `field_missing`","type":"string"},"error":{"description":"A further error identifier; may be empty","type":"string"},"source":{"description":"Which field","properties":{"pointer":{"description":"The field, as `/data/attributes/<field>`","type":"string","example":"/data/attributes/currency"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"Saving failed for another reason, such as two requests creating the same order at the same moment. The error is logged; part of the data may already be saved.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always the same text","type":"string","example":"Error while processing ecomData sync"}},"type":"object"}}}}},"x-canonical-resource":"ecomCustomers","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomOrderProducts":{"get":{"summary":"List EcomOrderProducts","description":"","operationId":"list-ecomorderproducts","x-canonical-resource":"ecomOrderProducts","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"ecomOrderProducts\": [\n        {\n            \"orderid\": \"1\",\n            \"connectionid\": \"1\",\n            \"externalid\": \"1269385775\",\n            \"sku\": \"SKATE-8\",\n            \"name\": \"My Cool Skateboard\",\n            \"description\": \"This skateboard is so cool, it rides itself\",\n            \"price\": \"5000\",\n            \"quantity\": \"1\",\n            \"category\": \"skateboards\",\n            \"imageUrl\": \"https://example.com/images/skateboard.jpg\",\n            \"productUrl\": \"http://example.com/products/skate-8\",\n            \"createdDate\": \"2019-06-28T18:04:19-05:00\",\n            \"updatedDate\": \"2019-06-28T18:04:19-05:00\",\n            \"tstamp\": \"2019-06-28T18:04:19-05:00\",\n            \"links\": {\n                \"ecomOrder\": \"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder\"\n            },\n            \"id\": \"1\",\n            \"ecomOrder\": \"2\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"ecomOrderProducts":{"type":"array","items":{"type":"object","properties":{"orderid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"1269385775"},"sku":{"type":"string","example":"SKATE-8"},"name":{"type":"string","example":"My Cool Skateboard"},"description":{"type":"string","example":"This skateboard is so cool, it rides itself"},"price":{"type":"string","example":"5000"},"quantity":{"type":"string","example":"1"},"category":{"type":"string","example":"skateboards"},"imageUrl":{"type":"string","example":"https://example.com/images/skateboard.jpg"},"productUrl":{"type":"string","example":"http://example.com/products/skate-8"},"createdDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"updatedDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"tstamp":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"links":{"type":"object","properties":{"ecomOrder":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder"}}},"id":{"type":"string","example":"1"},"ecomOrder":{"type":"string","example":"2"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/ecomOrderProducts/{id}":{"get":{"summary":"Retrieve an EcomOrderProduct","description":"","operationId":"retrieve-an-ecomorderproduct","x-canonical-resource":"ecomOrderProducts","parameters":[{"name":"id","in":"path","description":"The ID of the product you'd like returned.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"ecomOrderProduct\": {\n        \"orderid\": \"1\",\n        \"connectionid\": \"1\",\n        \"externalid\": \"1269385775\",\n        \"sku\": \"SKATE-8\",\n        \"name\": \"My Cool Skateboard\",\n        \"description\": \"This skateboard is so cool, it rides itself\",\n        \"price\": \"5000\",\n        \"quantity\": \"1\",\n        \"category\": \"skateboards\",\n        \"imageUrl\": \"https://example.com/images/skateboard.jpg\",\n        \"productUrl\": \"http://example.com/products/skate-8\",\n        \"createdDate\": \"2019-06-28T18:04:19-05:00\",\n        \"updatedDate\": \"2019-06-28T18:04:19-05:00\",\n        \"tstamp\": \"2019-06-28T18:04:19-05:00\",\n        \"links\": {\n            \"ecomOrder\": \"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder\"\n        },\n        \"id\": \"1\",\n        \"ecomOrder\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"ecomOrderProduct":{"type":"object","properties":{"orderid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"1269385775"},"sku":{"type":"string","example":"SKATE-8"},"name":{"type":"string","example":"My Cool Skateboard"},"description":{"type":"string","example":"This skateboard is so cool, it rides itself"},"price":{"type":"string","example":"5000"},"quantity":{"type":"string","example":"1"},"category":{"type":"string","example":"skateboards"},"imageUrl":{"type":"string","example":"https://example.com/images/skateboard.jpg"},"productUrl":{"type":"string","example":"http://example.com/products/skate-8"},"createdDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"updatedDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"tstamp":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"links":{"type":"object","properties":{"ecomOrder":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder"}}},"id":{"type":"string","example":"1"},"ecomOrder":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for EcomOrderProduct with id {the id requested}\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for EcomOrderProduct with id {the id requested}"}}}}}}},"deprecated":false}},"/ecomOrders":{"post":{"summary":"Create an order","description":"Create a new e-commerce order resource.","operationId":"create-order","x-canonical-resource":"ecomOrders","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ecomOrder":{"properties":{"externalid":{"type":"string","description":"The id of the order in the external service. ONLY REQUIRED IF EXTERNALCHECKOUTID NOT INCLUDED."},"externalcheckoutid":{"type":"string","description":"The id of the cart in the external service. ONLY REQUIRED IF EXTERNALID IS NOT INCLUDED."},"source":{"type":"integer","description":"The order source code. 0 - historical, 1 - real-time. Only real-time orders (source = 1) will show up on your Ecommerce Dashboard and trigger the “Makes a purchase” automation start, abandoned cart actions, customer conversions, or revenue attributions.","format":"int32"},"email":{"type":"string","description":"The email address of the customer who placed the order."},"orderProducts":{"type":"array","items":{"properties":{"name":{"type":"string","description":"The name of the product"},"price":{"type":"integer","description":"The price of the product, in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"quantity":{"type":"integer","description":"The quantity ordered.","format":"int32"},"externalid":{"type":"string","description":"The id of the product in the external service."},"category":{"type":"string","description":"The category of the product."},"sku":{"type":"string","description":"The SKU for the product"},"description":{"type":"string","description":"The description of the product"},"imageUrl":{"type":"string","description":"An Image URL that displays an image of the product"},"productUrl":{"type":"string","description":"A URL linking to the product in your store"}},"required":["name","price","quantity","externalid"],"type":"object"}},"totalPrice":{"type":"integer","description":"The total price of the order in cents, including tax and shipping charges. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"shippingAmount":{"type":"integer","description":"The total shipping amount in cents for the order","format":"int32"},"taxAmount":{"type":"integer","description":"The total tax amount for the order in cents","format":"int32"},"discountAmount":{"type":"integer","description":"The total discount amount for the order in cents","format":"int32"},"currency":{"type":"string","description":"The currency of the order (3-digit ISO code, e.g., 'USD')."},"connectionid":{"type":"integer","description":"The id of the connection from which this order originated.","format":"int32"},"customerid":{"type":"integer","description":"The id of the customer associated with this order.","format":"int32"},"orderUrl":{"type":"string","description":"The URL for the order in the external service."},"externalCreatedDate":{"type":"string","description":"The date the order was placed.","format":"date"},"externalUpdatedDate":{"type":"string","description":"The date the order was updated."},"abandonedDate":{"type":"string","description":"The date the cart was abandoned. REQUIRED ONLY IF INCLUDING EXTERNALCHECKOUTID."},"shippingMethod":{"type":"string","description":"The shipping method of the order."},"orderNumber":{"type":"string","description":"The order number. This can be different than the externalid."},"orderDiscounts":{"type":"array","items":{"properties":{"name":{"type":"string","description":"The discount code or name of the discount"},"type":{"type":"string","description":"The type of discount, either 'order' for discount on the order, or 'shipping' for free shipping."},"discountAmount":{"type":"integer","description":"The amount of the discount in cents.","format":"int32"}},"required":[],"type":"object"}},"connection":{"type":"integer"},"customer":{"type":"integer"},"linkId":{"type":"string"},"orderDate":{"type":"string","format":"date-time","description":"Alias of externalCreatedDate; when sent, its value is stored as the external created date."},"phone":{"type":"string"}},"required":["externalid","source","email","orderProducts","totalPrice","currency","connectionid","customerid","externalCreatedDate"],"type":"object"}}},"examples":{"Request Example":{"value":{"ecomOrder":{"externalid":"3246315233","source":1,"email":"alice@example.com","orderProducts":[{"externalid":"PROD12345","name":"Pogo Stick","price":4900,"quantity":1,"category":"Toys","sku":"POGO-12","description":"lorem ipsum...","imageUrl":"https://example.com/product.jpg","productUrl":"https://store.example.com/product12345"},{"externalid":"PROD23456","name":"Skateboard","price":3000,"quantity":1,"category":"Toys","sku":"SK8BOARD145","description":"lorem ipsum...","imageUrl":"https://example.com/product.jpg","productUrl":"https://store.example.com/product45678"}],"orderDiscounts":[{"name":"1OFF","type":"order","discountAmount":100}],"orderUrl":"https://example.com/orders/3246315233","externalCreatedDate":"2016-09-13T17:41:39-04:00","externalUpdatedDate":"2016-09-14T17:41:39-04:00","shippingMethod":"UPS Ground","totalPrice":9111,"shippingAmount":200,"taxAmount":500,"discountAmount":100,"currency":"USD","orderNumber":"myorder-123","connectionid":1,"customerid":1}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"connections\": [\n        {\n            \"service\": \"example\",\n            \"externalid\": \"examplestore\",\n            \"name\": \"My Example Store\",\n            \"isInternal\": \"0\",\n            \"connectionType\": \"ecommerce\",\n            \"status\": \"1\",\n            \"syncStatus\": \"0\",\n            \"sync_request_time\": null,\n            \"sync_start_time\": null,\n            \"lastSync\": null,\n            \"logoUrl\": \"https://myexamplestore.com/images/logo.jpg\",\n            \"linkUrl\": \"https://myexamplestore.com\",\n            \"cdate\": \"2018-01-12T13:13:53-06:00\",\n            \"udate\": \"2018-01-12T13:13:53-06:00\",\n            \"credentialExpiration\": null,\n            \"links\": {\n                \"options\": \"https://exampleaccount.api-us1.com/api/3/connections/1/options\",\n                \"customers\": \"https://:account.api-us1.com/api/3/connections/1/customers\"\n            },\n            \"id\": \"1\",\n            \"serviceName\": \"example\"\n        }\n    ],\n    \"ecomOrderProducts\": [\n        {\n            \"externalid\": \"PROD12345\",\n            \"name\": \"Pogo Stick\",\n            \"price\": 4900,\n            \"quantity\": 1,\n            \"category\": \"Toys\",\n            \"sku\": \"POGO-12\",\n            \"description\": \"lorem ipsum...\",\n            \"imageUrl\": \"https://example.com/product.jpg\",\n            \"productUrl\": \"https://store.example.com/product12345\"\n        },\n        {\n            \"externalid\": \"PROD23456\",\n            \"name\": \"Skateboard\",\n            \"price\": 3000,\n            \"quantity\": 1,\n            \"category\": \"Toys\",\n            \"sku\": \"SK8BOARD145\",\n            \"description\": \"lorem ipsum...\",\n            \"imageUrl\": \"https://example.com/product.jpg\",\n            \"productUrl\": \"https://store.example.com/product45678\"\n        }\n    ],\n    \"ecomOrderDiscounts\": [\n        {\n            \"name\": \"1OFF\",\n            \"type\": \"order\",\n            \"orderid\": \"5355\",\n            \"discountAmount\": \"100\",\n            \"id\": \"1\",\n            \"createdDate\": \"2019-09-05T12:16:18-05:00\",\n            \"updatedDate\": \"2019-09-05T12:16:18-05:00\"\n        }\n    ],\n    \"ecomOrder\": {\n        \"externalid\": \"3246315233\",\n        \"source\": \"1\",\n        \"email\": \"alice@example.com\",\n        \"currency\": \"USD\",\n        \"connectionid\": \"1\",\n        \"customerid\": \"1\",\n        \"orderUrl\": \"https://example.com/orders/3246315233\",\n        \"shippingMethod\": \"UPS Ground\",\n        \"totalPrice\": 9111,\n        \"shippingAmount\": 200,\n        \"taxAmount\": 500,\n        \"discountAmount\": 100,\n        \"externalCreatedDate\": \"2016-09-13T16:41:39-05:00\",\n        \"totalProducts\": 2,\n        \"createdDate\": \"2019-09-05T12:16:18-05:00\",\n        \"updatedDate\": \"2019-09-05T12:16:18-05:00\",\n        \"state\": 1,\n        \"connection\": \"1\",\n        \"orderProducts\": [\n            \"1\",\n            \"2\"\n        ],\n        \"orderDiscounts\": [\n            \"1\"\n        ],\n        \"customer\": \"1\",\n        \"orderDate\": \"2016-09-13T16:41:39-05:00\",\n        \"tstamp\": \"2019-09-05T12:16:18-05:00\",\n        \"links\": {\n            \"connection\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/connection\",\n            \"customer\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/customer\",\n            \"orderProducts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderProducts\",\n            \"orderDiscounts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts\",\n            \"orderActivities\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderActivities\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"connections":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string","example":"example"},"externalid":{"type":"string","example":"examplestore"},"name":{"type":"string","example":"My Example Store"},"isInternal":{"type":"string","example":"0"},"connectionType":{"type":"string","example":"ecommerce"},"status":{"type":"string","example":"1"},"syncStatus":{"type":"string","example":"0"},"sync_request_time":{"type":["string","null"],"description":"When a sync of the connection was last requested, in ISO 8601. Null when none was requested. Returned in snake_case."},"sync_start_time":{},"lastSync":{},"logoUrl":{"type":"string","example":"https://myexamplestore.com/images/logo.jpg"},"linkUrl":{"type":"string","example":"https://myexamplestore.com"},"cdate":{"type":"string","example":"2018-01-12T13:13:53-06:00"},"udate":{"type":"string","example":"2018-01-12T13:13:53-06:00"},"credentialExpiration":{"type":["string","null"],"description":"When the connection's stored credentials expire, in ISO 8601. Null when they do not expire."},"links":{"type":"object","properties":{"options":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/connections/1/options"},"customers":{"type":"string","example":"https://:account.api-us1.com/api/3/connections/1/customers"}}},"id":{"type":"string","example":"1"},"serviceName":{"type":"string","example":"example","description":"Display name of the service. A service the platform does not know by name is returned as sent in `service`."}}}},"ecomOrderProducts":{"type":"array","items":{"type":"object","properties":{"externalid":{"type":"string","example":"PROD12345"},"name":{"type":"string","example":"Pogo Stick"},"price":{"type":"integer","example":4900,"default":0},"quantity":{"type":"integer","example":1,"default":0},"category":{"type":"string","example":"Toys"},"sku":{"type":"string","example":"POGO-12"},"description":{"type":"string","example":"lorem ipsum..."},"imageUrl":{"type":"string","example":"https://example.com/product.jpg"},"productUrl":{"type":"string","example":"https://store.example.com/product12345"}}}},"ecomOrderDiscounts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"1OFF"},"type":{"type":"string","example":"order"},"orderid":{"type":"string","example":"5355"},"discountAmount":{"type":"string","example":"100"},"id":{"type":"string","example":"1"},"createdDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"},"updatedDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"}}}},"ecomOrder":{"type":"object","properties":{"externalid":{"type":"string","example":"3246315233"},"source":{"type":"string","example":"1"},"email":{"type":"string","example":"alice@example.com"},"currency":{"type":"string","example":"USD"},"connectionid":{"type":"string","example":"1"},"customerid":{"type":"string","example":"1"},"orderUrl":{"type":"string","example":"https://example.com/orders/3246315233"},"shippingMethod":{"type":"string","example":"UPS Ground"},"totalPrice":{"type":"integer","example":9111,"default":0},"shippingAmount":{"type":"integer","example":200,"default":0},"taxAmount":{"type":"integer","example":500,"default":0},"discountAmount":{"type":"integer","example":100,"default":0},"externalCreatedDate":{"type":"string","example":"2016-09-13T16:41:39-05:00"},"totalProducts":{"type":"integer","example":2,"default":0},"createdDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"},"updatedDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"},"state":{"type":"integer","example":1,"default":0},"connection":{"type":"string","example":"1"},"orderProducts":{"type":"array","items":{"type":"string","example":"1"}},"orderDiscounts":{"type":"array","items":{"type":"string","example":"1"}},"customer":{"type":"string","example":"1"},"orderDate":{"type":"string","example":"2016-09-13T16:41:39-05:00"},"tstamp":{"type":"string","example":"2019-09-05T12:16:18-05:00"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/connection"},"customer":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/customer"},"orderProducts":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderProducts"},"orderDiscounts":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts"},"orderActivities":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderActivities"}}},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"get":{"summary":"List all orders","description":"List all existing e-commerce order resources.","operationId":"list-all-orders","x-canonical-resource":"ecomOrders","parameters":[{"name":"filters[connectionid]","in":"query","description":"Filter by the connection id. Must be greater than 0.","schema":{"type":"integer","format":"int32"}},{"name":"filters[externalid]","in":"query","description":"Filter by the external id of the order.","schema":{"type":"integer","format":"int32"}},{"name":"filters[externalcheckoutid]","in":"query","description":"Filter by the external checkout id","schema":{"type":"string"}},{"name":"filters[email]","in":"query","description":"Filter by the customer email address.","schema":{"type":"string"}},{"name":"filters[state]","in":"query","description":"Filter by the state of the order. 0 = Pending, 1 = Completed, 2 = Abandoned, 3 = Recovered, 4 = Waiting (Customer checked out but payment is not yet completed)","schema":{"type":"integer","format":"int32"}},{"name":"filters[customerid]","in":"query","description":"Filter by the customer id","schema":{"type":"string"}},{"name":"filters[external_created_date]","in":"query","description":"Filter by the external created date","schema":{"type":"string","format":"date"}},{"name":"orders[connectionid]","in":"query","description":"Order by connection ID. Accepted values are ASC or DESC.","schema":{"type":"integer","format":"int32"}},{"name":"orders[externalid]","in":"query","description":"Order by external ID. Accepted values are ASC or DESC.","schema":{"type":"integer","format":"int32"}},{"name":"orders[externalcheckoutid]","in":"query","description":"Order by external checkout ID. Accepted values are ASC or DESC.","schema":{"type":"string"}},{"name":"orders[email]","in":"query","description":"Order by email. Accepted values are ASC or DESC.","schema":{"type":"string"}},{"name":"orders[state]","in":"query","description":"Order by state. Accepted values are ASC or DESC.","schema":{"type":"integer","format":"int32"}},{"name":"orders[customerid]","in":"query","description":"Order by customer ID. Accepted values are ASC or DESC.","schema":{"type":"string"}},{"name":"orders[external_created_date]","in":"query","description":"Order by external created date. Accepted values are ASC or DESC.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"ecomOrders\": [\n    {\n      \"externalid\": \"3246315234\",\n      \"source\": \"1\",\n      \"email\": \"alice@example.com\",\n      \"currency\": \"USD\",\n      \"connectionid\": \"1\",\n      \"customerid\": \"1\",\n      \"orderUrl\": \"https://example.com/orders/3246315233\",\n      \"shippingMethod\": \"UPS Ground\",\n      \"totalPrice\": 9111,\n      \"shippingAmount\": 200,\n      \"taxAmount\": 500,\n      \"discountAmount\": 100,\n      \"externalCreatedDate\": \"2016-09-13T16:41:39-05:00\",\n      \"totalProducts\": 2,\n      \"createdDate\": \"2019-09-05T12:16:18-05:00\",\n      \"updatedDate\": \"2019-09-05T12:16:18-05:00\",\n      \"state\": 1,\n      \"connection\": \"1\",\n      \"orderProducts\": [\n        \"1\",\n        \"2\"\n      ],\n      \"customer\": \"1\",\n      \"orderDate\": \"2016-09-13T16:41:39-05:00\",\n      \"tstamp\": \"2019-09-05T12:16:18-05:00\",\n      \"links\": {\n        \"connection\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/connection\",\n        \"customer\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/customer\",\n        \"orderProducts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderProducts\",\n        \"orderDiscounts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts\",\n        \"orderActivities\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderActivities\"\n      },\n      \"id\": \"1\"\n    },\n    {\n      \"externalid\": \"47856739866\",\n      \"source\": \"1\",\n      \"email\": \"example@example.com\",\n      \"currency\": \"USD\",\n      \"connectionid\": \"1\",\n      \"customerid\": \"2\",\n      \"orderUrl\": \"https://example.com/orders/47856739866\",\n      \"shippingMethod\": \"UPS Ground\",\n      \"totalPrice\": 3450,\n      \"shippingAmount\": 100,\n      \"taxAmount\": 0,\n      \"discountAmount\": 0,\n      \"externalCreatedDate\": \"2019-09-06T02:10:00-05:00\",\n      \"totalProducts\": 2,\n      \"createdDate\": \"2019-09-06T02:10:00-05:00\",\n      \"updatedDate\": \"2019-09-06T02:10:00-05:00\",\n      \"state\": 1,\n      \"connection\": \"1\",\n      \"orderProducts\": [\n        \"3\"\n      ],\n      \"customer\": \"2\",\n      \"orderDate\": \"2019-09-06T02:10:00-05:00\",\n      \"tstamp\": \"2019-09-06T02:10:00-05:00\",\n      \"links\": {\n        \"connection\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/2/connection\",\n        \"customer\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/2/customer\",\n        \"orderProducts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/2/orderProducts\",\n        \"orderDiscounts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/2/orderDiscounts\",\n        \"orderActivities\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/2/orderActivities\"\n      },\n      \"id\": \"2\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/ecomOrders/{ecomOrderId}":{"get":{"summary":"Retrieve an order","description":"Retrieve an existing e-commerce order resource.","operationId":"get-order","x-canonical-resource":"ecomOrders","parameters":[{"name":"ecomOrderId","in":"path","description":"The id of the order to retrieve.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"ecomOrder\": {\n        \"customerid\": \"1\",\n        \"connectionid\": \"1\",\n        \"state\": \"1\",\n        \"source\": \"1\",\n        \"externalid\": \"1233456789\",\n        \"externalcheckoutid\": null,\n        \"orderNumber\": \"123456789\",\n        \"email\": \"alice@example.com\",\n        \"totalPrice\": \"1000\",\n        \"discountAmount\": \"100\",\n        \"shippingAmount\": \"120\",\n        \"taxAmount\": \"120\",\n        \"totalProducts\": \"1\",\n        \"currency\": \"usd\",\n        \"shippingMethod\": \"ground shipping\",\n        \"orderUrl\": \"https://examplestore.com/orders/123456789\",\n        \"externalCreatedDate\": \"2019-06-29T14:44:49-05:00\",\n        \"externalUpdatedDate\": \"2019-06-29T14:44:49-05:00\",\n        \"abandonedDate\": null,\n        \"createdDate\": \"2019-06-29T14:44:51-05:00\",\n        \"updatedDate\": \"2019-06-29T14:44:51-05:00\",\n        \"orderDate\": \"2019-06-29T14:44:49-05:00\",\n        \"tstamp\": \"2019-06-29T14:44:51-05:00\",\n        \"links\": {\n            \"connection\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/connection\",\n            \"customer\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/customer\",\n            \"orderProducts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderProducts\",\n            \"orderDiscounts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts\",\n            \"orderActivities\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderActivities\"\n        },\n        \"id\": \"1\",\n        \"connection\": \"1\",\n        \"customer\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"ecomOrder":{"type":"object","properties":{"customerid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"state":{"type":"string","example":"1"},"source":{"type":"string","example":"1"},"externalid":{"type":"string","example":"1233456789"},"externalcheckoutid":{},"orderNumber":{"type":"string","example":"123456789"},"email":{"type":"string","example":"alice@example.com"},"totalPrice":{"type":"string","example":"1000"},"discountAmount":{"type":"string","example":"100"},"shippingAmount":{"type":"string","example":"120"},"taxAmount":{"type":"string","example":"120"},"totalProducts":{"type":"string","example":"1"},"currency":{"type":"string","example":"usd"},"shippingMethod":{"type":"string","example":"ground shipping"},"orderUrl":{"type":"string","example":"https://examplestore.com/orders/123456789"},"externalCreatedDate":{"type":"string","example":"2019-06-29T14:44:49-05:00"},"externalUpdatedDate":{"type":"string","example":"2019-06-29T14:44:49-05:00"},"abandonedDate":{},"createdDate":{"type":"string","example":"2019-06-29T14:44:51-05:00"},"updatedDate":{"type":"string","example":"2019-06-29T14:44:51-05:00"},"orderDate":{"type":"string","example":"2019-06-29T14:44:49-05:00"},"tstamp":{"type":"string","example":"2019-06-29T14:44:51-05:00"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/connection"},"customer":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/customer"},"orderProducts":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderProducts"},"orderDiscounts":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts"},"orderActivities":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderActivities"}}},"id":{"type":"string","example":"1"},"connection":{"type":"string","example":"1"},"customer":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete an order","description":"Delete an existing e-commerce order resource.","operationId":"delete-order","x-canonical-resource":"ecomOrders","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"ecomOrderId","in":"path","description":"The id of the order to delete.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update an order","description":"Update an existing ecommerce order/cart resource.","operationId":"update-order","x-canonical-resource":"ecomOrders","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"ecomOrderId","in":"path","description":"The ID of the order to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ecomOrder":{"properties":{"externalid":{"type":"string","description":"The id of the order in the external service. ONLY REQUIRED IF EXTERNALCHECKOUTID NOT INCLUDED."},"externalcheckoutid":{"type":"string","description":"The id of the cart in the external service. ONLY REQUIRED IF EXTERNALID IS NOT INCLUDED."},"email":{"type":"string","description":"The email address of the customer who placed the order."},"orderProducts":{"type":"array","items":{"properties":{"name":{"type":"string","description":"The name of the product"},"price":{"type":"integer","description":"The price of the product, in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"quantity":{"type":"integer","description":"The quantity ordered.","format":"int32"},"externalid":{"type":"string","description":"The id of the product in the external service."},"category":{"type":"string","description":"The category of the product."},"sku":{"type":"string","description":"The SKU for the product"},"description":{"type":"string","description":"The description of the product"},"imageUrl":{"type":"string","description":"An Image URL that displays an image of the product"},"productUrl":{"type":"string","description":"A URL linking to the product in your store"}},"required":[],"type":"object"}},"totalPrice":{"type":"integer","description":"The total price of the order in cents, including tax and shipping charges. (i.e. $456.78 => 45678). Must be greater than or equal to zero.","format":"int32"},"shippingAmount":{"type":"integer","description":"The total shipping amount in cents for the order","format":"int32"},"taxAmount":{"type":"integer","description":"The total tax amount for the order in cents","format":"int32"},"discountAmount":{"type":"integer","description":"The total discount amount for the order in cents","format":"int32"},"currency":{"type":"string","description":"The currency of the order (3-digit ISO code, e.g., 'USD')."},"orderUrl":{"type":"string","description":"The URL for the order in the external service."},"externalUpdatedDate":{"type":"string","description":"The date the order was updated."},"abandonedDate":{"type":"string","description":"The date the cart was abandoned. REQUIRED ONLY IF INCLUDING EXTERNALCHECKOUTID."},"shippingMethod":{"type":"string","description":"The shipping method of the order."},"orderNumber":{"type":"string","description":"The order number in your system. This can be different than the external ID."},"orderDiscounts":{"type":"array","items":{"properties":{"name":{"type":"string","description":"The discount code or name of the discount"},"type":{"type":"string","description":"The type of discount, either 'order' for discount on the order, or 'shipping' for free shipping."},"discountAmount":{"type":"integer","description":"The amount of the discount in cents.","format":"int32"}},"required":[],"type":"object"}},"connection":{"type":"integer"},"connectionid":{"type":"integer"},"customer":{"type":"integer"},"customerid":{"type":"integer"},"externalCreatedDate":{"type":"string","format":"date-time"},"linkId":{"type":"string"},"orderDate":{"type":"string","format":"date-time","description":"Alias of externalCreatedDate; when sent, its value is stored as the external created date."},"phone":{"type":"string"},"source":{"type":"integer"}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"ecomOrder":{"externalid":"3246315237","email":"alice@example.com","orderProducts":[{"externalid":"PROD12345","name":"Pogo Stick","price":4900,"quantity":1,"category":"Toys","sku":"POGO-12","description":"lorem ipsum...","imageUrl":"https://example.com/product.jpg","productUrl":"https://store.example.com/product12345"},{"externalid":"PROD23456","name":"Skateboard","price":3000,"quantity":1,"category":"Toys","sku":"SK8BOARD145","description":"lorem ipsum...","imageUrl":"https://example.com/product.jpg","productUrl":"https://store.example.com/product45678"}],"orderDiscounts":[{"name":"1OFF","type":"order","discountAmount":100}],"externalUpdatedDate":"2016-09-15T17:41:39-04:00","shippingMethod":"UPS Ground","totalPrice":9111,"shippingAmount":200,"taxAmount":500,"discountAmount":100,"currency":"USD","orderNumber":"12345-1"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"ecomOrderProducts\": [\n        {\n            \"orderid\": \"1\",\n            \"connectionid\": \"1\",\n            \"externalid\": \"PROD12345\",\n            \"sku\": \"POGO-12\",\n            \"name\": \"Pogo Stick\",\n            \"description\": \"lorem ipsum...\",\n            \"price\": \"4900\",\n            \"quantity\": \"1\",\n            \"category\": \"Toys\",\n            \"imageUrl\": \"https://example.com/product.jpg\",\n            \"productUrl\": \"https://store.example.com/product12345\",\n            \"createdDate\": \"2019-09-05T13:55:37-05:00\",\n            \"updatedDate\": \"2019-09-05T13:55:37-05:00\",\n            \"tstamp\": \"2019-09-05T13:55:37-05:00\",\n            \"links\": {\n                \"ecomOrder\": \"https://youraccounthere.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder\"\n            },\n            \"id\": \"3\",\n            \"ecomOrder\": \"1\"\n        },\n        {\n            \"orderid\": \"1\",\n            \"connectionid\": \"1\",\n            \"externalid\": \"PROD23456\",\n            \"sku\": \"SK8BOARD145\",\n            \"name\": \"Skateboard\",\n            \"description\": \"lorem ipsum...\",\n            \"price\": \"3000\",\n            \"quantity\": \"1\",\n            \"category\": \"Toys\",\n            \"imageUrl\": \"https://example.com/product.jpg\",\n            \"productUrl\": \"https://store.example.com/product45678\",\n            \"createdDate\": \"2019-09-05T13:55:37-05:00\",\n            \"updatedDate\": \"2019-09-05T13:55:37-05:00\",\n            \"tstamp\": \"2019-09-05T13:55:37-05:00\",\n            \"links\": {\n                \"ecomOrder\": \"https://youraccounthere.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder\"\n            },\n            \"id\": \"4\",\n            \"ecomOrder\": \"1\"\n        }\n    ],\n    \"ecomOrderDiscounts\": [\n        {\n            \"name\": \"1OFF\",\n            \"type\": \"order\",\n            \"orderid\": \"5355\",\n            \"discountAmount\": \"100\",\n            \"id\": \"1\",\n            \"createdDate\": \"2019-09-05T12:16:18-05:00\",\n            \"updatedDate\": \"2019-09-05T12:16:18-05:00\"\n        }\n    ],\n    \"ecomOrder\": {\n        \"customerid\": \"1\",\n        \"connectionid\": \"1\",\n        \"state\": \"1\",\n        \"source\": \"1\",\n        \"externalid\": \"3246315237\",\n        \"orderNumber\": \"\",\n        \"email\": \"alice@example.com\",\n        \"totalPrice\": 9111,\n        \"discountAmount\": 100,\n        \"shippingAmount\": 200,\n        \"taxAmount\": 500,\n        \"totalProducts\": 2,\n        \"currency\": \"USD\",\n        \"shippingMethod\": \"UPS Ground\",\n        \"orderUrl\": \"https://example.com/orders/3246315233\",\n        \"externalCreatedDate\": \"2016-09-13T16:41:39-05:00\",\n        \"externalUpdatedDate\": \"2016-09-15T16:41:39-05:00\",\n        \"createdDate\": \"2019-09-05T12:52:13-05:00\",\n        \"updatedDate\": \"2019-09-05T13:55:37-05:00\",\n        \"orderProducts\": [\n            \"3\",\n            \"4\"\n        ],\n        \"orderDiscounts\": [\n            \"1\"\n        ],\n        \"customer\": \"1\",\n        \"orderDate\": \"2016-09-13T16:41:39-05:00\",\n        \"tstamp\": \"2019-09-05T13:55:37-05:00\",\n        \"links\": {\n            \"connection\": \"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/connection\",\n            \"customer\": \"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/customer\",\n            \"orderProducts\": \"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/orderProducts\",\n            \"orderDiscounts\": \"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts\",\n            \"orderActivities\": \"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/orderActivities\"\n        },\n        \"id\": \"1\",\n        \"connection\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"ecomOrderProducts":{"type":"array","items":{"type":"object","properties":{"orderid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"PROD12345"},"sku":{"type":"string","example":"POGO-12"},"name":{"type":"string","example":"Pogo Stick"},"description":{"type":"string","example":"lorem ipsum..."},"price":{"type":"string","example":"4900"},"quantity":{"type":"string","example":"1"},"category":{"type":"string","example":"Toys"},"imageUrl":{"type":"string","example":"https://example.com/product.jpg"},"productUrl":{"type":"string","example":"https://store.example.com/product12345"},"createdDate":{"type":"string","example":"2019-09-05T13:55:37-05:00"},"updatedDate":{"type":"string","example":"2019-09-05T13:55:37-05:00"},"tstamp":{"type":"string","example":"2019-09-05T13:55:37-05:00"},"links":{"type":"object","properties":{"ecomOrder":{"type":"string","example":"https://youraccounthere.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder"}}},"id":{"type":"string","example":"3"},"ecomOrder":{"type":"string","example":"1"}}}},"ecomOrderDiscounts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"1OFF"},"type":{"type":"string","example":"order"},"orderid":{"type":"string","example":"5355"},"discountAmount":{"type":"string","example":"100"},"id":{"type":"string","example":"1"},"createdDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"},"updatedDate":{"type":"string","example":"2019-09-05T12:16:18-05:00"}}}},"ecomOrder":{"type":"object","properties":{"customerid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"state":{"type":"string","example":"1"},"source":{"type":"string","example":"1"},"externalid":{"type":"string","example":"3246315237"},"orderNumber":{"type":"string","example":""},"email":{"type":"string","example":"alice@example.com"},"totalPrice":{"type":"integer","example":9111,"default":0},"discountAmount":{"type":"integer","example":100,"default":0},"shippingAmount":{"type":"integer","example":200,"default":0},"taxAmount":{"type":"integer","example":500,"default":0},"totalProducts":{"type":"integer","example":2,"default":0},"currency":{"type":"string","example":"USD"},"shippingMethod":{"type":"string","example":"UPS Ground"},"orderUrl":{"type":"string","example":"https://example.com/orders/3246315233"},"externalCreatedDate":{"type":"string","example":"2016-09-13T16:41:39-05:00"},"externalUpdatedDate":{"type":"string","example":"2016-09-15T16:41:39-05:00"},"createdDate":{"type":"string","example":"2019-09-05T12:52:13-05:00"},"updatedDate":{"type":"string","example":"2019-09-05T13:55:37-05:00"},"orderProducts":{"type":"array","items":{"type":"string","example":"3"}},"orderDiscounts":{"type":"array","items":{"type":"string","example":"1"}},"customer":{"type":"string","example":"1"},"orderDate":{"type":"string","example":"2016-09-13T16:41:39-05:00"},"tstamp":{"type":"string","example":"2019-09-05T13:55:37-05:00"},"links":{"type":"object","properties":{"connection":{"type":"string","example":"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/connection"},"customer":{"type":"string","example":"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/customer"},"orderProducts":{"type":"string","example":"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/orderProducts"},"orderDiscounts":{"type":"string","example":"https://exampleaccount.api-us1.com/api/3/ecomOrders/1/orderDiscounts"},"orderActivities":{"type":"string","example":"https://youraccounthere.api-us1.com/api/3/ecomOrders/1/orderActivities"}}},"id":{"type":"string","example":"1"},"connection":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/ecomOrders/{id}":{"post":{"summary":"Create an order (path with an ID)","description":"Internal: kept so callers of the old router that post an order to /ecomOrders/{id} keep working. Runs the same handler as POST /ecomOrders: {id} is ignored and a new order is created from the body. Not a pure create: when the connection already has a checkout with this externalcheckoutid but no externalid, or an order with this externalid but no externalcheckoutid, that record is completed with the missing id instead and no new order is saved; when both exist as separate records and the checkout has no externalid, they are merged by deleting the one found by externalid. Any other repeat of externalid or externalcheckoutid on the connection is a 422. Refused with 403 when the account has no Deep Data.","operationId":"create-order-with-id","parameters":[{"name":"id","in":"path","description":"Ignored. Any value is accepted and none is looked up.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomOrder"],"properties":{"ecomOrder":{"description":"The order to create","required":["connectionid","customerid","totalPrice","currency","externalCreatedDate","orderProducts"],"properties":{"externalid":{"description":"ID of the order in the external store. Required unless externalcheckoutid is given.","type":"string","example":"3246315233"},"externalcheckoutid":{"description":"ID of the cart in the external store, for an abandoned-cart checkout","type":"string","example":"cart-998"},"source":{"description":"0 for a historical import, 1 for a real-time order. Only real-time orders trigger automations and reach the ecommerce dashboard.","type":"integer","example":1},"email":{"description":"Email address of the customer who placed the order. Required unless the account has phone-only contacts enabled, in which case email or a valid phone is required.","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer who placed the order","type":"string","example":"+15555550100"},"connectionid":{"description":"ID of the connection the order comes from; must exist","type":"integer","example":3},"customerid":{"description":"ID of the ecomCustomer who placed the order; must exist","type":"integer","example":12},"totalPrice":{"description":"Total price in cents, including tax and shipping","type":"integer","example":9111},"shippingAmount":{"description":"Shipping amount in cents","type":"integer","example":200},"taxAmount":{"description":"Tax amount in cents","type":"integer","example":500},"discountAmount":{"description":"Discount amount in cents","type":"integer","example":100},"currency":{"description":"Three-letter ISO currency code","type":"string","example":"USD"},"orderNumber":{"description":"Order number shown to the customer; may differ from externalid","type":"string","example":"myorder-123"},"orderUrl":{"description":"URL of the order in the external store","type":"string","example":"https://store.example.com/orders/3246315233"},"shippingMethod":{"description":"Shipping method of the order","type":"string","example":"UPS Ground"},"externalCreatedDate":{"description":"When the order was placed, ISO 8601. orderDate is accepted as an alias.","type":"string","example":"2026-10-13T17:41:39-04:00"},"externalUpdatedDate":{"description":"When the order was last updated in the store, ISO 8601","type":"string","example":"2026-10-14T17:41:39-04:00"},"abandonedDate":{"description":"When the cart was abandoned, ISO 8601","type":"string","example":"2026-10-13T18:41:39-04:00"},"state":{"description":"Order state, 0 to 9 (0 pending, 1 completed, 2 abandoned, 3 recovered, 4 waiting, 5 cancelled, 6 refunded, 7 failed, 8 returned, 9 pending payment). Only taken from an internal request, such as one signed by Deep Data; ignored otherwise.","type":"integer","example":1},"orderProducts":{"description":"The products of the order. Required.","type":"array","items":{"properties":{"externalid":{"description":"ID of the product in the external store","type":"string","example":"PROD12345"},"name":{"description":"Name of the product","type":"string","example":"Pogo Stick"},"price":{"description":"Price of the product in cents","type":"integer","example":4900},"quantity":{"description":"Quantity ordered; the quantities add up to the order's totalProducts","type":"integer","example":1},"category":{"description":"Category of the product","type":"string","example":"Toys"},"sku":{"description":"SKU of the product","type":"string","example":"POGO12"},"description":{"description":"Description of the product","type":"string","example":"A pogo stick"},"imageUrl":{"description":"URL of an image of the product","type":"string","example":"https://store.example.com/product.jpg"},"productUrl":{"description":"URL of the product in the store","type":"string","example":"https://store.example.com/product12345"}},"type":"object"}},"orderDiscounts":{"description":"Discounts on the order. Optional.","type":"array","items":{"properties":{"name":{"description":"Discount code or name","type":"string","example":"1OFF"},"type":{"description":"order for a discount on the order, shipping for free shipping","type":"string","example":"order"},"discountAmount":{"description":"Amount of the discount in cents","type":"integer","example":100}},"type":"object"}}},"type":"object"}},"type":"object"},"example":{"ecomOrder":{"externalid":"3246315233","source":1,"email":"alice@example.com","connectionid":3,"customerid":12,"totalPrice":4900,"currency":"USD","externalCreatedDate":"2026-10-13T17:41:39-04:00","orderProducts":[{"externalid":"PROD12345","name":"Pogo Stick","price":4900,"quantity":1}]}}}}},"responses":{"201":{"description":"The order was created. When an existing checkout or order was completed with the missing id instead, the body echoes the order as sent and has no id.","content":{"application/json":{"schema":{"properties":{"ecomOrder":{"description":"The order as stored. Numbers come back as strings.","properties":{"id":{"description":"ID of the order","type":"string","example":"5355"},"externalid":{"description":"ID of the order in the external store","type":"string","example":"3246315233"},"connectionid":{"description":"ID of the connection","type":"string","example":"3"},"customerid":{"description":"ID of the customer","type":"string","example":"12"},"email":{"description":"Email address of the customer","type":"string","example":"alice@example.com"},"totalPrice":{"description":"Total price in cents","type":"string","example":"9111"},"totalProducts":{"description":"Sum of the product quantities","type":"string","example":"2"},"currency":{"description":"Three-letter ISO currency code","type":"string","example":"USD"},"state":{"description":"Order state, 0 to 9","type":"string","example":"1"},"externalCreatedDate":{"description":"When the order was placed, ISO 8601","type":"string","example":"2026-10-13T16:41:39-05:00"},"links":{"description":"API paths of the related connection, customer, products, discounts and activities","type":"object","example":{"orderProducts":"/api/3/ecomOrders/5355/orderProducts"}}},"type":"object"},"ecomOrderProducts":{"description":"The order's products, side-loaded","type":"array","items":{"type":"object"}},"ecomOrderDiscounts":{"description":"The order's discounts, side-loaded when it has any","type":"array","items":{"type":"object"}}},"type":"object"}}}},"400":{"description":"The order duplicates one stored at the same time by another request (a unique-key conflict); it is not saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"Always \"Order already exists\"","type":"string","example":"Order already exists"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Order already exists"}]}}}},"403":{"description":"The account has no Deep Data.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Upgrade your account to enable Deep Data\"","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"The order failed validation: a required field is missing, connectionid or customerid names nothing, the email or phone is not valid for the account, state is not 0 to 9, or the externalid or externalcheckoutid is already used on the connection. The body is the validation errors.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed rule","type":"array","items":{"properties":{"title":{"description":"What failed","type":"string","example":"The ecomOrder orderProducts were not provided."},"detail":{"description":"More detail; often empty","type":"string","example":""},"code":{"description":"field_missing, related_missing, duplicate or field_invalid","type":"string","example":"field_missing"},"error":{"description":"Machine-readable error name; often empty","type":"string","example":""},"source":{"description":"Which field failed","properties":{"pointer":{"description":"JSON pointer to the field","type":"string","example":"/data/attributes/orderProducts"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"ecomOrders","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Update an order (PATCH)","description":"Internal: the PATCH form of PUT /ecomOrders/{ecomOrderId}, which it shares a handler with. Fields left out of ecomOrder keep their stored values, except orderProducts: the products sent replace the stored ones, so a request without orderProducts deletes every product of the order. Once an order has an externalid it cannot be cleared. The order must be one the current user can access. Refused with 403 when the account has no Deep Data.","operationId":"patch-order","parameters":[{"name":"id","in":"path","description":"ID of the order to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ecomOrder"],"properties":{"ecomOrder":{"description":"The fields to change","properties":{"externalid":{"description":"ID of the order in the external store. Required unless externalcheckoutid is given. Sending it empty on an order that has one keeps the stored value.","type":"string","example":"3246315233"},"externalcheckoutid":{"description":"ID of the cart in the external store, for an abandoned-cart checkout","type":"string","example":"cart-998"},"source":{"description":"0 for a historical import, 1 for a real-time order. Only real-time orders trigger automations and reach the ecommerce dashboard.","type":"integer","example":1},"email":{"description":"Email address of the customer who placed the order. Required unless the account has phone-only contacts enabled, in which case email or a valid phone is required.","type":"string","example":"alice@example.com"},"phone":{"description":"Phone number of the customer who placed the order","type":"string","example":"+15555550100"},"connectionid":{"description":"ID of the connection the order comes from; must exist","type":"integer","example":3},"customerid":{"description":"ID of the ecomCustomer who placed the order; must exist","type":"integer","example":12},"totalPrice":{"description":"Total price in cents, including tax and shipping","type":"integer","example":9111},"shippingAmount":{"description":"Shipping amount in cents","type":"integer","example":200},"taxAmount":{"description":"Tax amount in cents","type":"integer","example":500},"discountAmount":{"description":"Discount amount in cents","type":"integer","example":100},"currency":{"description":"Three-letter ISO currency code","type":"string","example":"USD"},"orderNumber":{"description":"Order number shown to the customer; may differ from externalid","type":"string","example":"myorder-123"},"orderUrl":{"description":"URL of the order in the external store","type":"string","example":"https://store.example.com/orders/3246315233"},"shippingMethod":{"description":"Shipping method of the order","type":"string","example":"UPS Ground"},"externalCreatedDate":{"description":"When the order was placed, ISO 8601. orderDate is accepted as an alias.","type":"string","example":"2026-10-13T17:41:39-04:00"},"externalUpdatedDate":{"description":"When the order was last updated in the store, ISO 8601","type":"string","example":"2026-10-14T17:41:39-04:00"},"abandonedDate":{"description":"When the cart was abandoned, ISO 8601","type":"string","example":"2026-10-13T18:41:39-04:00"},"state":{"description":"Order state, 0 to 9 (0 pending, 1 completed, 2 abandoned, 3 recovered, 4 waiting, 5 cancelled, 6 refunded, 7 failed, 8 returned, 9 pending payment). Only taken from an internal request, such as one signed by Deep Data; ignored otherwise.","type":"integer","example":1},"orderProducts":{"description":"Replaces the order's products: the products sent are created and every existing one is deleted, so leaving orderProducts out removes them all.","type":"array","items":{"properties":{"externalid":{"description":"ID of the product in the external store","type":"string","example":"PROD12345"},"name":{"description":"Name of the product","type":"string","example":"Pogo Stick"},"price":{"description":"Price of the product in cents","type":"integer","example":4900},"quantity":{"description":"Quantity ordered; the quantities add up to the order's totalProducts","type":"integer","example":1},"category":{"description":"Category of the product","type":"string","example":"Toys"},"sku":{"description":"SKU of the product","type":"string","example":"POGO12"},"description":{"description":"Description of the product","type":"string","example":"A pogo stick"},"imageUrl":{"description":"URL of an image of the product","type":"string","example":"https://store.example.com/product.jpg"},"productUrl":{"description":"URL of the product in the store","type":"string","example":"https://store.example.com/product12345"}},"type":"object"}},"orderDiscounts":{"description":"When sent, replaces the order's discounts; left out, they are kept.","type":"array","items":{"properties":{"name":{"description":"Discount code or name","type":"string","example":"1OFF"},"type":{"description":"order for a discount on the order, shipping for free shipping","type":"string","example":"order"},"discountAmount":{"description":"Amount of the discount in cents","type":"integer","example":100}},"type":"object"}}},"type":"object"}},"type":"object"},"example":{"ecomOrder":{"externalid":"3246315233","totalPrice":4900,"orderProducts":[{"externalid":"PROD12345","name":"Pogo Stick","price":4900,"quantity":1}]}}}}},"responses":{"200":{"description":"The order as stored after the update","content":{"application/json":{"schema":{"properties":{"ecomOrder":{"description":"The order as stored. Numbers come back as strings.","properties":{"id":{"description":"ID of the order","type":"string","example":"5355"},"externalid":{"description":"ID of the order in the external store","type":"string","example":"3246315233"},"connectionid":{"description":"ID of the connection","type":"string","example":"3"},"customerid":{"description":"ID of the customer","type":"string","example":"12"},"email":{"description":"Email address of the customer","type":"string","example":"alice@example.com"},"totalPrice":{"description":"Total price in cents","type":"string","example":"9111"},"totalProducts":{"description":"Sum of the product quantities","type":"string","example":"2"},"currency":{"description":"Three-letter ISO currency code","type":"string","example":"USD"},"state":{"description":"Order state, 0 to 9","type":"string","example":"1"},"externalCreatedDate":{"description":"When the order was placed, ISO 8601","type":"string","example":"2026-10-13T16:41:39-05:00"},"links":{"description":"API paths of the related connection, customer, products, discounts and activities","type":"object","example":{"orderProducts":"/api/3/ecomOrders/5355/orderProducts"}}},"type":"object"},"ecomOrderProducts":{"description":"The order's products, side-loaded","type":"array","items":{"type":"object"}},"ecomOrderDiscounts":{"description":"The order's discounts, side-loaded when it has any","type":"array","items":{"type":"object"}}},"type":"object"}}}},"400":{"description":"The order duplicates one stored at the same time by another request (a unique-key conflict); it is not saved.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"Always \"Order already exists\"","type":"string","example":"Order already exists"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Order already exists"}]}}}},"403":{"description":"The account has no Deep Data, or the current user may not access this order. The detail is \"Upgrade your account to enable Deep Data\" or \"Forbidden\".","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"\"Upgrade your account to enable Deep Data\" or \"Forbidden\"","type":"string","example":"Upgrade your account to enable Deep Data"}},"type":"object"}}},"type":"object"}}}},"404":{"description":"No order has this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the model and the ID","type":"string","example":"No Result found for EcomOrder with id 5355"}},"type":"object"},"example":{"message":"No Result found for EcomOrder with id 5355"}}}},"422":{"description":"The updated order failed validation, for example a required field was cleared, connectionid or customerid names nothing, or state is not 0 to 9. The body is the validation errors.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed rule","type":"array","items":{"properties":{"title":{"description":"What failed","type":"string","example":"The ecomOrder orderProducts were not provided."},"detail":{"description":"More detail; often empty","type":"string","example":""},"code":{"description":"field_missing, related_missing, duplicate or field_invalid","type":"string","example":"field_missing"},"error":{"description":"Machine-readable error name; often empty","type":"string","example":""},"source":{"description":"Which field failed","properties":{"pointer":{"description":"JSON pointer to the field","type":"string","example":"/data/attributes/orderProducts"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"ecomOrders","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ecomOrders/{id}/orderProducts":{"get":{"summary":"List EcomOrderProducts for a Specific EcomOrder","description":"","operationId":"list-products-for-order","x-canonical-resource":"ecomOrders","parameters":[{"name":"id","in":"path","description":"The ID of the order whose products you'd like returned.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"ecomOrderProducts\": [\n        {\n            \"orderid\": \"1\",\n            \"connectionid\": \"1\",\n            \"externalid\": \"1269385775\",\n            \"sku\": \"SKATE-8\",\n            \"name\": \"My Cool Skateboard\",\n            \"description\": \"This skateboard is so cool, it rides itself\",\n            \"price\": \"5000\",\n            \"quantity\": \"1\",\n            \"category\": \"skateboards\",\n            \"imageUrl\": \"https://example.com/images/skateboard.jpg\",\n            \"productUrl\": \"http://example.com/products/skate-8\",\n            \"createdDate\": \"2019-06-28T18:04:19-05:00\",\n            \"updatedDate\": \"2019-06-28T18:04:19-05:00\",\n            \"tstamp\": \"2019-06-28T18:04:19-05:00\",\n            \"links\": {\n                \"ecomOrder\": \"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder\"\n            },\n            \"id\": \"1\",\n            \"ecomOrder\": \"2\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"ecomOrderProducts":{"type":"array","items":{"type":"object","properties":{"orderid":{"type":"string","example":"1"},"connectionid":{"type":"string","example":"1"},"externalid":{"type":"string","example":"1269385775"},"sku":{"type":"string","example":"SKATE-8"},"name":{"type":"string","example":"My Cool Skateboard"},"description":{"type":"string","example":"This skateboard is so cool, it rides itself"},"price":{"type":"string","example":"5000"},"quantity":{"type":"string","example":"1"},"category":{"type":"string","example":"skateboards"},"imageUrl":{"type":"string","example":"https://example.com/images/skateboard.jpg"},"productUrl":{"type":"string","example":"http://example.com/products/skate-8"},"createdDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"updatedDate":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"tstamp":{"type":"string","example":"2019-06-28T18:04:19-05:00"},"links":{"type":"object","properties":{"ecomOrder":{"type":"string","example":"https://:account.api-us1.com/api/3/ecomOrderProducts/1/ecomOrder"}}},"id":{"type":"string","example":"1"},"ecomOrder":{"type":"string","example":"2"}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/emailAccounts":{"post":{"summary":"Create an email account","description":"Creates a Subscriptions by Email account owned by the calling user and links it to the lists in emailAccount.lists. For a pop3 account the server first logs in to the mailbox with host, port, user and pass, and refuses the request when it cannot; the password is stored encrypted and never returned. A pipe account keeps no mailbox details: host, user and pass are cleared, port is set to 110 and emailsPerBatch to 120. Needs the add-list permission (pg_list_add) besides the Subscriptions by Email permission. Internal: the API behind the Subscriptions by Email list setting.","operationId":"create-an-email-account","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsWriteRequest"},"example":{"emailAccount":{"type":"pop3","action":"sub","email":"join@example.com","host":"pop.example.com","port":110,"user":"join@example.com","pass":"secret","lists":[1,2]}}}}},"responses":{"201":{"description":"Created. The email account with its list associations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsSavedResponse"}}}},"400":{"description":"The body is not a JSON object."},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount) or the add-list permission (pg_list_add), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"422":{"description":"Refused before saving: emailAccount.lists is missing, not an array or names no list; email is not a valid address; a pop3 account has a blank host or user; or the POP3 login with host, port, user and pass failed (detail \"POP3 Connection could not be established.\"). A refused email, host or user answers {\"errors\": [{\"title\", \"detail\", \"code\", \"error\", \"source\": {\"pointer\": \"/data/attributes/<field>\"}}]}, one entry per field; the other cases {\"errors\": [{\"status\": \"422\", \"detail\": ...}]}."}},"x-canonical-resource":"email_account","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"List all email accounts","description":"The account's Subscriptions by Email accounts: POP3 mailboxes and piped addresses whose incoming mail subscribes or unsubscribes the sender to lists. filters[email], filters[host] and filters[user] match part of the value; filters[type], filters[action] and filters[listid] match exactly; unknown filter and order keys are ignored. meta.total is the number of matching email accounts. 20 per request by default and at most 100; page with offset. The password is never returned. Internal: the API behind the Subscriptions by Email list setting.","operationId":"list-all-email-accounts","x-canonical-resource":"email_account","parameters":[{"name":"filters[email]","in":"query","description":"Return only email accounts whose address (email) contains this text.","schema":{"type":"string"}},{"name":"filters[host]","in":"query","description":"Return only email accounts whose POP3 host contains this text.","schema":{"type":"string"}},{"name":"filters[user]","in":"query","description":"Return only email accounts whose POP3 user name contains this text.","schema":{"type":"string"}},{"name":"filters[type]","in":"query","description":"Return only email accounts of this type.","schema":{"type":"string","enum":["pop3","pipe"]}},{"name":"filters[action]","in":"query","description":"Return only email accounts with this action.","schema":{"type":"string","enum":["sub","unsub"]}},{"name":"filters[listid]","in":"query","description":"Return only email accounts linked to this list. A list the calling user cannot see returns no email accounts; 0 applies no list filter.","schema":{"type":"integer"}},{"name":"orders[email]","in":"query","description":"Sort by address. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[host]","in":"query","description":"Sort by POP3 host. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[user]","in":"query","description":"Sort by POP3 user name. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[type]","in":"query","description":"Sort by type. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[action]","in":"query","description":"Sort by action. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"orders[lists]","in":"query","description":"Sort by how many lists each email account is linked to, counting only the lists the calling user can see. Applied before any other orders[] sort. DESC, in any case, sorts descending; any other value sorts ascending.","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"ids","in":"query","description":"Return only these email accounts: comma-separated IDs, or repeated ids[] keys. The page size becomes the number of IDs given, and limit is ignored.","schema":{"type":"string"},"example":"1,2,3"},{"name":"include","in":"query","description":"emailAccountList side-loads each listed email account's list associations as emailAccountLists and adds their IDs to each email account as emailAccountList. A name that is not a relationship of the email account is ignored.","schema":{"type":"string","enum":["emailAccountList"]}},{"name":"limit","in":"query","description":"Number of email accounts to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of email accounts to skip before returning results. Use with limit to page.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The matching email accounts and their total.","content":{"application/json":{"schema":{"type":"object","required":["emailAccounts","meta"],"properties":{"emailAccounts":{"type":"array","description":"One page of email accounts. Without include, emailAccountList is absent from each.","items":{"$ref":"#/components/schemas/EmailAccountsEmailAccount"}},"emailAccountLists":{"type":"array","description":"The list associations of the listed email accounts; only with include=emailAccountList.","items":{"$ref":"#/components/schemas/EmailAccountsListAssociation"}},"meta":{"type":"object","description":"Paging information","required":["total"],"properties":{"total":{"type":"integer","description":"Number of email accounts matching the filters, across all pages","example":2}}}}}}}},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."}},"x-internal":true}},"/emailAccounts/bulkDelete":{"delete":{"summary":"Delete several email accounts","description":"Deletes each email account named in ids the way DELETE /emailAccounts/{id} does: its links to the lists the calling user can see go, and the account goes once no links remain. IDs with no email account are skipped. Needs the delete-list permission (pg_list_delete) besides the Subscriptions by Email permission. Internal: the API behind the Subscriptions by Email list setting.","operationId":"bulk-delete-email-accounts","parameters":[{"name":"ids","in":"query","description":"IDs of the email accounts to delete, comma-separated; repeated ids[] keys are read too. Each entry is read as an integer; entries that read as 0 are dropped, and a repeated ID is deleted once.","required":true,"schema":{"type":"string"},"example":"1,2,3"}],"responses":{"200":{"description":"Done. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount) or the delete-list permission (pg_list_delete), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"422":{"description":"ids is missing or names no ID. The body is {\"errors\": [{\"status\": \"422\", \"detail\": \"Missing ids\"}]}."}},"x-canonical-resource":"email_account","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/emailAccounts/parserAddresses":{"get":{"summary":"Retrieve the Subscriptions by Email parser addresses","description":"The account's two mail parser addresses, subscribe-<hash>@<domain> and unsubscribe-<hash>@<domain>, built from the account hash, which the API exposes nowhere else. The Subscriptions by Email setting offers them as the address to forward mail to for a pipe email account. The domain is subscription-serv.com, or staging.activecampaignsd2.com on a staging account. Internal: the API behind the Subscriptions by Email list setting.","operationId":"retrieve-email-account-parser-addresses","responses":{"200":{"description":"The two parser addresses","content":{"application/json":{"schema":{"required":["parserEmailAddresses"],"properties":{"parserEmailAddresses":{"description":"The subscribe- address, then the unsubscribe- address","type":"array","items":{"type":"string"}}},"type":"object"},"example":{"parserEmailAddresses":["subscribe-0123456789abcdef0123456789abcdef@subscription-serv.com","unsubscribe-0123456789abcdef0123456789abcdef@subscription-serv.com"]}}}},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."}},"x-canonical-resource":"email_account","x-internal":true}},"/emailAccounts/{id}":{"put":{"summary":"Update an email account","description":"Changes an email account and replaces its list associations with emailAccount.lists, which must be sent on every update. Fields left out keep their values, except that for a pop3 account the server logs in to the mailbox again with the pass in the request and stores that password, so pass must be sent again. Associations with lists the calling user cannot see are left in place. Needs the edit-list permission (pg_list_edit) besides the Subscriptions by Email permission. PATCH /emailAccounts/{id} does the same. Internal: the API behind the Subscriptions by Email list setting.","operationId":"update-an-email-account","parameters":[{"name":"id","in":"path","description":"ID of the email account","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsWriteRequest"},"example":{"emailAccount":{"type":"pop3","action":"sub","email":"join@example.com","host":"pop.example.com","port":110,"user":"join@example.com","pass":"secret","lists":[1,2]}}}}},"responses":{"200":{"description":"The email account as saved, with its list associations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsSavedResponse"}}}},"400":{"description":"The body is not a JSON object."},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount) or the edit-list permission (pg_list_edit), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"404":{"description":"No email account with this ID. The body is {\"message\": \"No Result found for ActiveCampaign\\Hosted\\EmailAccount with id <id>\"}."},"422":{"description":"Refused before saving: emailAccount.lists is missing, not an array or names no list; email is not a valid address; a pop3 account has a blank host or user; or the POP3 login with host, port, user and pass failed (detail \"POP3 Connection could not be established.\"). A refused email, host or user answers {\"errors\": [{\"title\", \"detail\", \"code\", \"error\", \"source\": {\"pointer\": \"/data/attributes/<field>\"}}]}, one entry per field; the other cases {\"errors\": [{\"status\": \"422\", \"detail\": ...}]}."}},"x-canonical-resource":"email_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete an email account","description":"Removes the email account's links to the lists the calling user can see, then deletes the account once no links remain. While the account is still linked to lists the calling user cannot see, those links and the account stay, and the call still answers 200. Needs the delete-list permission (pg_list_delete) besides the Subscriptions by Email permission. Internal: the API behind the Subscriptions by Email list setting.","operationId":"delete-an-email-account","parameters":[{"name":"id","in":"path","description":"ID of the email account","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Done. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount) or the delete-list permission (pg_list_delete), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"404":{"description":"No email account with this ID. The body is {\"message\": \"No Result found for ActiveCampaign\\Hosted\\EmailAccount with id <id>\"}."}},"x-canonical-resource":"email_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Update an email account (PATCH)","description":"Changes an email account and replaces its list associations with emailAccount.lists, which must be sent on every update. Fields left out keep their values, except that for a pop3 account the server logs in to the mailbox again with the pass in the request and stores that password, so pass must be sent again. Associations with lists the calling user cannot see are left in place. Needs the edit-list permission (pg_list_edit) besides the Subscriptions by Email permission. The same as PUT /emailAccounts/{id}. Internal: the API behind the Subscriptions by Email list setting.","operationId":"patch-an-email-account","parameters":[{"name":"id","in":"path","description":"ID of the email account","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsWriteRequest"},"example":{"emailAccount":{"type":"pop3","action":"sub","email":"join@example.com","host":"pop.example.com","port":110,"user":"join@example.com","pass":"secret","lists":[1,2]}}}}},"responses":{"200":{"description":"The email account as saved, with its list associations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAccountsSavedResponse"}}}},"400":{"description":"The body is not a JSON object."},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount) or the edit-list permission (pg_list_edit), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"404":{"description":"No email account with this ID. The body is {\"message\": \"No Result found for ActiveCampaign\\Hosted\\EmailAccount with id <id>\"}."},"422":{"description":"Refused before saving: emailAccount.lists is missing, not an array or names no list; email is not a valid address; a pop3 account has a blank host or user; or the POP3 login with host, port, user and pass failed (detail \"POP3 Connection could not be established.\"). A refused email, host or user answers {\"errors\": [{\"title\", \"detail\", \"code\", \"error\", \"source\": {\"pointer\": \"/data/attributes/<field>\"}}]}, one entry per field; the other cases {\"errors\": [{\"status\": \"422\", \"detail\": ...}]}."}},"x-canonical-resource":"email_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"Retrieve an email account","description":"One Subscriptions by Email account. The password and the detected POP3 login method are never returned, and the list associations are not side-loaded: read them from the emailAccountList link. Internal: the API behind the Subscriptions by Email list setting.","operationId":"retrieve-an-email-account","x-canonical-resource":"email_account","parameters":[{"name":"id","in":"path","description":"ID of the email account","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The email account","content":{"application/json":{"schema":{"type":"object","required":["emailAccount"],"properties":{"emailAccount":{"description":"The email account, without emailAccountList","$ref":"#/components/schemas/EmailAccountsEmailAccount"}}}}}},"403":{"description":"The calling user lacks the Subscriptions by Email permission (pg_list_emailaccount), or is neither the primary admin nor in the Admin group. The body is {\"errors\": [{\"status\": ..., \"detail\": \"Forbidden\"}]}."},"404":{"description":"No email account with this ID. The body is {\"message\": \"No Result found for ActiveCampaign\\Hosted\\EmailAccount with id <id>\"}."}},"x-internal":true}},"/emailActivities":{"get":{"summary":"List all email activities","description":"Returns the email history the platform keeps for a contact or a deal: one-to-one emails sent from the platform, emails from a connected mailbox (synced in, or sent through it), and campaign emails sent to the contact. reltype says which kind each entry is. Send filters[subscriberid] or filters[dealId]; without either, the read covers every email on the account. With filters[subscriberid], the request first adds any of the contact's emails sent since the last read, then returns the entries. With filters[dealId], it does the same for the deal and its contacts, and returns the emails of the deal's contacts that are tied to this deal or to no deal; users without deal access then see only the emails tied to no deal. Each email appears once. Emails from a connected mailbox that are marked private are returned only to the user they belong to. Subjects have personalization tags filled in, and message bodies have the mailbox service's open-tracking pixel removed, so showing them does not count as an open. Results are paged: limit defaults to 20 and is capped at 100, page with offset, and meta.total is the number of matching emails. This endpoint is read-only.","operationId":"list-all-email-activities","x-canonical-resource":"emailActivities","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Return only the emails of this contact. An unknown contact id returns 404.","schema":{"type":"integer","format":"int32"}},{"name":"filters[dealId]","in":"query","description":"Return only the emails of this deal's contacts that are tied to this deal or to no deal. An unknown deal id returns 404.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The matching emails. When nothing matches, emailActivities is an empty list.","content":{"application/json":{"schema":{"type":"object","properties":{"emailActivities":{"type":"array","description":"The emails, one entry per email.","items":{"type":"object","properties":{"id":{"type":"string","description":"The email activity entry id.","example":"12"},"subscriberid":{"type":"string","description":"The id of the contact the email belongs to.","example":"1"},"contact":{"type":["string","null"],"description":"The same contact id as subscriberid. Null when the entry has no contact.","example":"1"},"userid":{"type":"string","description":"The id of the account user the email belongs to: the user who sent a one-to-one email, the user whose connected mailbox a mailbox email belongs to, or the owner of the campaign message for a campaign send. 0 when there is none.","example":"1"},"user":{"type":["string","null"],"description":"The same user id as userid. Null when userid is 0.","example":"1"},"d_id":{"type":"string","description":"The id of the deal the email is tied to, or 0 when it is not tied to a deal.","example":"0"},"deal":{"type":["string","null"],"description":"The same deal id as d_id. Null when d_id is 0.","example":null},"account":{"type":["string","null"],"description":"The id of the account (company) the email is tied to. Null when it is not tied to one.","example":null},"reltype":{"type":"string","description":"Which kind of email this is: SubscriberEmail for a one-to-one email sent from the platform, DealEmail for an email from a connected mailbox (synced in, or sent through it), Log for a campaign email sent to the contact.","enum":["SubscriberEmail","DealEmail","Log"],"example":"SubscriberEmail"},"relid":{"type":"string","description":"The id of the underlying email record of that kind.","example":"34"},"reference":{"type":"object","description":"The underlying email record as a type and id pair.","properties":{"type":{"type":"string","description":"The API type name of the underlying record: contact-email, deal-email or log.","example":"contact-email"},"id":{"type":"string","description":"The same id as relid.","example":"34"}}},"from_name":{"type":"string","description":"The sender name. Empty for mailbox emails.","example":"Sam Example"},"fromAddress":{"type":"string","description":"The sender email address.","example":"sam@example.com"},"toAddress":{"type":"string","description":"The recipient address or addresses.","example":"pat@example.com"},"ccAddress":{"type":"string","description":"The copied addresses, or empty.","example":""},"subject":{"type":["string","null"],"description":"The subject line.","example":"Following up"},"message":{"type":["string","null"],"description":"The plain-text body.","example":"Hi Pat, just following up."},"messageHtml":{"type":["string","null"],"description":"The HTML body.","example":"<p>Hi Pat, just following up.</p>"},"tstamp":{"type":["string","null"],"description":"When the email was sent or received.","example":"2026-10-12T20:16:41-05:00"},"sentiment":{"type":["string","null"],"description":"The tone detected in a mailbox email: 0 not worked out yet, 1 negative, 2 neutral, 3 positive. Null for other kinds of email, and when sentiment is turned off for the mailbox connection. Present only on accounts with sentiment analysis.","example":null},"files":{"type":["string","null"],"description":"For a mailbox email, its attachments as a JSON-encoded list. Null for other kinds of email.","example":null},"connectionid":{"type":["string","null"],"description":"For a mailbox email, the id of the mailbox connection it came from. Null otherwise.","example":null},"messageid":{"type":["string","null"],"description":"For a mailbox email, the mailbox service's id for the message. Null otherwise.","example":null},"service_provider":{"type":["string","null"],"description":"For a mailbox email, the type of the mailbox connection it came from. Null otherwise.","example":null},"series_id":{"type":["string","null"],"description":"When an automation sent the email, the id of that automation. Null otherwise.","example":null},"subscriber_series_id":{"type":["string","null"],"description":"When an automation sent the email, the id of the contact's run through that automation. Null otherwise.","example":null},"automation_name":{"type":["string","null"],"description":"When an automation sent the email, its name. Null otherwise.","example":null},"links":{"type":"object","description":"URLs of the related reads for this entry: contact, deal, user, reference and account, each at /emailActivities/{id}/<name>."}}}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching emails.","example":1}}}}}}}},"404":{"description":"The contact named by filters[subscriberid], or the deal named by filters[dealId], does not exist.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Subscriber with id 999999\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the contact or deal id that was not found."}}}}}}},"deprecated":false}},"/ember/globalData":{"get":{"summary":"Retrieve the Ember app start-up data","description":"One document with everything the Ember app reads at start-up: account settings and limits, the signed-in user and their groups, branding, connections, session flags, regions and the cell name. Expensive: it runs many queries and can take seconds and return megabytes on large accounts, so prefer the narrower `/globalData/*` reads. The response is marked private for caches. Internal: backs the Ember app.","operationId":"retrieve-ember-global-data","responses":{"200":{"description":"The start-up data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmberGlobalData"}}}},"500":{"description":"Gathering the data failed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always `An exception occurred.`","type":"string","example":"An exception occurred."}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/enableReadTracking/message":{"post":{"summary":"Create read-tracking messages","description":"Creates one message record for each entry of `message`, owned by the user making the request, with the user's name and email address as the sender and the `mime` format; the record's name and subject both take the entry's subject. The response carries only the ID of the last message created. Internal: one step of the read tracking the ActiveCampaign Chrome extension adds to emails sent from Gmail. Responses carry CORS headers that allow https://mail.google.com (any other origin gets `*`). Only POST is routed; any other method is answered 405 with `Allow: POST`.","operationId":"create-read-tracking-messages","x-canonical-resource":"message","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"array","minItems":1,"description":"The messages to create.","items":{"type":"object","required":["subject","html"],"properties":{"subject":{"type":"string","description":"Subject line; also stored as the message name.","example":"Following up"},"html":{"type":"string","description":"HTML body of the email.","example":"<p>Hi Sam,</p>"}}}}}},"example":{"message":[{"subject":"Following up","html":"<p>Hi Sam,</p>"}]}}}},"responses":{"201":{"description":"The messages were created.","content":{"application/json":{"schema":{"type":"object","properties":{"message_id":{"type":"string","description":"ID of the last message created.","example":"42"}}}}}},"422":{"description":"`message` is missing or empty, or a message could not be created; in the second case the body is `{\"error\": \"Error occurred while creating message, try again.\"}`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/EnableReadTrackingBulkFailure"},{"$ref":"#/components/schemas/EnableReadTrackingWriteFailure"}]}}}}},"deprecated":false,"x-internal":true}},"/enableReadTracking/tracker":{"post":{"summary":"Enable read tracking for a message","description":"In one transaction: updates each message in `messages` (its `text` is converted from HTML to plain text first), logs each entry of `contactEmails` as an email of a message to a contact, stamped with the requesting user, the request's IPv4 address and the current time, and creates each entry of `links` as a tracked link. All three arrays are required. Each of `contactEmails` and `links` is written through one record: the first entry creates it and any later entry overwrites that same record, so send one entry in each. Any failure rolls back the whole request. Internal: one step of the read tracking the ActiveCampaign Chrome extension adds to emails sent from Gmail. Responses carry CORS headers that allow https://mail.google.com (any other origin gets `*`). Only POST is routed; any other method is answered 405 with `Allow: POST`.","operationId":"enable-message-read-tracking","x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["messages","contactEmails","links"],"properties":{"messages":{"type":"array","minItems":1,"description":"Messages to update. Only the fields listed are written.","items":{"type":"object","required":["id","text"],"properties":{"id":{"type":"integer","description":"ID of an existing message.","example":42},"text":{"type":"string","description":"Body of the email. It is converted from HTML to plain text and stored as the plain-text body.","example":"<p>Hi Sam,</p>"},"subject":{"type":"string","description":"Subject line."},"name":{"type":"string","description":"Internal name of the message."},"html":{"type":"string","description":"HTML body."},"preheader_text":{"type":"string","description":"Preheader text."},"fromname":{"type":"string","description":"Sender name."},"fromemail":{"type":"string","description":"Sender address."},"reply2":{"type":"string","description":"Reply-to address."},"format":{"type":"string","enum":["html","text","mime"],"description":"Body format."},"priority":{"type":"integer","description":"Email priority header value."},"charset":{"type":"string","description":"Character set."},"encoding":{"type":"string","description":"Content transfer encoding."},"htmlfetch":{"type":"string","description":"When to fetch the HTML body from a URL."},"textfetch":{"type":"string","description":"When to fetch the plain-text body from a URL."}}}},"contactEmails":{"type":"array","minItems":1,"description":"The email to log, as a contact email record. `userid`, `ip` and `sdate` are set by the server and override anything sent.","items":{"type":"object","properties":{"messageid":{"type":"integer","description":"ID of the message that was emailed; `message` is accepted as an alias.","example":42},"subscriberid":{"type":"integer","description":"ID of the contact the message was emailed to; `contact` is accepted as an alias.","example":8},"d_id":{"type":"integer","description":"ID of the deal the email belongs to; `deal` is accepted as an alias."},"customer_acct_id":{"type":"integer","description":"ID of the account the email belongs to; `account` is accepted as an alias."},"seriesid":{"type":"integer","description":"ID of the automation that sent the email, if any."},"messageheader":{"type":"string","description":"Headers of the email as sent."},"source":{"type":"string","description":"Where the email was sent from."}}}},"links":{"type":"array","minItems":1,"description":"The tracked link to create.","items":{"type":"object","properties":{"messageid":{"type":"integer","description":"ID of the message the link belongs to; `message` is accepted as an alias.","example":42},"campaignid":{"type":"integer","description":"ID of the campaign the link belongs to; `campaign` is accepted as an alias. 0 for an email that is not part of a campaign.","example":0},"link":{"type":"string","description":"The tracked URL, or `open` for the open-tracking link.","example":"open"},"name":{"type":"string","description":"Display name of the link.","example":"Read tracker"},"ref":{"type":"string","description":"Social network the link shares to, if any; empty for an ordinary link."},"tracked":{"type":"integer","description":"1 when clicks on the link are tracked."}}}}}},"example":{"messages":[{"id":42,"text":"<p>Hi Sam,</p>"}],"contactEmails":[{"messageid":42,"subscriberid":8}],"links":[{"messageid":42,"campaignid":0,"link":"open","name":"Read tracker"}]}}}},"responses":{"201":{"description":"Everything was written. Each list holds one item per entry sent, so a repeated `contactEmails` or `links` entry appears more than once with the same record.","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","description":"The updated messages.","items":{"$ref":"#/components/schemas/EnableReadTrackingMessage"}},"contactEmails":{"type":"array","description":"The contact email record.","items":{"$ref":"#/components/schemas/EnableReadTrackingContactEmail"}},"links":{"type":"array","description":"The tracked link record.","items":{"$ref":"#/components/schemas/EnableReadTrackingLink"}}}}}}},"422":{"description":"One of `messages`, `contactEmails` or `links` is missing or empty, or a write failed: a message ID that does not exist, or a record that could not be saved. A write failure is answered `{\"error\": \"Error occurred while creating message, try again.\"}` and nothing is kept.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/EnableReadTrackingBulkFailure"},{"$ref":"#/components/schemas/EnableReadTrackingWriteFailure"}]}}}},"500":{"description":"An entry of `messages` has no `text`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableReadTrackingServerError"}}}}},"deprecated":false,"x-internal":true}},"/enableReadTracking/trackingLink":{"post":{"summary":"Generate an open-tracking link","description":"Returns the open-tracking pixel URL for one contact and one message, the URL the extension embeds in the email so that opening it is recorded. The contact, message and link must exist; the link is only checked and echoed back. Nothing is written. Internal: one step of the read tracking the ActiveCampaign Chrome extension adds to emails sent from Gmail. Responses carry CORS headers that allow https://mail.google.com (any other origin gets `*`). Only POST is routed; any other method is answered 405 with `Allow: POST`.","operationId":"generate-open-tracking-link","x-canonical-resource":"message","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contactid","messageid","linkid"],"properties":{"contactid":{"type":"integer","description":"ID of the contact the email is sent to.","example":8},"messageid":{"type":"integer","description":"ID of the message being sent.","example":42},"linkid":{"type":"integer","description":"ID of the message's open-tracking link.","example":31}}},"example":{"contactid":8,"messageid":42,"linkid":31}}}},"responses":{"200":{"description":"The tracking link.","content":{"application/json":{"schema":{"type":"object","properties":{"linkId":{"type":["string","integer"],"description":"ID of the link, as sent.","example":"31"},"messageId":{"type":["string","integer"],"description":"ID of the message, as sent.","example":"42"},"trackingLink":{"type":"string","description":"Open-tracking pixel URL personalised for the contact and message."}}}}}},"400":{"description":"The body is empty or lacks `contactid`, `messageid` or `linkid`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the failure.","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 400.","example":400},"title":{"type":"string","description":"Name of the HTTP status.","example":"Bad Request"},"detail":{"type":"string","description":"Which field is missing.","example":"Tracking link generation failed. Missing required parameter contactid"}}}}}}}}},"404":{"description":"No contact, message or link with the ID sent.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which record was not found.","example":"No Result found for Subscriber with id 8"}}}}}}},"deprecated":false,"x-internal":true}},"/enableReadTracking/trackingReferer":{"post":{"summary":"Update read-tracking referrers","description":"In one transaction, for each entry of `linkData`: finds the first link data (open or click) record of the message `messageid`, converts `referer` from HTML to plain text, and writes the entry onto that record, `linkid` included. Any failure rolls back the whole request. Internal: one step of the read tracking the ActiveCampaign Chrome extension adds to emails sent from Gmail. Responses carry CORS headers that allow https://mail.google.com (any other origin gets `*`). Only POST is routed; any other method is answered 405 with `Allow: POST`.","operationId":"update-read-tracking-referrers","x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["linkData"],"properties":{"linkData":{"type":"array","minItems":1,"description":"The referrers to record, one entry per message. Any other column of the link data record sent in an entry is written too.","items":{"type":"object","required":["messageid","linkid","referer"],"properties":{"messageid":{"type":"integer","description":"ID of the message whose link data record is updated. The message must already have one.","example":42},"linkid":{"type":"integer","description":"ID of the link to store on the record.","example":31},"referer":{"type":"string","description":"Referrer to store. It is converted from HTML to plain text first.","example":"https://mail.google.com/"}}}}}},"example":{"linkData":[{"messageid":42,"linkid":31,"referer":"https://mail.google.com/"}]}}}},"responses":{"201":{"description":"The records were updated.","content":{"application/json":{"schema":{"type":"object","properties":{"linkData":{"type":"array","description":"The updated records, one per entry sent.","items":{"$ref":"#/components/schemas/EnableReadTrackingLinkData"}}}}}}},"422":{"description":"`linkData` is missing or empty, or a record could not be saved. A save failure is answered `{\"error\": \"Error occurred while updating the link, try again.\"}` and nothing is kept.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/EnableReadTrackingBulkFailure"},{"$ref":"#/components/schemas/EnableReadTrackingWriteFailure"}]}}}},"500":{"description":"A `messageid` has no link data record, or an entry has no `referer`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableReadTrackingServerError"}}}}},"deprecated":false,"x-internal":true}},"/eventTracking":{"get":{"summary":"Retrieve Event Tracking Status","description":"Get event tracking status (enabled or disabled)","operationId":"retrieve-event-tracking-status","x-canonical-resource":"eventTracking","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"eventTracking\": {\n    \"enabled\": true\n  }\n}"}}}}}},"deprecated":false},"put":{"summary":"Enable/disable","description":"Enable or disable event tracking","operationId":"enable-disable-event-tracking","x-canonical-resource":"eventTracking","x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"eventTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether event tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"eventTracking":{"enabled":true}}},"Disable":{"value":{"eventTracking":{"enabled":false}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"eventTracking\": {\n    \"enabled\": true\n  }\n}"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/eventTracking/{id}":{"put":{"summary":"Update event tracking by id","description":"Enables or disables event tracking, exactly like PUT /eventTracking: the id in the path is ignored. The body must carry eventTracking.enabled as a boolean. PATCH on this path does the same. Internal: an alias of PUT /eventTracking that is not part of the public API.","operationId":"update-event-tracking-by-id","x-canonical-resource":"eventTracking","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Ignored. The controller never reads it, so any value gives the same result as the same request without an id.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"eventTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether event tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"eventTracking":{"enabled":true}}},"Disable":{"value":{"eventTracking":{"enabled":false}}}}}}},"responses":{"200":{"description":"Event tracking was enabled or disabled. The body repeats the setting as eventTracking.enabled.","content":{"application/json":{"example":{"eventTracking":{"enabled":true}}}}},"403":{"description":"Forbidden. The account's plan does not include custom events. This check runs before anything else."},"422":{"description":"eventTracking.enabled is missing or is not a boolean. Nothing is changed."}}},"patch":{"summary":"Update event tracking by id (PATCH)","description":"Enables or disables event tracking, exactly like PUT /eventTracking: the id in the path is ignored. The body must carry eventTracking.enabled as a boolean. PUT on this path does the same. Internal: an alias of PUT /eventTracking that is not part of the public API.","operationId":"patch-event-tracking-by-id","x-canonical-resource":"eventTracking","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Ignored. The controller never reads it, so any value gives the same result as the same request without an id.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"eventTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether event tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"eventTracking":{"enabled":true}}},"Disable":{"value":{"eventTracking":{"enabled":false}}}}}}},"responses":{"200":{"description":"Event tracking was enabled or disabled. The body repeats the setting as eventTracking.enabled.","content":{"application/json":{"example":{"eventTracking":{"enabled":true}}}}},"403":{"description":"Forbidden. The account's plan does not include custom events. This check runs before anything else."},"422":{"description":"eventTracking.enabled is missing or is not a boolean. Nothing is changed."}}}},"/eventTrackingEvents":{"post":{"summary":"Create a new event (name only)","description":"Create a new event tracking event (name only)","operationId":"create-a-new-event-name-only","x-canonical-resource":"eventTrackingEvents","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"eventTrackingEvent":{"properties":{"name":{"type":"string","description":"The name of the event"}},"required":["name"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"JSON":{"value":{"eventTrackingEvent":{"name":"my new fab event"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"eventTrackingEvent\": {\n\t\t\"name\": \"my new fab event\"\n\t}\n}"}},"schema":{"type":"object","properties":{"eventTrackingEvent":{"type":"object","properties":{"name":{"type":"string","example":"my new fab event"}}}}}}}}},"deprecated":false},"get":{"summary":"List all events (names only)","description":"List the names of tracked events","operationId":"list-all-event-types","x-canonical-resource":"eventTrackingEvents","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"eventTrackingEvents\": [\n    {\n      \"name\": \"__pagevisit\"\n    },\n    {\n      \"name\": \"__redir\"\n    }\n  ],\n  \"meta\": {\n    \"total\": 2\n  }\n}"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/eventTrackingEvents/{eventName}":{"delete":{"summary":"Delete event (name only)","description":"Remove an existing event tracking event (name only)","operationId":"remove-event-name-only","x-canonical-resource":"eventTrackingEvents","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"eventName","in":"path","description":"Name of event to delete. Spaces in names are allowed, but must be encoded (for example, \"my%20event\").","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/exclusions":{"get":{"summary":"List exclusions","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Lists the rules, 20 per page by default and at most 100 per page. By default only rules for the email channel, or for both channels, are returned. Rules come in no guaranteed order.","operationId":"list-all-exclusions","x-canonical-resource":"lists","x-internal":true,"parameters":[{"name":"channel","in":"query","description":"email (the default) or sms returns the rules for that channel plus the rules for both channels. all returns every rule. Any other value returns only the rules for both channels.","schema":{"type":"string"}},{"name":"email","in":"query","description":"Only rules that match this address: an exact rule equal to it, a begin rule it starts with, or an end rule it ends with.","schema":{"type":"string"}},{"name":"list","in":"query","description":"Only rules linked to this list ID, plus rules for all lists. A rule linked to this list and to all lists comes back twice, and is counted twice in meta.total.","schema":{"type":"integer"}},{"name":"hidden","in":"query","description":"1 for only rules added because a contact reported a campaign as spam, 0 for only the others.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Only the rules with these comma-separated IDs.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of rules per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of rules to skip. Default 0.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The rules on this page. exclusions is an empty array when none match.","content":{"application/json":{"schema":{"type":"object","properties":{"exclusions":{"type":"array","description":"The rules.","items":{"$ref":"#/components/schemas/Exclusion"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching rules, across all pages.","example":1}}}}},"examples":{"Result":{"value":{"exclusions":[{"email":"sam@example.com","wildcard":"0","hidden":"0","matchtype":"exact","channel":"email","created_timestamp":"2026-10-01 09:30:00","updated_timestamp":"2026-10-01 09:30:00","links":{"exclusionLists":"https://example.api-us1.com/api/3/exclusions/7/exclusionLists"},"id":"7"}],"meta":{"total":1}}}}}}}}},"post":{"summary":"Create an exclusion","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Creates a rule and links it to lists. The body fields are top-level, not inside an exclusion object. It fails when any rule already has this email, whatever that rule's match type or channel. Case does not matter. The response returns the new ID and the email as sent. The rule is not read back.","operationId":"create-an-exclusion","x-canonical-resource":"lists","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExclusionCreate"},"examples":{"Request Example":{"value":{"email":"sam@example.com","matchtype":"exact","channel":"email","target":"several","lists":[3,5]}}}}}},"responses":{"200":{"$ref":"#/components/responses/ExclusionWriteResult"},"400":{"$ref":"#/components/responses/ExclusionBodyNotObject"}}}},"/exclusions/{id}":{"get":{"summary":"Retrieve an exclusion","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Returns one rule by its ID, with the IDs of its lists. The rule is the top-level object, not inside an exclusion key.","operationId":"retrieve-an-exclusion","x-canonical-resource":"lists","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ExclusionId"}],"responses":{"200":{"description":"The rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExclusionDetail"},"examples":{"Result":{"value":{"id":"7","email":"sam@example.com","matchtype":"exact","hidden":"0","channel":"email","lists":"3,5","matchall":false,"wildcard":"0"}}}}}},"404":{"$ref":"#/components/responses/ExclusionNotFound"}}},"put":{"summary":"Update an exclusion","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Changes a rule's channel and replaces its lists. The address or pattern and the match type do not change. PATCH /exclusions/{id} does the same thing. The body fields are top-level, not inside an exclusion object. Links to lists that are not sent are removed, and links to new lists are added. An unknown ID also returns 200, with status error and code 0.","operationId":"update-an-exclusion-rule","x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ExclusionId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExclusionUpdate"},"examples":{"Request Example":{"value":{"channel":"all","target":"several","lists":[3]}}}}}},"responses":{"200":{"$ref":"#/components/responses/ExclusionWriteResult"},"400":{"$ref":"#/components/responses/ExclusionBodyNotObject"}}},"delete":{"summary":"Delete an exclusion","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Deletes a rule, including one added because a contact reported a campaign as spam. The rule no longer stops sends.","operationId":"delete-an-exclusion","x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/ExclusionId"}],"responses":{"200":{"description":"The rule was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object","maxProperties":0},"examples":{"Result":{"value":{}}}}}},"403":{"description":"The delete failed on a database error such as a deadlock. The body is a plain sentence, not JSON, such as \"Failed to delete exclusion\", in the user's language. The Content-Type header still says application/json."},"404":{"$ref":"#/components/responses/ExclusionNotFound"}}}},"/exclusions/{id}/exclusionLists":{"get":{"summary":"List an exclusion's list links","description":"An exclusion is a rule on the account's exclusion list. It stops sends to matching addresses, even when the contact is active on a list. These routes cover the same rules as GET /lists/exclusions, with the stored field names. This is an internal operation. Returns every link between the rule and a list, with no paging. A link to list 0 means the rule applies to all lists.","operationId":"list-an-exclusions-exclusion-lists","x-canonical-resource":"lists","x-internal":true,"parameters":[{"$ref":"#/components/parameters/ExclusionId"}],"responses":{"200":{"description":"The links. exclusionLists is an empty array when the rule has none.","content":{"application/json":{"schema":{"type":"object","properties":{"exclusionLists":{"type":"array","description":"The links.","items":{"$ref":"#/components/schemas/ExclusionListLink"}}}},"examples":{"Result":{"value":{"exclusionLists":[{"exclusionid":"7","listid":"3","sync":"0","created_timestamp":"2026-10-01 09:30:00","updated_timestamp":"2026-10-01 09:30:00","links":[],"id":"12"}]}}}}}},"404":{"$ref":"#/components/responses/ExclusionNotFound"}}}},"/field/default":{"get":{"summary":"List contact standard-field defaults","description":"Returns the account-wide default values stored for contact standard fields, keyed by field name. The app stores them under the names firstname, lastname, email and phone. Some contact reads use the stored firstname and lastname defaults when a contact has no first or last name. GET /fieldDetails reports the same values as defaultValue. Only GET and POST do anything. Any other method gets an empty 200 response.","operationId":"list-contact-standard-field-defaults","x-canonical-resource":"custom_field_definition","x-internal":true,"responses":{"200":{"description":"Each stored default, keyed by field name. Values are strings. When no default is stored, the body is an empty array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactStandardFieldDefaults"},"examples":{"Result":{"value":{"firstname":"Sam","lastname":"Example"}},"None stored":{"value":[]}}}}}}},"post":{"summary":"Set a contact standard-field default","description":"Stores value as the account-wide default for the contact standard field named by field. An existing default for that field is replaced. A new name adds a new default. The app reads the names firstname, lastname, email and phone. Other names are stored and returned by GET /field/default, but nothing else reads them. Both parameters are read from the query string or a form body (form-encoded or multipart), not from a JSON body. When a parameter is in both, the query string wins. A missing value stores an empty string. A missing field stores the value under an empty name. Only GET and POST do anything. Any other method gets an empty 200 response.","operationId":"set-a-contact-standard-field-default","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"field":{"type":"string","description":"Name of the standard field, such as firstname.","example":"firstname"},"value":{"type":"string","description":"Default value to store. Defaults to an empty string.","example":"Sam"}}},"example":{"field":"firstname","value":"Sam"}}}},"responses":{"200":{"description":"The default was stored. The body is empty."}}}},"/field/reorder":{"post":{"summary":"Reorder contact custom fields","description":"Sets the display order of contact custom fields. For each entry of positions, the field with that id gets position as its new order number. Fields that are not listed keep their order number, and an id that matches no field changes nothing. positions is read from the query string or a form body (form-encoded or multipart), not from a JSON body. When it is in both, the query string wins. When positions is missing or empty, nothing changes and the body is empty. The script does not check the method: any other method runs the same code, with positions sent in the query string.","operationId":"reorder-contact-custom-fields","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"positions":{"type":"array","description":"The fields to move, sent as positions[0][id], positions[0][position] and so on.","items":{"type":"object","required":["id","position"],"properties":{"id":{"type":"integer","description":"ID of the custom field.","example":12},"position":{"type":"integer","description":"New order number. Fields are listed from the lowest number up.","example":1}}}}}},"encoding":{"positions":{"style":"deepObject","explode":true}},"example":{"positions":[{"id":12,"position":1},{"id":7,"position":2}]}}}},"responses":{"200":{"description":"The order numbers were updated. The body is always the same. It is JSON, but the script sets no Content-Type header, so the header is the server default.","content":{"application/json":{"schema":{"type":"object","properties":{"field":{"type":"array","description":"Always empty.","maxItems":0,"items":{},"example":[]}}},"examples":{"Result":{"value":{"field":[]}}}}}}}}},"/fieldDetails":{"get":{"summary":"List the required and default-value settings of standard fields","description":"Lists the account's settings for its standard fields: the built-in fields of contacts, deals and accounts, such as a contact's email or a deal's description. Each setting says whether the field must have a value and what value is used when it has none. Custom fields are not listed here: contact custom fields use GET/PUT /fields, and deal and account custom fields use /dealCustomFieldMeta and /accountCustomFieldMeta.\n\nOnly fields that have a setting are listed. Accounts are created with settings for contact.email (required), contact.first_name, contact.last_name, contact.phone, contact.userid, deal.description, account.account_url, account.account_owner and account.userid.\n\nThe list is not paginated. Any query parameter other than type returns 400.","operationId":"list-field-details","x-canonical-resource":"custom_field_definition","parameters":[{"name":"type","in":"query","required":false,"description":"Return only the settings for one record type: contact, deal or account. Any other value returns an empty list.","schema":{"type":"string","example":"contact"}}],"responses":{"200":{"description":"The settings. An empty array when none match.","content":{"application/json":{"schema":{"type":"object","properties":{"fieldDetails":{"type":"array","description":"One item per standard field that has a setting.","items":{"$ref":"#/components/schemas/FieldDetail"}}}},"examples":{"Result":{"value":{"fieldDetails":[{"id":"contact.first_name","name":"first_name","type":"contact","isRequired":false,"defaultValue":""},{"id":"contact.email","name":"email","type":"contact","isRequired":true,"defaultValue":""},{"id":"deal.description","name":"description","type":"deal","isRequired":false,"defaultValue":""},{"id":"contact.userid","name":"userid","type":"contact","isRequired":false,"defaultValue":"1"}]}}}}}},"400":{"description":"A query parameter other than type was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":400,"title":"Bad Request","detail":"Invalid parameters. Allowed parameters aretype"}]}}}}}}}},"post":{"summary":"Create a standard field setting","description":"This operation does not work. It returns 403 and creates nothing. To change a setting, use PUT /fieldDetails/{id}. To add a custom field, use POST /fields for contacts, or /dealCustomFieldMeta and /accountCustomFieldMeta for deals and accounts.\n\nNo field of the body is read. A non-empty JSON list, or a non-empty, non-zero JSON value that is not an object, returns 400. Any other body, including a JSON object, an empty value such as [], 0, \"\", \"0\", false or null, a body that is not JSON, or no body, returns 403. Internal.","operationId":"create-a-field-detail","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"responses":{"400":{"description":"The body is a non-empty JSON list, or a non-empty, non-zero JSON value that is not an object. detail names the type that was sent, such as \"Request body must be a JSON object, array given.\"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}}}},"403":{"description":"Returned for every request that gets this far. Nothing is changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":403,"title":"Forbidden","detail":"Forbidden"}]}}}}}}}}},"/fieldDetails/{id}":{"put":{"summary":"Update the required and default-value setting of a standard field","description":"Sets whether a standard field must have a value, and the value used when it has none. The change applies to the whole account. No permission beyond API access is checked, so any API user can change these settings. PATCH is accepted and does the same.\n\n- isRequired must be sent.\n- Sending isRequired true needs a non-empty defaultValue, except for contact.email, even when the field is already required. \"0\" counts as empty.\n- contact.email cannot be made optional.\n- When the field is contact.first_name, contact.last_name, contact.email or contact.phone, at least one contact standard field must stay required.\n- A missing or null defaultValue leaves the stored default as it is. Any other value replaces it, so an empty string clears it.\n\nEach broken rule returns 400 and changes nothing. 404 if the account has no setting with this id. Custom fields are changed elsewhere: contact custom fields with PUT /fields/{id}, and deal and account custom fields with /dealCustomFieldMeta and /accountCustomFieldMeta.","operationId":"update-a-field-detail","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"The setting's id from GET /fieldDetails, such as contact.first_name.","schema":{"type":"string","example":"contact.first_name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fieldDetail"],"properties":{"fieldDetail":{"type":"object","description":"The new settings for the field. A body without it, or without isRequired in it, gets 400.","required":["isRequired"],"properties":{"isRequired":{"type":"boolean","description":"Whether the field must have a value. Send a JSON boolean: a string such as \"false\" is read as true."},"defaultValue":{"type":["string","null"],"description":"The value to use when the field has none. Required, and not empty, when isRequired is true, except for contact.email. Leave it out, or send null, to keep the stored default."}},"additionalProperties":false}}},"examples":{"Request Example":{"value":{"fieldDetail":{"isRequired":true,"defaultValue":"Friend"}}}}}}},"responses":{"200":{"description":"The setting was saved. isRequired and defaultValue are the values from the request, not read back, so defaultValue is null when the request did not send one, even if a default is stored.","content":{"application/json":{"schema":{"type":"object","properties":{"fieldDetail":{"$ref":"#/components/schemas/FieldDetail"}}},"examples":{"Result":{"value":{"fieldDetail":{"id":"contact.first_name","name":"first_name","type":"contact","isRequired":true,"defaultValue":"Friend"}}}}}}},"400":{"description":"The body is not a JSON object, isRequired is missing, or one of the rules above is broken. detail is one of: \"Request body must be a JSON object, array given.\" (or another type), \"isRequired must be provided\", \"A defaultValue must be provided for required fields\", \"Contact email should be required.\", \"Name or Phone or Email must be required. Please make at least one of these fields required.\"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":400,"title":"Bad Request","detail":"A defaultValue must be provided for required fields"}]}}}}}},"404":{"description":"The account has no setting with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":404,"title":"Not Found"}]}}}}}}}},"delete":{"summary":"Delete a standard field setting","description":"This operation does not work. It returns 403 for any id and deletes nothing. The id is not looked up, so an id the account does not have also returns 403, not 404. Standard field settings cannot be removed. To make a field optional or clear its default, use PUT /fieldDetails/{id}. Internal.","operationId":"delete-a-field-detail","x-canonical-resource":"custom_field_definition","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"A setting id, such as contact.first_name. Any value gets the same response.","schema":{"type":"string","example":"contact.first_name"}}],"responses":{"403":{"description":"Returned for every request that gets this far. Nothing is changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldDetailError"},"examples":{"Result":{"value":{"errors":[{"status":403,"title":"Forbidden","detail":"Forbidden"}]}}}}}}}}},"/fieldOption/bulk":{"post":{"summary":"Create custom field options","description":"Creates several field options in one call, inside a single transaction: if any option fails validation the whole request is rolled back. Every entry must name the custom field it belongs to in its field property. Entries whose field id does not exist, or names a field the API user cannot access, are silently skipped, and entries whose value already exists on the field return the existing option instead of creating a new one. The response's fieldOptions array can therefore be shorter than the request's and can mix new and pre-existing options; match them to the request by value. label defaults to value. To add one option use POST /fieldOptions; to update or delete one use PUT or DELETE /fieldOptions/{id}. This is a separate endpoint from the /fieldOptions resource: it takes and returns arrays. It accepts POST and PUT only; other methods get 405.","operationId":"create-custom-field-options","x-canonical-resource":"fieldOption","x-destructive":false,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["fieldOptions"],"properties":{"fieldOptions":{"type":"array","minItems":1,"items":{"type":"object","required":["field","value"],"properties":{"field":{"type":"integer","description":"ID of the custom field to add the option to. Entries without it are silently skipped.","format":"int32"},"label":{"type":"string","description":"Name of the option"},"value":{"type":"string","description":"Value of the option"},"orderid":{"type":"integer","description":"Order for displaying the custom field option","format":"int32"},"isdefault":{"type":"boolean","description":"Whether or not this option is the default value"}}},"description":"The options to create. The endpoint rejects a request that does not carry this array."}}},"examples":{"Request Example":{"value":{"fieldOptions":[{"orderid":1,"value":"X","label":"Option X","isdefault":false,"field":"62"},{"orderid":2,"value":"Y","label":"Option Y","isdefault":false,"field":"62"},{"orderid":3,"value":"Z","label":"Option Z","isdefault":false,"field":"62"}]}}}}}},"responses":{"201":{"description":"The created options, plus any existing options returned for duplicate values. Skipped entries are missing.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOptions\": [\n        {\n            \"orderid\": 1,\n            \"value\": \"X\",\n            \"label\": \"Option X\",\n            \"isdefault\": 0,\n            \"field\": \"62\",\n            \"cdate\": \"2023-06-08T15:36:49-05:00\",\n            \"udate\": \"2023-06-08T15:36:49-05:00\",\n            \"links\": {\n                \"field\": \"https://{{yourAccount}}.api-us1.com/api/3/fieldOptions/1/field\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"orderid\": 2,\n            \"value\": \"Y\",\n            \"label\": \"Option Y\",\n            \"isdefault\": 0,\n            \"field\": \"62\",\n            \"cdate\": \"2023-06-08T15:36:49-05:00\",\n            \"udate\": \"2023-06-08T15:36:49-05:00\",\n            \"links\": {\n                \"field\": \"https://{{yourAccount}}.api-us1.com/api/3/fieldOptions/2/field\"\n            },\n            \"id\": \"2\"\n        },\n        {\n            \"orderid\": 3,\n            \"value\": \"Z\",\n            \"label\": \"Option Z\",\n            \"isdefault\": 0,\n            \"field\": \"62\",\n            \"cdate\": \"2023-06-08T15:36:49-05:00\",\n            \"udate\": \"2023-06-08T15:36:49-05:00\",\n            \"links\": {\n                \"field\": \"{{yourAccount}}.api-us1.com/api/3/fieldOptions/3/field\"\n            },\n            \"id\": \"3\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"fieldOptions":{"description":"One entry per created or matched option, in request order.","type":"array","items":{"type":"object","properties":{"orderid":{"description":"Display position of the option. For a new option, echoed as sent and absent when not sent; for an existing option returned for a duplicate value, a string.","type":["integer","string"],"example":1},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen. Echoed as sent.","type":"string","example":"X"},"label":{"description":"Display label of the option. Echoed as sent.","type":"string","example":"Option X"},"isdefault":{"description":"Whether the option is the field's default value. For a new option, echoed as sent and absent when not sent; for an existing option returned for a duplicate value, \"1\" or \"0\".","type":["boolean","integer","string"],"example":false},"field":{"description":"ID of the custom field the option belongs to. For a new option, echoed as sent; for an existing option, a string.","type":["integer","string"],"example":"62"},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2023-06-08T15:36:49-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2023-06-08T15:36:49-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://{{yourAccount}}.api-us1.com/api/3/fieldOptions/1/field"}}},"id":{"description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}.","type":"string","example":"1"}}}}}}}}},"422":{"description":"The body has no fieldOptions array, or it is empty. Nothing is created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": \"Bulk operation failed. Request must contain an array of fieldOption objects.\"\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"Why the request was refused.","type":"string","example":"Bulk operation failed. Request must contain an array of fieldOption objects."}}}}}}},"deprecated":false},"put":{"summary":"Update custom field options","description":"Updates several existing field options in one call, inside a single transaction: if any option fails validation the whole request is rolled back. Every entry must carry the id of the field option to update and its field property (the id of the custom field it belongs to). Entries without a field property, whose field id does not exist, or whose field the API user cannot access, are silently skipped and missing from the response; the response's fieldOptions array holds only the options that were actually updated. Every update rewrites an option's label to match its value unless the entry also changes the label to new text, so labels that differ from their values must be updated, not merely re-sent, to survive. 404 if an entry's id does not match an existing field option.","operationId":"update-custom-field-options","x-canonical-resource":"fieldOption","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["fieldOptions"],"properties":{"fieldOptions":{"description":"The options to update. A request without this array, or with an empty one, gets 422.","type":"array","items":{"type":"object","required":["id","field"],"properties":{"id":{"type":"integer","description":"ID of the field option to update."},"field":{"type":"integer","description":"ID of the custom field the option belongs to. Entries without it are silently skipped."},"value":{"type":"string","description":"New stored value of the option."},"label":{"type":"string","description":"New display label. Unless this property is changed by the update, the label is rewritten to match the option's value."},"orderid":{"type":"integer","description":"New display position of the option."},"isdefault":{"type":"boolean","description":"Whether the option is the field's default value."}}}}}},"examples":{"Request Example":{"value":{"fieldOptions":[{"id":81,"field":7,"value":"Early morning","label":"Early morning"},{"id":82,"field":7,"value":"Late evening","label":"Late evening"}]}}}}}},"responses":{"200":{"description":"The updated options. Properties sent in the request are echoed as sent; the others are strings.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOptions\": [\n        {\n            \"orderid\": \"1\",\n            \"value\": \"Early morning\",\n            \"label\": \"Early morning\",\n            \"isdefault\": \"0\",\n            \"field\": \"7\",\n            \"cdate\": \"2026-09-18T09:00:00-05:00\",\n            \"udate\": \"2026-09-18T09:00:00-05:00\",\n            \"links\": {\n                \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n            },\n            \"id\": \"81\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"fieldOptions":{"description":"One entry per updated option, in request order. Skipped entries are missing.","type":"array","items":{"type":"object","properties":{"orderid":{"description":"Display position of the option among the field's options; lower values come first.","type":"string","example":"1"},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen.","type":"string","example":"Morning"},"label":{"description":"Display label of the option.","type":"string","example":"Morning"},"isdefault":{"description":"\"1\" when this option is the field's default value, otherwise \"0\".","type":"string","example":"0"},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}}}}}}},"404":{"description":"An entry's id does not match an existing field option. The whole request is rolled back.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldOption with id 81\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field option id was not found.","type":"string","example":"No Result found for FieldOption with id 81"}}}}}},"422":{"description":"The body has no fieldOptions array, or it is empty. Nothing is updated.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": \"Bulk operation failed. Request must contain an array of fieldOption objects.\"\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"Why the request was refused.","type":"string","example":"Bulk operation failed. Request must contain an array of fieldOption objects."}}}}}}},"deprecated":false}},"/fieldOptions":{"get":{"summary":"List all field options","description":"Lists the options of the account's dropdown, listbox, radio, and checkbox custom contact fields, 20 per page by default. Use field to list one custom field's options; that and ids are the only supported filters on this endpoint. filters[...] and orders[...] parameters are not supported here and are silently ignored, so the response looks filtered but is not. Each entry's id is a field option id: it is valid only on the fieldOptions endpoints and must never be passed to /fields/{id}, which addresses whole custom field definitions in a separate id space. Each entry's field property holds the id of the field definition it belongs to. meta.total is the number of matching options, returned as a string; it is null whenever field is set.","operationId":"list-all-field-options","x-canonical-resource":"fieldOption","parameters":[{"name":"field","in":"query","description":"Return only the options of this custom field definition id. Exact match.","schema":{"type":"string"}},{"name":"ids","in":"query","description":"Comma-separated list of field option ids to fetch. Unlike most list endpoints, ids does not change the page size here: limit (default 20) still applies, so pass a limit at least as large as the number of ids.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of options per page. Default 20. There is no maximum, and 0 returns every option (offset is then ignored).","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of options to skip, for pagination.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The options on this page.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOptions\": [\n        {\n            \"orderid\": \"1\",\n            \"value\": \"Morning\",\n            \"label\": \"Morning\",\n            \"isdefault\": \"0\",\n            \"field\": \"7\",\n            \"cdate\": \"2026-09-18T09:00:00-05:00\",\n            \"udate\": \"2026-09-18T09:00:00-05:00\",\n            \"links\": {\n                \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n            },\n            \"id\": \"81\"\n        },\n        {\n            \"orderid\": \"2\",\n            \"value\": \"Afternoon\",\n            \"label\": \"Afternoon\",\n            \"isdefault\": \"0\",\n            \"field\": \"7\",\n            \"cdate\": \"2026-09-18T09:00:00-05:00\",\n            \"udate\": \"2026-09-18T09:00:00-05:00\",\n            \"links\": {\n                \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/82/field\"\n            },\n            \"id\": \"82\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOptions":{"description":"The options on this page.","type":"array","items":{"type":"object","properties":{"orderid":{"description":"Display position of the option among the field's options; lower values come first.","type":"string","example":"1"},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen.","type":"string","example":"Morning"},"label":{"description":"Display label of the option.","type":"string","example":"Morning"},"isdefault":{"description":"\"1\" when this option is the field's default value, otherwise \"0\".","type":"string","example":"0"},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}},"meta":{"description":"Paging information.","type":"object","properties":{"total":{"description":"Number of matching options, ignoring limit and offset, as a string. Known defect: whenever field is set, total is null, so page with limit and offset until a page comes back with fewer than limit options.","type":["string","null"],"example":"2"}}}}}}}}},"deprecated":false},"post":{"summary":"Create a field option","description":"Adds one option to an existing dropdown, listbox, radio, or checkbox custom field. If the field already has an option with the same value, no new option is created and the existing option is returned with status 200 instead of 201. label defaults to value. The field id in the payload is not checked against existing fields, so a wrong id silently creates an option that never appears on any field; confirm it with GET /fields/{id} first. The 201 response echoes the property types as sent; subsequent reads return every property as a string. To create several options in one call use POST /fieldOption/bulk.","operationId":"create-a-field-option","x-canonical-resource":"fieldOption","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["fieldOption"],"properties":{"fieldOption":{"description":"The option to create.","type":"object","required":["field","value"],"properties":{"field":{"type":"integer","description":"ID of the custom field definition to add the option to."},"value":{"type":"string","description":"Stored value of the option."},"label":{"type":"string","description":"Display label of the option. Defaults to value."},"orderid":{"type":"integer","description":"Display position of the option."},"isdefault":{"type":"boolean","description":"Whether the option is the field's default value."}}}}},"examples":{"Request Example":{"value":{"fieldOption":{"field":7,"value":"Morning","label":"Morning","orderid":1}}}}}}},"responses":{"200":{"description":"200: the field already had an option with this value; the existing option is returned and nothing is created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOption\": {\n        \"orderid\": \"1\",\n        \"value\": \"Morning\",\n        \"label\": \"Morning\",\n        \"isdefault\": \"0\",\n        \"field\": \"7\",\n        \"cdate\": \"2026-09-18T09:00:00-05:00\",\n        \"udate\": \"2026-09-18T09:00:00-05:00\",\n        \"links\": {\n            \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n        },\n        \"id\": \"81\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOption":{"description":"The existing option with this value.","type":"object","properties":{"orderid":{"description":"Display position of the option among the field's options; lower values come first.","type":"string","example":"1"},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen.","type":"string","example":"Morning"},"label":{"description":"Display label of the option.","type":"string","example":"Morning"},"isdefault":{"description":"\"1\" when this option is the field's default value, otherwise \"0\".","type":"string","example":"0"},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}}}}}},"201":{"description":"201: the option was created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOption\": {\n        \"field\": 7,\n        \"value\": \"Morning\",\n        \"label\": \"Morning\",\n        \"orderid\": 1,\n        \"cdate\": \"2026-09-18T09:00:00-05:00\",\n        \"udate\": \"2026-09-18T09:00:00-05:00\",\n        \"links\": {\n            \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n        },\n        \"id\": \"81\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOption":{"description":"The new option.","type":"object","properties":{"field":{"type":"integer","example":7,"description":"ID of the custom field definition the option was added to, echoed as sent."},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen. Echoed as sent.","type":"string","example":"Morning"},"label":{"description":"Display label of the option. Echoed as sent.","type":"string","example":"Morning"},"orderid":{"type":"integer","example":1,"description":"Echoed as sent; omitted properties are absent from the response."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id of the new option. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}}}}}},"400":{"description":"The request body is JSON but not an object, for example a list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldOptionBodyNotObjectError"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}}},"deprecated":false}},"/fieldOptions/{id}":{"get":{"summary":"Retrieve a field option","description":"Returns one field option by its field option id. The option's field property holds the id of the custom field definition it belongs to; use that id, never the option id, on the /fields/{id} endpoints. 404 if no option has this id.","operationId":"retrieve-a-field-option","x-canonical-resource":"fieldOption","parameters":[{"name":"id","in":"path","description":"ID of the field option, from the fieldOptions array of GET /fields or GET /fieldOptions. This is not a custom field definition id.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The field option.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOption\": {\n        \"orderid\": \"1\",\n        \"value\": \"Morning\",\n        \"label\": \"Morning\",\n        \"isdefault\": \"0\",\n        \"field\": \"7\",\n        \"cdate\": \"2026-09-18T09:00:00-05:00\",\n        \"udate\": \"2026-09-18T09:00:00-05:00\",\n        \"links\": {\n            \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n        },\n        \"id\": \"81\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOption":{"description":"The field option.","type":"object","properties":{"orderid":{"description":"Display position of the option among the field's options; lower values come first.","type":"string","example":"1"},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen.","type":"string","example":"Morning"},"label":{"description":"Display label of the option.","type":"string","example":"Morning"},"isdefault":{"description":"\"1\" when this option is the field's default value, otherwise \"0\".","type":"string","example":"0"},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}}}}}},"404":{"description":"No field option has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldOption with id 81\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field option id was not found.","type":"string","example":"No Result found for FieldOption with id 81"}}}}}}},"deprecated":false},"put":{"summary":"Update a field option","description":"Updates one field option by its field option id. Only the properties present in the request are changed, with one exception: every update rewrites the label to match the option's value unless the update also changes the label to new text (the campaign preferred-language field is the only exception). Sending the current label back does not preserve it, so a label that differs from its value is lost on any update that leaves the label unchanged. Renaming an option does not update contacts: a contact whose saved value is the old text keeps it until the contact is edited. 404 if no option has this id.","operationId":"update-a-field-option","x-canonical-resource":"fieldOption","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the field option, from the fieldOptions array of GET /fields or GET /fieldOptions. This is not a custom field definition id.","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["fieldOption"],"properties":{"fieldOption":{"description":"The properties to change; omitted properties are left as they are.","type":"object","properties":{"field":{"type":"integer","description":"ID of the custom field definition the option belongs to."},"value":{"type":"string","description":"New stored value of the option."},"label":{"type":"string","description":"New display label. Unless this property is changed by the update, the label is rewritten to match the option's value."},"orderid":{"type":"integer","description":"New display position of the option."},"isdefault":{"type":"boolean","description":"Whether the option is the field's default value."}}}}},"examples":{"Request Example":{"value":{"fieldOption":{"field":7,"value":"Early morning","label":"Early morning"}}}}}}},"responses":{"200":{"description":"The updated option. Properties sent in the request are echoed as sent; the others are strings.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOption\": {\n        \"orderid\": \"1\",\n        \"value\": \"Early morning\",\n        \"label\": \"Early morning\",\n        \"isdefault\": \"0\",\n        \"field\": \"7\",\n        \"cdate\": \"2026-09-18T09:00:00-05:00\",\n        \"udate\": \"2026-09-18T09:00:00-05:00\",\n        \"links\": {\n            \"field\": \"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field\"\n        },\n        \"id\": \"81\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOption":{"description":"The updated option.","type":"object","properties":{"orderid":{"description":"Display position of the option among the field's options; lower values come first.","type":"string","example":"1"},"value":{"description":"Stored value of the option. This is what a contact's field value holds when the option is chosen.","type":"string","example":"Morning"},"label":{"description":"Display label of the option.","type":"string","example":"Morning"},"isdefault":{"description":"\"1\" when this option is the field's default value, otherwise \"0\".","type":"string","example":"0"},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"description":"When the option was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"udate":{"description":"When the option was last changed, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-18T09:00:00-05:00"},"links":{"description":"API links for the option.","type":"object","properties":{"field":{"description":"API URL that returns the custom field this option belongs to.","type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field"}}},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}}}}}},"400":{"description":"The request body is JSON but not an object, for example a list. Checked before anything else.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldOptionBodyNotObjectError"}}}},"404":{"description":"No field option has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldOption with id 81\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field option id was not found.","type":"string","example":"No Result found for FieldOption with id 81"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a field option","description":"Deletes one option from a dropdown, listbox, radio, or checkbox custom field, leaving the field and its other options in place. The id is a field option id from the fieldOptions array of GET /fields or GET /fieldOptions, never a custom field definition id; deleting the whole field is DELETE /fields/{id}, which also destroys all contact values stored under it. Deleting an option does not update contacts: a contact whose saved value is the deleted option keeps that value until it is changed. 404 if no option has this id.","operationId":"delete-a-custom-field-option","x-canonical-resource":"fieldOption","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the field option, from the fieldOptions array of GET /fields or GET /fieldOptions. This is not a custom field definition id.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The option was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"No field option has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldOption with id 81\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field option id was not found.","type":"string","example":"No Result found for FieldOption with id 81"}}}}}}},"deprecated":false}},"/fieldRel/sync":{"post":{"summary":"Sync a field's list relationships","description":"Replaces a custom field's list relationships with exactly the given set: relationships to the listed lists are created where missing, and every other relationship of the field, including an all-lists relid 0 relationship, is deleted. The new relationships are created first, in one transaction; the deletions are then applied separately, row by row, so a failure during the deletions leaves the already-created relationships and completed deletions in place and the field's relationships partially replaced. The response's fieldRels array holds only the newly created relationships; ids of deleted relationships are returned in meta.deletedFieldRelIds, and meta is omitted when nothing was deleted. lists must contain at least one real list id: entries of 0 are ignored, and an empty or all-zero lists fails with 422. To relate a field to every list, use POST /fieldRel/syncExcept with an empty lists array, or POST /fieldRels with relid 0. 404 if the field does not exist. List ids are not checked against existing lists. No user permission is checked beyond API access. POST only; other methods get 405.","operationId":"sync-a-fields-list-relationships","x-canonical-resource":"fieldRels","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["field","lists"],"properties":{"field":{"type":"integer","description":"ID of the custom field definition whose list relationships are replaced."},"lists":{"type":"array","items":{"type":"integer"},"description":"List ids. Entries of 0 are ignored."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"field":49,"lists":[1,2]}}}}}},"responses":{"200":{"description":"The field's new relationships, and the ids of any it deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRels\": [\n        {\n            \"field\": \"49\",\n            \"relid\": 1,\n            \"dorder\": 0,\n            \"cdate\": \"2026-09-21T08:53:46-05:00\",\n            \"links\": [],\n            \"id\": \"71\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"fieldRels":{"type":"array","description":"The newly created relationships only; relationships that already existed are not repeated here.","items":{"type":"object","properties":{"field":{"description":"ID of the custom field.","type":"string","example":"49"},"relid":{"description":"ID of the list the field is now available on; 0 means all lists.","type":"integer","example":1},"dorder":{"description":"Position of the field among the list's fields. Always 0 for relationships created here.","type":"integer","example":0},"cdate":{"description":"When the relationship was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-21T08:53:46-05:00"},"id":{"description":"ID of the new field relationship; use it with GET or DELETE /fieldRels/{fieldRelId}.","type":"string","example":"71"},"links":{"type":"array","description":"Always empty for field relationships."}}}},"meta":{"type":"object","description":"Present only when relationships were deleted.","properties":{"deletedFieldRelIds":{"description":"IDs of the field relationships this request deleted.","type":"array","items":{"type":"string"},"example":["71"]}}}}}}}},"404":{"description":"No custom field has the id in field.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Field with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field id was not found.","type":"string","example":"No Result found for Field with id 999999"}}}}}},"422":{"description":"422: field is missing or lists contains no valid list id (response has the errors shape shown); an entirely empty request body also fails with 422 but with an empty response body.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": \"Bulk operation failed. Request body's 'field' key must contain a valid field ID.\"\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"Why the request was refused.","type":"string"}}}}}}},"deprecated":false}},"/fieldRel/syncExcept":{"post":{"summary":"Sync a field's list relationships by exclusion","description":"Relates a custom field to every list except the given ones. With a non-empty lists array, the field's relationships to those lists (and any all-lists relid 0 relationship) are deleted and explicit relationships to every other list are created. With an empty lists array, all of the field's relationships are replaced by a single all-lists relationship with relid 0. The deletions run first and are not rolled back if the create phase fails, so the field's relationships can be left partially replaced on a failure. The response's fieldRels array holds the newly created relationships; ids of deleted relationships are returned in meta.deletedFieldRelIds, and meta is omitted when nothing was deleted. 404 if the field does not exist. List ids are not checked against existing lists. No user permission is checked beyond API access. POST only; other methods get 405.","operationId":"sync-a-fields-list-relationships-by-exclusion","x-canonical-resource":"fieldRels","x-destructive":true,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["field","lists"],"properties":{"field":{"type":"integer","description":"ID of the custom field definition whose list relationships are replaced."},"lists":{"type":"array","items":{"type":"integer"},"description":"List ids the field must NOT be related to. Entries of 0 are filtered out, so a lists of [0] behaves exactly like an empty array: the field is related to every list via a single relid 0 relationship."}},"additionalProperties":false},"examples":{"Request Example":{"value":{"field":49,"lists":[]}}}}}},"responses":{"200":{"description":"The field's new relationships, and the ids of any it deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRels\": [\n        {\n            \"field\": \"49\",\n            \"relid\": 0,\n            \"dorder\": 0,\n            \"cdate\": \"2026-09-21T08:53:47-05:00\",\n            \"links\": [],\n            \"id\": \"72\"\n        }\n    ],\n    \"meta\": {\n        \"deletedFieldRelIds\": [\n            \"71\"\n        ]\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRels":{"type":"array","description":"The newly created relationships only; relationships that already existed are not repeated here.","items":{"type":"object","properties":{"field":{"description":"ID of the custom field.","type":"string","example":"49"},"relid":{"description":"ID of the list the field is now available on; 0 means all lists.","type":"integer","example":1},"dorder":{"description":"Position of the field among the list's fields. Always 0 for relationships created here.","type":"integer","example":0},"cdate":{"description":"When the relationship was created, in ISO 8601 with UTC offset.","type":"string","example":"2026-09-21T08:53:46-05:00"},"id":{"description":"ID of the new field relationship; use it with GET or DELETE /fieldRels/{fieldRelId}.","type":"string","example":"71"},"links":{"type":"array","description":"Always empty for field relationships."}}}},"meta":{"type":"object","description":"Present only when relationships were deleted.","properties":{"deletedFieldRelIds":{"description":"IDs of the field relationships this request deleted.","type":"array","items":{"type":"string"},"example":["71"]}}}}}}}},"404":{"description":"No custom field has the id in field.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Field with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field id was not found.","type":"string","example":"No Result found for Field with id 999999"}}}}}},"422":{"description":"422: field is missing (response has the errors shape shown); an entirely empty request body also fails with 422 but with an empty response body. An empty lists array is valid and is not rejected.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": \"Bulk operation failed. Request body's 'field' key must contain a valid field ID.\"\n}"}},"schema":{"type":"object","properties":{"errors":{"description":"Why the request was refused.","type":"string"}}}}}}},"deprecated":false}},"/fieldRels":{"post":{"summary":"Create a custom field relationship to list(s)","description":"Relates a custom field to a list so the field applies to contacts on that list. relid 0 relates the field to every list. If the relationship already exists, the existing record is returned with 200 instead of 201, in a reduced shape without links and with cdate formatted as a plain SQL datetime rather than ISO 8601. To remove a relationship use DELETE /fieldRels/{fieldRelId}; to replace a field's whole set of list relationships in one call use POST /fieldRel/sync or POST /fieldRel/syncExcept.","operationId":"create-a-custom-field-relationship-to-lists","x-canonical-resource":"fieldRels","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"fieldRel":{"description":"The relationship to create.","type":"object","properties":{"field":{"type":"integer","description":"ID of the field to create the relationship","default":8,"format":"int32"},"relid":{"type":"integer","description":"ID of the list to create the relationship (0 makes the field available on all lists)","default":2,"format":"int32"},"dorder":{"type":"integer"},"fieldid":{"type":"integer"}}}}},"examples":{"Request Example":{"value":{"fieldRel":{"field":8,"relid":2}}}}}}},"responses":{"200":{"description":"200: the field was already related to this list; the existing relationship is returned and nothing is created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRel\": {\n        \"field\": \"49\",\n        \"relid\": \"1\",\n        \"id\": \"70\",\n        \"cdate\": \"2026-09-21 08:53:44\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRel":{"description":"The existing relationship.","type":"object","properties":{"field":{"description":"ID of the custom field.","type":"string","example":"49"},"relid":{"description":"ID of the list; 0 means all lists.","type":"string","example":"1"},"id":{"description":"ID of the existing field relationship.","type":"string","example":"70"},"cdate":{"type":"string","example":"2026-09-21 08:53:44","description":"Plain SQL datetime on this duplicate path, unlike the ISO 8601 cdate returned on create."}}}}}}}},"201":{"description":"The relationship was created. field and relid are echoed as sent.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRel\": {\n        \"relid\": 2,\n        \"field\": 8,\n        \"cdate\": \"2019-02-01T08:39:25-06:00\",\n        \"links\": [],\n        \"id\": \"19\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRel":{"description":"The new relationship.","type":"object","properties":{"relid":{"description":"ID of the list the field is now available on; 0 means all lists. Echoed as sent.","type":"integer","example":2,"default":0},"field":{"description":"ID of the custom field, echoed as sent.","type":"integer","example":8,"default":0},"cdate":{"description":"When the relationship was created, in ISO 8601 with UTC offset.","type":"string","example":"2019-02-01T08:39:25-06:00"},"links":{"description":"Always empty for field relationships.","type":"array"},"id":{"description":"ID of the new field relationship; use it with GET, PUT or DELETE /fieldRels/{fieldRelId}.","type":"string","example":"19"}}}}}}}},"400":{"description":"The request body is JSON but not an object, for example a list. Checked before anything else.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldRelBodyNotObjectError"}}}},"403":{"description":"Only for API-key requests from users outside the Admin group: relid is a list the user does not have access to. relid 0 (all lists) is always allowed.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry describing the error.","type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"description":"HTTP status code."},"title":{"type":"string","example":"Forbidden","description":"Short name of the error."},"detail":{"type":"string","example":"You do not have permission to perform this action","description":"Why the request was refused."}}}}}},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to perform this action"}]}}}}},"deprecated":false},"get":{"summary":"List all custom field relationships to lists","description":"Lists which custom fields are available on which lists. A relationship with `relid` 0 makes the field available on every list. 20 per page by default, at most 100; ids overrides the limit, and 0 or a negative limit returns every relationship. filters[...] and orders[...] are ignored, and the order is not defined. No user permission is checked beyond API access: every relationship in the account is listed.","operationId":"list-all-custom-field-relationships","x-canonical-resource":"fieldRels","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","format":"int32","default":20},"description":"Maximum number of field relationships to return. Default 20, at most 100. 0 or a negative number returns all of them, and offset is then ignored."},{"name":"offset","in":"query","schema":{"type":"integer","format":"int32","default":0},"description":"Number of field relationships to skip, for paging"},{"name":"ids","in":"query","description":"Comma-separated list of field relationship ids to fetch. Overrides limit; offset still applies.","schema":{"type":"string"}}],"responses":{"200":{"description":"The field relationships on this page.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRels\": [\n        {\n            \"field\": \"2\",\n            \"relid\": \"17\",\n            \"dorder\": \"0\",\n            \"cdate\": \"2026-10-01T10:22:22-05:00\",\n            \"links\": [],\n            \"id\": \"434\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 1\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRels":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","example":"2","description":"ID of the custom field"},"relid":{"type":"string","example":"17","description":"ID of the list the field is available on; 0 means all lists"},"dorder":{"type":"string","example":"0","description":"Position of the field among the list's fields; lower values sort first. Usually 0"},"cdate":{"type":"string","example":"2026-10-01T10:22:22-05:00","description":"When the relationship was created, in ISO 8601 with UTC offset"},"links":{"type":"array","description":"Always empty for field relationships"},"id":{"type":"string","example":"434","description":"ID of the field relationship; use it with GET or DELETE /fieldRels/{fieldRelId}"}}},"description":"Field relationships, one per field and list pair"},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"description":"Number of matching field relationships, ignoring limit and offset."}},"description":"Paging metadata"}}}}}}},"deprecated":false}},"/fieldRels/{fieldRelId}":{"get":{"summary":"Retrieve a custom field relationship to lists","description":"Returns one field-to-list relationship by its id. relid 0 means the field is available on every list. No user permission is checked beyond API access. 404 if no field relationship has this id.","operationId":"retrieve-a-custom-field-relationship","x-canonical-resource":"fieldRels","parameters":[{"name":"fieldRelId","in":"path","description":"ID of the field relationship","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The field relationship.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRel\": {\n        \"field\": \"2\",\n        \"relid\": \"17\",\n        \"dorder\": \"0\",\n        \"cdate\": \"2026-10-01T10:22:22-05:00\",\n        \"links\": [],\n        \"id\": \"434\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRel":{"type":"object","properties":{"field":{"type":"string","example":"2","description":"ID of the custom field"},"relid":{"type":"string","example":"17","description":"ID of the list the field is available on; 0 means all lists"},"dorder":{"type":"string","example":"0","description":"Position of the field among the list's fields; lower values sort first. Usually 0"},"cdate":{"type":"string","example":"2026-10-01T10:22:22-05:00","description":"When the relationship was created, in ISO 8601 with UTC offset"},"links":{"type":"array","description":"Always empty for field relationships"},"id":{"type":"string","example":"434","description":"ID of the field relationship; use it with GET or DELETE /fieldRels/{fieldRelId}"}},"description":"The field relationship"}}}}}},"404":{"description":"No field relationship has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldRel with id 434\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for FieldRel with id 434","description":"No field relationship has this ID"}}}}}}},"deprecated":false},"put":{"summary":"Update a custom field relationship to lists","description":"Changes the field or list of one relationship. Saving also removes the field's other relationships that conflict with the new values, and the relationship being updated is not exempt:\n\n- Setting `relid` to 0 (all lists) deletes every list-specific relationship for the field. If this relationship currently has a list-specific `relid`, it is deleted too.\n- Setting `relid` to a list ID deletes the field's all-lists relationship (`relid` 0) and any other relationship between the field and that list. If this relationship currently has `relid` 0, it is deleted too.\n- Moving from one list to another list keeps this relationship.\n\nWhen this relationship is deleted, the response is still 200 and echoes the requested values, but `GET /fieldRels/{fieldRelId}` then returns 404, and the field may be left on no lists. To set which lists a field appears on, use `POST /fieldRel/sync` or `POST /fieldRel/syncExcept` instead; they are what the app uses. PATCH /fieldRels/{fieldRelId} does the same thing.","operationId":"update-a-custom-field-relationship","x-canonical-resource":"fieldRels","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"fieldRelId","in":"path","description":"ID of the field relationship","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"fieldRel":{"type":"object","description":"The values to change; omitted properties are left as they are","properties":{"field":{"type":"integer","format":"int32","description":"ID of the custom field to relate instead"},"relid":{"type":"integer","format":"int32","description":"ID of the list to relate the field to, or 0 for all lists. See the operation description for what changing to or from 0 deletes"},"dorder":{"type":"integer"},"fieldid":{"type":"integer"}}}}},"examples":{"Request Example":{"value":{"fieldRel":{"relid":6}}}}}}},"responses":{"200":{"description":"The relationship as saved, or the requested values if the update deleted it (see the operation description).","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldRel\": {\n        \"field\": \"2\",\n        \"relid\": 6,\n        \"dorder\": \"0\",\n        \"cdate\": \"2026-10-01T10:21:23-05:00\",\n        \"links\": [],\n        \"id\": \"433\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldRel":{"type":"object","description":"The relationship as saved in memory. If the update deleted it, these are the requested values and the relationship no longer exists","properties":{"field":{"type":["string","integer"],"example":"2","description":"ID of the custom field. Returned as an integer when the request changed it, otherwise as a string"},"relid":{"type":["string","integer"],"example":6,"description":"ID of the list the field is available on; 0 means all lists. Returned as an integer when the request changed it, otherwise as a string"},"dorder":{"type":"string","example":"0","description":"Position of the field among the list's fields; lower values sort first. Usually 0"},"cdate":{"type":"string","example":"2026-10-01T10:21:23-05:00","description":"When the relationship was created, in ISO 8601 with UTC offset"},"links":{"type":"array","description":"Always empty for field relationships"},"id":{"type":"string","example":"433","description":"ID of the field relationship; use it with GET or DELETE /fieldRels/{fieldRelId}"}}}}}}}},"400":{"description":"The request body is JSON but not an object, for example a list. Checked before anything else.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldRelBodyNotObjectError"}}}},"403":{"description":"The request is not tied to a user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry describing the error.","type":"array","items":{"type":"object","properties":{"status":{"type":"string","example":"403","description":"HTTP status code, as a string."},"detail":{"type":"string","example":"Forbidden","description":"Always Forbidden."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No field relationship has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldRel with id 434\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for FieldRel with id 434","description":"No field relationship has this ID"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a custom field relationship to list(s)","description":"Removes one field-to-list relationship by its fieldRel id, from the fieldRels array of GET /fields or the id in the POST /fieldRels response. The field itself and all stored contact values are untouched. 404 if no fieldRel has this id.","operationId":"delete-a-custom-field-relationship-to-lists","x-canonical-resource":"fieldRels","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"fieldRelId","in":"path","description":"Field relationship ID to be deleted","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The relationship was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The relationship could not be deleted. The body is plain text, not JSON, even though the response is labelled application/json.","content":{"application/json":{"schema":{"type":"string","example":"Failed to delete fieldRel"}}}},"404":{"description":"No field relationship has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldRel with id 70\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says which field relationship id was not found.","type":"string","example":"No Result found for FieldRel with id 70"}}}}}}},"deprecated":false}},"/fieldValues":{"post":{"summary":"Set a contact custom field value","description":"Sets a contact's value for one custom field. This operation is an upsert: when the contact has no value for the field yet, a new fieldValue is created and returned with 201; when a value already exists, that existing record is updated and returned with 200 with its original id, so a contact-and-field pair never produces two records. Multi-select fields (checkbox, listbox) store their selections as ||option 1||option 2||, wrapped and separated by double pipes. Date and datetime values are best sent in ISO 8601 (YYYY-MM-DD for dates); other formats are also read, as described on value. 422 if the field id is missing or does not exist, 404 if the contact does not exist, 400 if the body is not a JSON object. 403 without contact-edit permission, or, for a user outside the Admin group calling the API directly, when the field is not on any of the user's lists. The response side-loads the updated contact in a contacts array. The preferred language field comes back as its stored code here, not the language name the reads return.","operationId":"create-fieldvalue","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","description":"The field value to set.","properties":{"fieldValue":{"properties":{"contact":{"type":["integer","string"],"description":"ID of the contact."},"field":{"type":["integer","string"],"description":"ID of the custom field definition. Required: a missing or unknown id fails with 422."},"value":{"type":"string","description":"The value to store, as text. How it is stored depends on the field type. Checkbox and listbox: send the chosen options as ||option 1||option 2||; repeated pipes are collapsed, the value is wrapped in || when saved, and || or |||| clears it. Date: send YYYY-MM-DD; other formats are read using the account's date format, then as free-form text, and a value that cannot be read is stored as sent. Datetime: send ISO 8601, such as 2020-05-19T02:45:00-05:00; a value without an offset is read in the API user's time zone, the value is stored in UTC, and a value that cannot be read is stored as empty. Dropdown and radio: send one option's value, without pipes. Text, textarea and hidden: stored as sent. The value is not checked against the field's options."}},"required":["contact","field","value"],"type":"object","description":"The contact, the custom field and the value."},"useDefaults":{"type":"boolean"}}},"examples":{"text/textarea/hidden value":{"value":{"fieldValue":{"contact":2,"field":3,"value":"Blue"}}},"dropdown/radio value":{"value":{"fieldValue":{"contact":2,"field":4,"value":"Option 1"}}},"date value":{"value":{"fieldValue":{"contact":2,"field":7,"value":"2018-12-31"}}},"datetime value ISO format":{"value":{"fieldValue":{"contact":2,"field":7,"value":"2020-05-19T02:45:00-05:00"}}},"multiselect with multiple options":{"value":{"fieldValue":{"contact":2,"field":6,"value":"||Option 1||Option 3||Option 4||"}}},"multiselect with single option":{"value":{"fieldValue":{"contact":2,"field":6,"value":"||Option 2||"}}}}}}},"responses":{"200":{"description":"The contact already had a value for this field. That record was updated and is returned with its original id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2018-08-06T16:26:04-05:00\",\n            \"email\": \"sam@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"\",\n            \"lastName\": \"\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": null,\n            \"hash\": \"14d8c4418ae944c68e9dde4a975854cc\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": \"2018-10-01T17:18:40-05:00\",\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2018-09-21 12:04:40\",\n            \"updated_utc_timestamp\": \"2018-10-01 17:18:40\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/2/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/2/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/:version/contacts/2/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/2/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/2/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/2/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/2/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/2/scoreValues\"\n            },\n            \"id\": \"2\",\n            \"organization\": null\n        }\n    ],\n    \"fieldValue\": {\n        \"contact\": 2,\n        \"field\": 3,\n        \"value\": \"Blue\",\n        \"cdate\": \"2018-10-01T17:18:40-05:00\",\n        \"udate\": \"2018-10-01T17:18:40-05:00\",\n        \"links\": {\n            \"owner\": \"https://:account.api-us1.com/api/:version/fieldValues/15/owner\",\n            \"field\": \"https://:account.api-us1.com/api/:version/fieldValues/15/field\"\n        },\n        \"owner\": 2,\n        \"id\": \"15\"\n    }\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","description":"The contact the value belongs to. Usually present, because the contact is loaded while the value is saved. Only common contact fields are listed.","items":{"type":"object","properties":{"cdate":{"type":"string","description":"When the contact was created, in ISO 8601 with the account's UTC offset.","example":"2018-08-06T16:26:04-05:00"},"email":{"type":"string","description":"The contact's email address.","example":"sam@example.com"},"phone":{"type":"string","description":"The contact's phone number. Empty when not set.","example":""},"firstName":{"type":"string","description":"The contact's first name. Empty when not set.","example":""},"lastName":{"type":"string","description":"The contact's last name. Empty when not set.","example":""},"orgid":{"type":"string","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none.","example":"0"},"segmentio_id":{"type":"string","description":"Id of the contact in the Segment integration. Empty when the contact did not come from Segment.","example":""},"bounced_hard":{"type":"string","description":"Number of hard bounces recorded for the contact.","example":"0"},"bounced_soft":{"type":"string","description":"Number of soft bounces recorded for the contact.","example":"0"},"bounced_date":{"type":["string","null"],"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced."},"ip":{"type":"string","description":"IPv4 address the contact was added from, as a whole number. \"0\" when not recorded.","example":"0"},"ua":{"type":["string","null"],"description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded."},"hash":{"type":"string","description":"A 32-character identifier for the contact.","example":"14d8c4418ae944c68e9dde4a975854cc"},"socialdata_lastcheck":{"type":["string","null"],"description":"When social profile data was last looked up for the contact. Null when never looked up."},"email_local":{"type":"string","description":"The part of the email address before the @ sign. Usually empty.","example":""},"email_domain":{"type":"string","description":"The part of the email address after the @ sign.","example":""},"sentcnt":{"type":"string","description":"Number of campaigns that have been sent to the contact.","example":"0"},"rating_tstamp":{"type":["string","null"],"description":"Date the contact's engagement rating last changed. Null when never rated."},"gravatar":{"type":"string","description":"Gravatar lookup status: \"0\" not looked up yet, \"1\" no image found, \"2\" image found, \"3\" use the image from the appended social profile data.","example":"0"},"deleted":{"type":"string","description":"\"1\" when the contact has been soft-deleted, \"0\" otherwise.","example":"0"},"anonymized":{"type":"string","description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise.","example":"0"},"adate":{"type":["string","null"],"description":"When activity was last generated for the contact. Null when it never has been."},"udate":{"type":"string","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Changing the value moves it.","example":"2018-10-01T17:18:40-05:00"},"edate":{"type":["string","null"],"description":"Watermark for email activity generation. Null when email activity has never been generated for the contact."},"deleted_at":{"type":["string","null"],"description":"When the contact was soft-deleted. Null for a contact that has not been deleted."},"created_utc_timestamp":{"type":"string","description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS.","example":"2018-09-21 12:04:40"},"updated_utc_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Despite the name it is not in UTC.","example":"2018-10-01 17:18:40"},"links":{"type":"object","description":"URLs of the reads for the contact's related records.","properties":{"bounceLogs":{"type":"string","description":"URL of the read that lists the contact's bounce logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs"},"contactAutomations":{"type":"string","description":"URL of the read that lists the automations the contact has entered.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations"},"contactData":{"type":"string","description":"URL of the read for the contact's engagement data.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactData"},"contactGoals":{"type":"string","description":"URL of the read that lists the automation goals the contact has met.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactGoals"},"contactLists":{"type":"string","description":"URL of the read that lists the contact's list memberships.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLists"},"contactLogs":{"type":"string","description":"URL of the read that lists the contact's logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLogs"},"contactTags":{"type":"string","description":"URL of the read that lists the tags on the contact.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactTags"},"contactDeals":{"type":"string","description":"URL of the read that lists the links between the contact and deals.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactDeals"},"deals":{"type":"string","description":"URL of the read that lists the contact's deals.","example":"https://:account.api-us1.com/api/:version/contacts/2/deals"},"fieldValues":{"type":"string","description":"URL of the read that lists the contact's custom field values.","example":"https://:account.api-us1.com/api/:version/contacts/2/fieldValues"},"geoIps":{"type":"string","description":"URL of the read that lists the IP addresses recorded for the contact.","example":"https://:account.api-us1.com/api/:version/contacts/2/geoIps"},"notes":{"type":"string","description":"URL of the read that lists the contact's notes.","example":"https://:account.api-us1.com/api/:version/contacts/2/notes"},"organization":{"type":"string","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts.","example":"https://:account.api-us1.com/api/:version/contacts/2/organization"},"plusAppend":{"type":"string","description":"URL of the read for the contact's appended social profile data.","example":"https://:account.api-us1.com/api/:version/contacts/2/plusAppend"},"trackingLogs":{"type":"string","description":"URL of the read that lists the contact's tracking logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs"},"scoreValues":{"type":"string","description":"URL of the read that lists the contact's score values.","example":"https://:account.api-us1.com/api/:version/contacts/2/scoreValues"}}},"id":{"type":"string","description":"Id of the contact.","example":"2"},"organization":{"type":["string","null"],"description":"The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."}}}},"fieldValue":{"type":"object","description":"The stored value.","properties":{"contact":{"type":["integer","string"],"description":"ID of the contact the value belongs to, as sent in the request (a number or a string).","example":2,"default":0},"field":{"type":["integer","string"],"description":"ID of the custom field definition, as sent in the request (a number or a string).","example":3,"default":0},"value":{"type":"string","description":"The stored value. Checkbox and listbox values come back in the ||option 1||option 2|| form. Datetime values come back in ISO 8601 with the user's UTC offset.","example":"Blue"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2018-10-01T17:18:40-05:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2018-10-01T17:18:40-05:00"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/field"}}},"owner":{"type":["integer","string"],"description":"ID of the contact the value belongs to, the same as contact.","example":2,"default":0},"id":{"type":"string","description":"ID of the field value record. Use it with GET, PUT and DELETE /fieldValues/{id}.","example":"15"}}}}}}}},"201":{"description":"The contact had no value for this field. A new record was created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2018-08-06T16:26:04-05:00\",\n            \"email\": \"sam@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"\",\n            \"lastName\": \"\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": null,\n            \"hash\": \"14d8c4418ae944c68e9dde4a975854cc\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": \"2018-10-01T17:18:40-05:00\",\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2018-09-21 12:04:40\",\n            \"updated_utc_timestamp\": \"2018-10-01 17:18:40\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/2/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/2/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/:version/contacts/2/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/2/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/2/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/2/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/2/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/2/scoreValues\"\n            },\n            \"id\": \"2\",\n            \"organization\": null\n        }\n    ],\n    \"fieldValue\": {\n        \"contact\": 2,\n        \"field\": 3,\n        \"value\": \"Blue\",\n        \"cdate\": \"2018-10-01T17:18:40-05:00\",\n        \"udate\": \"2018-10-01T17:18:40-05:00\",\n        \"links\": {\n            \"owner\": \"https://:account.api-us1.com/api/:version/fieldValues/15/owner\",\n            \"field\": \"https://:account.api-us1.com/api/:version/fieldValues/15/field\"\n        },\n        \"owner\": 2,\n        \"id\": \"15\"\n    }\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","description":"The contact the value belongs to. Usually present, because the contact is loaded while the value is saved. Only common contact fields are listed.","items":{"type":"object","properties":{"cdate":{"type":"string","description":"When the contact was created, in ISO 8601 with the account's UTC offset.","example":"2018-08-06T16:26:04-05:00"},"email":{"type":"string","description":"The contact's email address.","example":"sam@example.com"},"phone":{"type":"string","description":"The contact's phone number. Empty when not set.","example":""},"firstName":{"type":"string","description":"The contact's first name. Empty when not set.","example":""},"lastName":{"type":"string","description":"The contact's last name. Empty when not set.","example":""},"orgid":{"type":"string","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none.","example":"0"},"segmentio_id":{"type":"string","description":"Id of the contact in the Segment integration. Empty when the contact did not come from Segment.","example":""},"bounced_hard":{"type":"string","description":"Number of hard bounces recorded for the contact.","example":"0"},"bounced_soft":{"type":"string","description":"Number of soft bounces recorded for the contact.","example":"0"},"bounced_date":{"type":["string","null"],"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced."},"ip":{"type":"string","description":"IPv4 address the contact was added from, as a whole number. \"0\" when not recorded.","example":"0"},"ua":{"type":["string","null"],"description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded."},"hash":{"type":"string","description":"A 32-character identifier for the contact.","example":"14d8c4418ae944c68e9dde4a975854cc"},"socialdata_lastcheck":{"type":["string","null"],"description":"When social profile data was last looked up for the contact. Null when never looked up."},"email_local":{"type":"string","description":"The part of the email address before the @ sign. Usually empty.","example":""},"email_domain":{"type":"string","description":"The part of the email address after the @ sign.","example":""},"sentcnt":{"type":"string","description":"Number of campaigns that have been sent to the contact.","example":"0"},"rating_tstamp":{"type":["string","null"],"description":"Date the contact's engagement rating last changed. Null when never rated."},"gravatar":{"type":"string","description":"Gravatar lookup status: \"0\" not looked up yet, \"1\" no image found, \"2\" image found, \"3\" use the image from the appended social profile data.","example":"0"},"deleted":{"type":"string","description":"\"1\" when the contact has been soft-deleted, \"0\" otherwise.","example":"0"},"anonymized":{"type":"string","description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise.","example":"0"},"adate":{"type":["string","null"],"description":"When activity was last generated for the contact. Null when it never has been."},"udate":{"type":"string","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Changing the value moves it.","example":"2018-10-01T17:18:40-05:00"},"edate":{"type":["string","null"],"description":"Watermark for email activity generation. Null when email activity has never been generated for the contact."},"deleted_at":{"type":["string","null"],"description":"When the contact was soft-deleted. Null for a contact that has not been deleted."},"created_utc_timestamp":{"type":"string","description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS.","example":"2018-09-21 12:04:40"},"updated_utc_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Despite the name it is not in UTC.","example":"2018-10-01 17:18:40"},"links":{"type":"object","description":"URLs of the reads for the contact's related records.","properties":{"bounceLogs":{"type":"string","description":"URL of the read that lists the contact's bounce logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs"},"contactAutomations":{"type":"string","description":"URL of the read that lists the automations the contact has entered.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations"},"contactData":{"type":"string","description":"URL of the read for the contact's engagement data.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactData"},"contactGoals":{"type":"string","description":"URL of the read that lists the automation goals the contact has met.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactGoals"},"contactLists":{"type":"string","description":"URL of the read that lists the contact's list memberships.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLists"},"contactLogs":{"type":"string","description":"URL of the read that lists the contact's logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLogs"},"contactTags":{"type":"string","description":"URL of the read that lists the tags on the contact.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactTags"},"contactDeals":{"type":"string","description":"URL of the read that lists the links between the contact and deals.","example":"https://:account.api-us1.com/api/:version/contacts/2/contactDeals"},"deals":{"type":"string","description":"URL of the read that lists the contact's deals.","example":"https://:account.api-us1.com/api/:version/contacts/2/deals"},"fieldValues":{"type":"string","description":"URL of the read that lists the contact's custom field values.","example":"https://:account.api-us1.com/api/:version/contacts/2/fieldValues"},"geoIps":{"type":"string","description":"URL of the read that lists the IP addresses recorded for the contact.","example":"https://:account.api-us1.com/api/:version/contacts/2/geoIps"},"notes":{"type":"string","description":"URL of the read that lists the contact's notes.","example":"https://:account.api-us1.com/api/:version/contacts/2/notes"},"organization":{"type":"string","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts.","example":"https://:account.api-us1.com/api/:version/contacts/2/organization"},"plusAppend":{"type":"string","description":"URL of the read for the contact's appended social profile data.","example":"https://:account.api-us1.com/api/:version/contacts/2/plusAppend"},"trackingLogs":{"type":"string","description":"URL of the read that lists the contact's tracking logs.","example":"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs"},"scoreValues":{"type":"string","description":"URL of the read that lists the contact's score values.","example":"https://:account.api-us1.com/api/:version/contacts/2/scoreValues"}}},"id":{"type":"string","description":"Id of the contact.","example":"2"},"organization":{"type":["string","null"],"description":"The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."}}}},"fieldValue":{"type":"object","description":"The stored value.","properties":{"contact":{"type":["integer","string"],"description":"ID of the contact the value belongs to, as sent in the request (a number or a string).","example":2,"default":0},"field":{"type":["integer","string"],"description":"ID of the custom field definition, as sent in the request (a number or a string).","example":3,"default":0},"value":{"type":"string","description":"The stored value. Checkbox and listbox values come back in the ||option 1||option 2|| form. Datetime values come back in ISO 8601 with the user's UTC offset.","example":"Blue"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2018-10-01T17:18:40-05:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2018-10-01T17:18:40-05:00"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/field"}}},"owner":{"type":["integer","string"],"description":"ID of the contact the value belongs to, the same as contact.","example":2,"default":0},"id":{"type":"string","description":"ID of the field value record. Use it with GET, PUT and DELETE /fieldValues/{id}.","example":"15"}}}}}}}},"400":{"description":"The request body is JSON but not an object: a non-empty list, or a single value such as a string, number or true. An empty or falsy body is read as an empty object and fails with 422.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as an integer."},"title":{"type":"string","description":"The HTTP status text, present on some errors."},"detail":{"type":"string","description":"What went wrong."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The caller may not change this value. Without permission to edit contacts the detail is Forbidden and status is a string. For a user outside the Admin group calling the API directly, the field must be available on at least one list the user can access (or on all lists); otherwise the detail is \"You do not have permission to perform this action\", with an integer status and a title.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status code. A string for missing contact-edit permission, an integer for the list check."},"title":{"type":"string","description":"The HTTP status text, present on some errors."},"detail":{"type":"string","description":"What went wrong."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No contact has the id in fieldValue.contact. A missing contact id is read as 0.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Subscriber with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for Subscriber with id 999999"}}}}}},"422":{"description":"fieldValue.field is missing, or no custom field has that id. Nothing was saved.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": \"422\",\n            \"detail\": \"Error: Field id not valid\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"string","description":"The HTTP status code, as a string."},"detail":{"type":"string","description":"What went wrong."}}}}}}}}}},"deprecated":false},"get":{"summary":"List contact custom field values","description":"Lists stored custom field values across contacts, one entry per contact-and-field pair, 20 per page by default. Each entry's contact property is the contact id, field is the custom field definition id, and value holds the stored text. Use filters[fieldid] to scope to one field, contacts[] to scope to contacts, or GET /contacts/{id}/fieldValues for a single contact's values. Values whose contact row no longer exists are excluded. Use only the query parameters documented here: unsupported filter and order fields are silently ignored, so the response looks filtered but is not; filters match exactly. Date and datetime values are returned in ISO 8601 in the API user's timezone. meta.total is the number of matching values, returned as a string. For a user outside the Admin group calling the API directly, only values of fields available on one of the user's lists (or on all lists) are returned. Without orders, the order is not defined.","operationId":"list-all-custom-field-values","x-canonical-resource":"custom_field_value","parameters":[{"name":"filters[fieldid]","in":"query","description":"Return only values of this custom field definition id. Exact match.","schema":{"type":"string"}},{"name":"filters[val]","in":"query","description":"Return only values exactly equal to this text. No partial matching.","schema":{"type":"string"}},{"name":"fields[]","in":"query","description":"Return only values of the given custom field definition ids, passed in array form: fields[]=1&fields[]=2. The non-array form fields=1,2 currently fails with a 500 error.","schema":{"type":"string"}},{"name":"contacts[]","in":"query","description":"Return only values belonging to the given contact ids, passed in array form: contacts[]=1&contacts[]=2. The non-array form contacts=1,2 currently fails with a 500 error.","schema":{"type":"string"}},{"name":"orders[fieldid]","in":"query","description":"Order values by custom field definition id. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[val]","in":"query","description":"Order values by the stored text. ASC or DESC.","schema":{"type":"string"}},{"name":"ids","in":"query","description":"Comma-separated list of fieldValue ids to fetch. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of values per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of values to skip, for pagination.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The matching values.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValues\": [\n        {\n            \"contact\": \"5\",\n            \"field\": \"1\",\n            \"value\": \"Burger\",\n            \"cdate\": \"2018-09-29T12:03:11-06:00\",\n            \"udate\": \"2018-09-29T12:03:11-06:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/1/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/1/field\"\n            },\n            \"id\": \"1\",\n            \"owner\": \"5\"\n        },\n        {\n            \"contact\": \"7\",\n            \"field\": \"2\",\n            \"value\": \"2018-05-10\",\n            \"cdate\": \"2018-04-24T12:04:46-06:00\",\n            \"udate\": \"2018-04-24T12:04:46-06:00\",\n            \"links\": {\n                \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/2/owner\",\n                \"field\": \"https://:account.api-us1.com/api/3/fieldValues/2/field\"\n            },\n            \"id\": \"2\",\n            \"owner\": \"7\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValues":{"type":"array","description":"One entry per matching contact-and-field value.","items":{"type":"object","properties":{"contact":{"type":"string","description":"ID of the contact the value belongs to.","example":"5"},"field":{"type":["string","null"],"description":"ID of the custom field definition. Null when the stored field id is 0.","example":"1"},"value":{"type":"string","description":"The stored value, as a string. Checkbox and listbox values use the ||option 1||option 2|| form, datetime values are converted to ISO 8601 in the requesting user's time zone, and the preferred language field returns the language name instead of its code.","example":"Burger"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2018-09-29T12:03:11-06:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2018-09-29T12:03:11-06:00"},"created_by":{"type":["string","null"],"description":"ID of the account user who created the value; 0 or null when it was not set by a user.","example":"0"},"updated_by":{"type":["string","null"],"description":"ID of the account user who last changed the value; 0 or null when the last change was not made by a user.","example":"0"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/3/fieldValues/1/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/3/fieldValues/1/field"}}},"id":{"type":"string","description":"ID of the field value record.","example":"1"},"owner":{"type":"string","description":"ID of the contact the value belongs to, the same as contact.","example":"5"}}}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"string","description":"Number of matching values, ignoring limit and offset, as a string.","example":"2"}}}}}}}}},"deprecated":false}},"/fieldValues/{id}":{"get":{"summary":"Retrieve a contact custom field value","description":"Returns one stored custom field value by its fieldValue id. The entry's contact property is the contact id and field is the custom field definition id. 404 if no fieldValue has this id. Unlike the list, this read does not check whether the field is on one of the caller's lists. Like the list, the preferred language field returns the language name instead of its code.","operationId":"retrieve-a-fieldvalues","x-canonical-resource":"custom_field_value","parameters":[{"name":"id","in":"path","description":"ID of the fieldValue to retrieve. This is the stored value's own id, not a contact id or field id.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"The value.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldValue\": {\n        \"contact\": \"5\",\n        \"field\": \"1\",\n        \"value\": \"Blue\",\n        \"cdate\": \"2018-09-18T10:30:31-05:00\",\n        \"udate\": \"2018-09-18T10:30:31-05:00\",\n        \"created_by\": \"0\",\n        \"updated_by\": \"0\",\n        \"links\": {\n            \"owner\": \"https://:account.api-us1.com/api/3/fieldValues/2/owner\",\n            \"field\": \"https://:account.api-us1.com/api/3/fieldValues/2/field\"\n        },\n        \"id\": \"2\",\n        \"owner\": \"5\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldValue":{"type":"object","description":"The stored value.","properties":{"contact":{"type":"string","description":"ID of the contact the value belongs to.","example":"0"},"field":{"type":["string","null"],"description":"ID of the custom field definition. Null when the stored field id is 0.","example":"1"},"value":{"type":"string","description":"The stored value, as a string. Checkbox and listbox values use the ||option 1||option 2|| form, and datetime values are converted to ISO 8601 in the requesting user's time zone.","example":"Blue"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2018-09-18T10:30:31-05:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2018-09-18T10:30:31-05:00"},"created_by":{"type":["string","null"],"description":"ID of the account user who created the value; 0 or null when it was not set by a user.","example":"0"},"updated_by":{"type":["string","null"],"description":"ID of the account user who last changed the value; 0 or null when the last change was not made by a user.","example":"0"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/3/fieldValues/2/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/3/fieldValues/2/field"}}},"id":{"type":"string","description":"ID of the field value record.","example":"2"},"owner":{"type":["string","null"],"description":"ID of the contact the value belongs to, the same as contact. Null when the stored contact id is 0.","example":"5"}}}}}}}},"404":{"description":"No field value has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldValue with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for FieldValue with id 10"}}}}}}},"deprecated":false},"put":{"summary":"Update a custom field value for contact","description":"Updates one stored custom field value by its fieldValue id. The request must include the fieldValue's contact and field ids along with the new value: omitting them fails with a misleading 404 that reports \"No Result found for Field with id 0\" rather than a validation error. Multi-select fields use the ||option 1||option 2|| format. Date and datetime values are best sent in ISO 8601; other formats are also read, as described on value. The response side-loads the updated contact in a contacts array. 403 without contact-edit permission, or, for a user outside the Admin group calling the API directly, when the field sent in fieldValue.field is not on any of the user's lists. Sending a contact and field that already have a different value record fails, because a contact can have only one value per field. Unlike the reads, the preferred language field comes back as its stored code.","operationId":"update-a-custom-field-value-for-contact","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the fieldValue to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","description":"The field value to set.","properties":{"fieldValue":{"properties":{"contact":{"type":["integer","string"],"description":"ID of the contact. Send the contact the record already belongs to: the ids sent are written to the record."},"field":{"type":["integer","string"],"description":"ID of the custom field definition. Send the field the record already belongs to. A missing or unknown id fails with 404."},"value":{"type":"string","description":"The value to store, as text. How it is stored depends on the field type. Checkbox and listbox: send the chosen options as ||option 1||option 2||; repeated pipes are collapsed, the value is wrapped in || when saved, and || or |||| clears it. Date: send YYYY-MM-DD; other formats are read using the account's date format, then as free-form text, and a value that cannot be read is stored as sent. Datetime: send ISO 8601, such as 2020-05-19T02:45:00-05:00; a value without an offset is read in the API user's time zone, the value is stored in UTC, and a value that cannot be read is stored as empty. Dropdown and radio: send one option's value, without pipes. Text, textarea and hidden: stored as sent. The value is not checked against the field's options."}},"required":["contact","field","value"],"type":"object","description":"The contact, the custom field and the value."},"useDefaults":{"type":"boolean"}}},"examples":{"text/textarea/hidden value":{"value":{"fieldValue":{"contact":4,"field":24,"value":"Blue"}}},"dropdown/radio value":{"value":{"fieldValue":{"contact":2,"field":5,"value":"Option 1"}}},"checkbox/listbox values (multiple)":{"value":{"fieldValue":{"contact":2,"field":6,"value":"||Option 1||Option 3||Option 4||"}}},"date value":{"value":{"fieldValue":{"contact":2,"field":7,"value":"2018-12-31"}}},"datetime value (ISO)":{"value":{"fieldValue":{"contact":2,"field":7,"value":"2020-05-19T02:45:00-05:00"}}},"checkbox/listbox values (single)":{"value":{"fieldValue":{"contact":2,"field":6,"value":"||Option 2||"}}}}}}},"responses":{"200":{"description":"The value was updated.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2018-08-06T16:56:43-05:00\",\n            \"email\": \"johndoe@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"John\",\n            \"lastName\": \"Doe\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": \"0000-00-00\",\n            \"ip\": \"4\",\n            \"ua\": \"\",\n            \"hash\": \"867d56644591991f6b50e1cb913f038b\",\n            \"socialdata_lastcheck\": \"0000-00-00 00:00:00\",\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": \"0000-00-00\",\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": \"2018-10-24T13:33:06-05:00\",\n            \"udate\": \"2018-10-24T13:33:11-05:00\",\n            \"edate\": \"2018-10-24T13:33:07-05:00\",\n            \"deleted_at\": \"0000-00-00 00:00:00\",\n            \"created_utc_timestamp\": \"2018-09-21 12:04:48\",\n            \"updated_utc_timestamp\": \"2018-10-24 13:33:11\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/24/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/24/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/24/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/24/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/24/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/24/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/24/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/24/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/:version/contacts/24/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/24/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/24/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/24/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/24/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/24/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/24/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/24/scoreValues\"\n            },\n            \"id\": \"24\",\n            \"organization\": null\n        }\n    ],\n    \"fieldValue\": {\n        \"contact\": 4,\n        \"field\": 24,\n        \"value\": \"Blue\",\n        \"cdate\": \"2018-10-24T13:32:52-05:00\",\n        \"udate\": \"2018-10-24T13:33:11-05:00\",\n        \"links\": {\n            \"owner\": \"https://:account.api-us1.com/api/:version/fieldValues/15/owner\",\n            \"field\": \"https://:account.api-us1.com/api/:version/fieldValues/15/field\"\n        },\n        \"owner\": 4,\n        \"id\": \"15\"\n    }\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","description":"The contact the value belongs to. Usually present, because the contact is loaded while the value is saved. Only common contact fields are listed.","items":{"type":"object","properties":{"cdate":{"type":"string","description":"When the contact was created, in ISO 8601 with the account's UTC offset.","example":"2018-08-06T16:56:43-05:00"},"email":{"type":"string","description":"The contact's email address.","example":"johndoe@example.com"},"phone":{"type":"string","description":"The contact's phone number. Empty when not set.","example":""},"firstName":{"type":"string","description":"The contact's first name. Empty when not set.","example":"John"},"lastName":{"type":"string","description":"The contact's last name. Empty when not set.","example":"Doe"},"orgid":{"type":"string","description":"Id of the account the contact belongs to through the legacy account link. \"0\" when there is none.","example":"0"},"segmentio_id":{"type":"string","description":"Id of the contact in the Segment integration. Empty when the contact did not come from Segment.","example":""},"bounced_hard":{"type":"string","description":"Number of hard bounces recorded for the contact.","example":"0"},"bounced_soft":{"type":"string","description":"Number of soft bounces recorded for the contact.","example":"0"},"bounced_date":{"type":["string","null"],"description":"Date of the most recent bounce, as YYYY-MM-DD. Null when the contact has never bounced.","example":"0000-00-00"},"ip":{"type":"string","description":"IPv4 address the contact was added from, as a whole number. \"0\" when not recorded.","example":"4"},"ua":{"type":["string","null"],"description":"Browser user agent recorded when the contact subscribed through a form. Null when not recorded.","example":""},"hash":{"type":"string","description":"A 32-character identifier for the contact.","example":"867d56644591991f6b50e1cb913f038b"},"socialdata_lastcheck":{"type":["string","null"],"description":"When social profile data was last looked up for the contact. Null when never looked up.","example":"0000-00-00 00:00:00"},"email_local":{"type":"string","description":"The part of the email address before the @ sign. Usually empty.","example":""},"email_domain":{"type":"string","description":"The part of the email address after the @ sign.","example":""},"sentcnt":{"type":"string","description":"Number of campaigns that have been sent to the contact.","example":"0"},"rating_tstamp":{"type":["string","null"],"description":"Date the contact's engagement rating last changed. Null when never rated.","example":"0000-00-00"},"gravatar":{"type":"string","description":"Gravatar lookup status: \"0\" not looked up yet, \"1\" no image found, \"2\" image found, \"3\" use the image from the appended social profile data.","example":"0"},"deleted":{"type":"string","description":"\"1\" when the contact has been soft-deleted, \"0\" otherwise.","example":"0"},"anonymized":{"type":"string","description":"\"1\" when the contact's personal data has been anonymized, \"0\" otherwise.","example":"0"},"adate":{"type":["string","null"],"description":"When activity was last generated for the contact. Null when it never has been.","example":"2018-10-24T13:33:06-05:00"},"udate":{"type":"string","description":"When the contact record was last modified, in ISO 8601 with the account's UTC offset. Changing the value moves it.","example":"2018-10-24T13:33:11-05:00"},"edate":{"type":["string","null"],"description":"Watermark for email activity generation. Null when email activity has never been generated for the contact.","example":"2018-10-24T13:33:07-05:00"},"deleted_at":{"type":["string","null"],"description":"When the contact was soft-deleted. Null for a contact that has not been deleted.","example":"0000-00-00 00:00:00"},"created_utc_timestamp":{"type":"string","description":"When the row was inserted into the database, as YYYY-MM-DD HH:MM:SS.","example":"2018-09-21 12:04:48"},"updated_utc_timestamp":{"type":"string","description":"When the row last changed, as YYYY-MM-DD HH:MM:SS. Despite the name it is not in UTC.","example":"2018-10-24 13:33:11"},"links":{"type":"object","description":"URLs of the reads for the contact's related records.","properties":{"bounceLogs":{"type":"string","description":"URL of the read that lists the contact's bounce logs.","example":"https://:account.api-us1.com/api/:version/contacts/24/bounceLogs"},"contactAutomations":{"type":"string","description":"URL of the read that lists the automations the contact has entered.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactAutomations"},"contactData":{"type":"string","description":"URL of the read for the contact's engagement data.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactData"},"contactGoals":{"type":"string","description":"URL of the read that lists the automation goals the contact has met.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactGoals"},"contactLists":{"type":"string","description":"URL of the read that lists the contact's list memberships.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactLists"},"contactLogs":{"type":"string","description":"URL of the read that lists the contact's logs.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactLogs"},"contactTags":{"type":"string","description":"URL of the read that lists the tags on the contact.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactTags"},"contactDeals":{"type":"string","description":"URL of the read that lists the links between the contact and deals.","example":"https://:account.api-us1.com/api/:version/contacts/24/contactDeals"},"deals":{"type":"string","description":"URL of the read that lists the contact's deals.","example":"https://:account.api-us1.com/api/:version/contacts/24/deals"},"fieldValues":{"type":"string","description":"URL of the read that lists the contact's custom field values.","example":"https://:account.api-us1.com/api/:version/contacts/24/fieldValues"},"geoIps":{"type":"string","description":"URL of the read that lists the IP addresses recorded for the contact.","example":"https://:account.api-us1.com/api/:version/contacts/24/geoIps"},"notes":{"type":"string","description":"URL of the read that lists the contact's notes.","example":"https://:account.api-us1.com/api/:version/contacts/24/notes"},"organization":{"type":"string","description":"URL of the read for the account named by orgid. Deprecated; use accountContacts.","example":"https://:account.api-us1.com/api/:version/contacts/24/organization"},"plusAppend":{"type":"string","description":"URL of the read for the contact's appended social profile data.","example":"https://:account.api-us1.com/api/:version/contacts/24/plusAppend"},"trackingLogs":{"type":"string","description":"URL of the read that lists the contact's tracking logs.","example":"https://:account.api-us1.com/api/:version/contacts/24/trackingLogs"},"scoreValues":{"type":"string","description":"URL of the read that lists the contact's score values.","example":"https://:account.api-us1.com/api/:version/contacts/24/scoreValues"}}},"id":{"type":"string","description":"Id of the contact.","example":"24"},"organization":{"type":["string","null"],"description":"The same value as orgid, except null instead of \"0\" when there is none. Deprecated; use accountContacts."}}}},"fieldValue":{"type":"object","description":"The stored value.","properties":{"contact":{"type":["integer","string"],"description":"ID of the contact the value belongs to, as sent in the request (a number or a string).","example":4,"default":0},"field":{"type":["integer","string"],"description":"ID of the custom field definition, as sent in the request (a number or a string).","example":24,"default":0},"value":{"type":"string","description":"The stored value. Checkbox and listbox values come back in the ||option 1||option 2|| form.","example":"Blue"},"cdate":{"type":"string","description":"When the value was first stored.","example":"2018-10-24T13:32:52-05:00"},"udate":{"type":"string","description":"When the value was last changed.","example":"2018-10-24T13:33:11-05:00"},"created_by":{"type":["string","null"],"description":"ID of the account user who created the value; 0 or null when it was not set by a user.","example":"0"},"updated_by":{"type":["string","null"],"description":"ID of the account user who last changed the value; 0 or null when the last change was not made by a user.","example":"0"},"links":{"type":"object","description":"URLs of the records related to this value.","properties":{"owner":{"type":"string","description":"URL of the contact the value belongs to.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/owner"},"field":{"type":"string","description":"URL of the custom field definition.","example":"https://:account.api-us1.com/api/:version/fieldValues/15/field"}}},"owner":{"type":["integer","string"],"description":"ID of the contact the value belongs to, the same as contact.","example":4,"default":0},"id":{"type":"string","description":"ID of the field value record. Use it with GET, PUT and DELETE /fieldValues/{id}.","example":"15"}}}}}}}},"400":{"description":"The request body is JSON but not an object: a non-empty list or a non-empty single value.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as an integer."},"title":{"type":"string","description":"The HTTP status text, present on some errors."},"detail":{"type":"string","description":"What went wrong."}}}}}},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}},"403":{"description":"The caller may not change this value. Without permission to edit contacts the detail is Forbidden and status is a string. For a user outside the Admin group calling the API directly, the field sent in fieldValue.field must be available on at least one list the user can access (or on all lists); otherwise the detail is \"You do not have permission to perform this action\", with an integer status and a title.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status code. A string for missing contact-edit permission, an integer for the list check."},"title":{"type":"string","description":"The HTTP status text, present on some errors."},"detail":{"type":"string","description":"What went wrong."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No field value has this id, no custom field has the id in fieldValue.field (a missing id reads as \"No Result found for Field with id 0\"), or no contact has the id in fieldValue.contact.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldValue with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for FieldValue with id 999999"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a contact custom field value","description":"Deletes one stored custom field value, clearing the field for that contact only. The field definition, its options, and other contacts' values are untouched. 404 if no fieldValue has this id; 403 without contact-edit permission.","operationId":"delete-a-fieldvalue-1","x-canonical-resource":"custom_field_value","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the fieldValue to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The value was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The caller may not change this value. Without permission to edit contacts the detail is Forbidden and status is a string. For a user outside the Admin group calling the API directly, the field must be available on at least one list the user can access (or on all lists); otherwise the detail is \"You do not have permission to perform this action\", with an integer status and a title.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"The HTTP status code. A string for missing contact-edit permission, an integer for the list check."},"title":{"type":"string","description":"The HTTP status text, present on some errors."},"detail":{"type":"string","description":"What went wrong."}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No field value has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for FieldValue with id 999999\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","description":"What was not found.","example":"No Result found for FieldValue with id 999999"}}}}}}},"deprecated":false}},"/fields":{"post":{"summary":"Create a contact custom field","description":"Creates a custom field definition for contacts. For dropdown, listbox, radio, and checkbox fields, create the options in the same request by adding an options array inside the field payload; list relationships can likewise be added as a relations array (relid 0 relates the field to every list). Each array is capped at 25 entries and the field plus its children are created in one transaction. Options can also be added later with POST /fieldOptions or POST /fieldOption/bulk. Fails with 400 when options are sideposted on a field type that cannot have options, and 422 when the title is already used by another field. Only title is required: type defaults to hidden when omitted, and ordernum is ignored on create because the new field is placed last. Without options or relations in the request, the response echoes the properties that were sent plus id, perstag, ordernum, cdate, udate, created_by and updated_by; with them, the complete field is read back with its options and relations and the fieldOptions and fieldRels side-loaded. The field is also added to the account's default field group unless group is sent. A lookup field (type lookup) is created with field.lookup naming the field of another CRM object it shows; it cannot be required and cannot have options of its own. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","operationId":"create-a-contact-custom-field","x-canonical-resource":"custom_field_definition","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"field":{"properties":{"title":{"type":"string","description":"Title of the field. Required, must not contain HTML, and must be unique among contact fields."},"type":{"type":"string","description":"Field type. Options are only allowed for dropdown, listbox, radio and checkbox. A value outside this list is not rejected up front and ends in a database error or an empty type. lookup shows a field of another CRM object and holds no value of its own; it needs field.lookup and cannot be required. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","enum":["text","textarea","checkbox","radio","dropdown","hidden","listbox","date","datetime","lookup"]},"descript":{"type":"string","description":"Description of field being created"},"perstag":{"type":"string","description":"Personalization tag, used as %TAG% in content. Uppercased and stripped of everything but A-Z, 0-9 and _ on save; generated from the title when blank. Not checked against other fields' tags on create, only on update."},"defval":{"type":"string","description":"Default value of the field being created"},"show_in_list":{"type":["integer","boolean"],"description":"1 to show this field in the contact list view, 0 to hide it. No longer used. true and false are accepted and stored as 1 and 0.","minimum":0,"maximum":1},"rows":{"type":"integer","description":"Number of rows of a textarea field. Only meaningful for type textarea and only honoured by the legacy form and custom-field renderers.","format":"int32"},"cols":{"type":"integer","description":"Number of columns of a textarea field. Only meaningful for type textarea and only honoured by the legacy form and custom-field renderers.","format":"int32"},"visible":{"type":["integer","boolean"],"description":"1 to show this field in the Form Builder, 0 to hide it. true and false are accepted and stored as 1 and 0.","minimum":0,"maximum":1},"isrequired":{"type":"integer","format":"int32","description":"Required flag of the field: 1 when a value is required, 0 when it is optional. Must be 0 for a lookup field."},"service":{"type":"string","description":"Free text naming the integration the field belongs to, for example salesforce or google. Empty by default and not validated."},"ordernum":{"type":"integer","description":"Ignored on create: the new field is placed last. Set it with PUT /fields/{id}.","format":"int32"},"group":{"type":"integer","format":"int32","description":"Any non-zero value stops the field from being added to the account's default field group. It does not place the field in another group; use the groupMembers endpoints for that."},"options":{"type":"array","description":"Options to create with the field, in one transaction. Only valid for dropdown, listbox, radio, and checkbox types; other types fail with 400. Maximum 25 entries; duplicate values are rejected with 400. Not accepted on a lookup field, whose single option row is its configuration.","items":{"type":"object","required":["value"],"properties":{"value":{"type":"string","description":"Stored value of the option. Required and non-empty; must be unique within the request."},"label":{"type":"string","description":"Display label of the option. Defaults to value."},"orderid":{"type":"integer","description":"Display position of the option. Defaults to its position in the array, counting from 1."},"isdefault":{"type":"boolean","description":"Whether the option is the field's default value. Defaults to false."}},"additionalProperties":false}},"relations":{"type":"array","description":"List relationships to create with the field, in the same transaction. Maximum 25 entries.","items":{"type":"object","required":["relid"],"properties":{"relid":{"type":"integer","description":"List id to relate the field to. 0 relates the field to every list."}},"additionalProperties":false}},"lookup":{"type":"object","description":"Configuration of a lookup field: the field of another CRM object it shows. Only accepted when the field's type is lookup. Required when type is lookup. Stored as the field's single option row (label lookup, value the JSON-encoded configuration), which must fit 250 characters once encoded. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","required":["object","field"],"properties":{"object":{"type":"string","enum":["account","contact","deal"],"description":"The CRM object whose field is shown."},"field":{"type":"string","description":"Identifier of the field shown, on that object. Must not be blank; surrounding whitespace is trimmed."}}}},"required":["title"],"type":"object","description":"The field to create.","additionalProperties":false}},"additionalProperties":false},"examples":{"textarea":{"value":{"field":{"type":"textarea","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","defval":"Default Value","visible":1,"ordernum":1}}},"text":{"value":{"field":{"type":"text","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","defval":"Default Value","visible":1,"ordernum":1}}},"date":{"value":{"field":{"type":"date","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","defval":"2025-01-01","visible":1,"ordernum":1}}},"dropdown":{"value":{"field":{"type":"dropdown","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","visible":1,"ordernum":1}}},"multiselect":{"value":{"field":{"type":"listbox","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","visible":1,"ordernum":1}}},"radio":{"value":{"field":{"type":"radio","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","visible":1,"ordernum":1}}},"checkbox":{"value":{"field":{"type":"checkbox","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","visible":1,"ordernum":1}}},"hidden":{"value":{"field":{"type":"hidden","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","defval":"Default Value","visible":1,"ordernum":1}}},"datetime (ISO)":{"value":{"field":{"type":"datetime","title":"Field Title","descript":"Field description","perstag":"Personalized Tag","defval":"2025-05-19T02:45:00-05:00","visible":1,"ordernum":1}}},"lookup":{"value":{"field":{"type":"lookup","title":"Deal owner","perstag":"DEAL_OWNER","lookup":{"object":"deal","field":"owner"}}}}}}}},"responses":{"201":{"description":"Created. The echo of the request for a plain field, or the complete field with its children when options or relations were sent.","content":{"application/json":{"schema":{"type":"object","properties":{"field":{"type":"object","properties":{"title":{"type":"string","example":"test","description":"Name of the field."},"type":{"type":"string","example":"text","description":"Field type: text, textarea, date, datetime, dropdown, listbox, radio, checkbox, hidden, lookup or calculated."},"perstag":{"type":"string","example":"TEST","description":"Personalization tag for the field, used as %PERSTAG% in messages. Uppercase letters, digits and underscores."},"id":{"type":"string","example":"1","description":"The field id. Use it with /fields/{id}; it is never a field option id."}},"description":"The created field. Without options or relations in the request this echoes the properties sent plus id, perstag, ordernum, cdate, udate, created_by and updated_by; with them, the complete field is read back. Either way the properties are as described for field in GET /fields/{id}."},"fieldOptions":{"type":"array","description":"Options of the new field, side-loaded, in the same shape as fieldOptions in GET /fields/{id}. Present, possibly empty, whenever options or relations were sent; absent otherwise.","items":{"type":"object"}},"fieldRels":{"type":"array","description":"List relationships of the new field, side-loaded, in the same shape as fieldRels in GET /fields/{id}. Present, possibly empty, whenever options or relations were sent; absent otherwise.","items":{"type":"object"}}}},"examples":{"Result":{"value":"{\n    \"field\": {\n        \"title\": \"Shoe size\",\n        \"type\": \"dropdown\",\n        \"perstag\": \"SHOE_SIZE\",\n        \"ordernum\": \"12\",\n        \"cdate\": \"2026-10-15T09:00:00-05:00\",\n        \"udate\": \"2026-10-15T09:00:00-05:00\",\n        \"options\": [\n            \"31\"\n        ],\n        \"relations\": [\n            \"40\"\n        ],\n        \"links\": {\n            \"options\": \"https://:account.api-us1.com/api/3/fields/12/options\",\n            \"relations\": \"https://:account.api-us1.com/api/3/fields/12/relations\"\n        },\n        \"id\": \"12\",\n        \"created_by\": \"1\",\n        \"updated_by\": \"1\"\n    },\n    \"fieldOptions\": [\n        {\n            \"field\": \"12\",\n            \"orderid\": \"1\",\n            \"value\": \"Small\",\n            \"label\": \"Small\",\n            \"isdefault\": \"0\",\n            \"cdate\": \"2026-10-15T09:00:00-05:00\",\n            \"udate\": \"2026-10-15T09:00:00-05:00\",\n            \"links\": {\n                \"field\": \"https://:account.api-us1.com/api/3/fieldOptions/31/field\"\n            },\n            \"id\": \"31\"\n        }\n    ],\n    \"fieldRels\": [\n        {\n            \"field\": \"12\",\n            \"relid\": \"0\",\n            \"dorder\": \"0\",\n            \"cdate\": \"2026-10-15T09:00:00-05:00\",\n            \"links\": [],\n            \"id\": \"40\"\n        }\n    ]\n}"}}}}},"400":{"description":"options or relations are malformed: more than 25 entries, an option without a value or with a duplicate value, a relation id that is not a whole number, or options sent for a type that cannot have them (type missing, or not dropdown, listbox, radio or checkbox). For a lookup field also: type lookup without field.lookup, field.lookup on another type, field.lookup that is not an object, an unknown object, a blank field or one too long to store, a required lookup field, options sent alongside field.lookup, or the crm-lookup-fields feature being off."},"403":{"description":"The API user may not manage custom fields, or may not access a list named in relations.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"403. A string when the user lacks the permission to manage custom fields; a number, with a title, when a list named in relations is not one the user can access."},"title":{"type":"string","description":"\"Forbidden\" in English. Present only with the numeric status."},"detail":{"type":"string","description":"\"Forbidden\", or with the numeric status \"You do not have permission to perform this action\"."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to perform this action\"\n        }\n    ]\n}"}}}}},"422":{"description":"title is missing, contains HTML, or is already used by another field.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"There is already a field with this title\",\n            \"detail\": \"There is already a field named 'Test Title' -- choose another name\",\n            \"code\": \"duplicate\"\n        }\n    ]\n}"}},"schema":{"anyOf":[{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The field title was not provided.","description":"What is wrong."},"detail":{"type":"string","example":"","description":"More detail. Can be empty."},"code":{"type":"string","example":"field_missing","description":"Machine-readable reason: field_missing, field_invalid or duplicate."}}},"description":"One entry per problem."}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"There is already a field with this personalization tag","description":"What is wrong."},"detail":{"type":"string","example":"There is already a personalization tag named 'Perstag' -- choose another name","description":"More detail. Can be empty."},"code":{"type":"string","example":"field_invalid","description":"Machine-readable reason: field_missing, field_invalid or duplicate."}}},"description":"One entry per problem."}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"There is already a field with this title","description":"What is wrong."},"detail":{"type":"string","example":"There is already a field named 'Test Title' -- choose another name","description":"More detail. Can be empty."},"code":{"type":"string","example":"duplicate","description":"Machine-readable reason: field_missing, field_invalid or duplicate."}}},"description":"One entry per problem."}}}]}}}}},"deprecated":false},"get":{"summary":"List contact custom fields","description":"Lists custom field definitions for contacts, 20 per page by default, ordered by ordernum then id unless an orders parameter is given. The response side-loads a fieldOptions array with the options of every returned field; ids inside it are field option ids, not field ids, and are only valid on the fieldOptions endpoints, never on /fields/{id}. A fieldRels array side-loads the fields' list relationships. Each field's own options property lists the ids of its options in the side-loaded array. Use only the query parameters documented here: unsupported filter and order fields are silently ignored, so the response looks filtered but is not. filters match exactly; use search for a partial title match. Passing any orders parameter, including an unsupported one, replaces the default ordernum ordering: when no supported orders field is given, the results come back in no guaranteed order. meta.total is the number of matching fields, returned as a string. This endpoint covers contact fields only; deal fields live under dealCustomFieldMeta and account fields under accountCustomFieldMeta.","operationId":"retrieve-fields","x-canonical-resource":"custom_field_definition","parameters":[{"name":"limit","in":"query","description":"Number of fields per page. Default 20, maximum 500.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Number of fields to skip, for pagination.","schema":{"type":"integer"}},{"name":"all","in":"query","description":"Pass all=1 to return every field in one response, ignoring limit and offset.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Return only fields whose title contains this text (substring match).","schema":{"type":"string"}},{"name":"filter","in":"query","description":"Comma-separated list of field types; returns only fields of those types. Example: filter=dropdown,listbox.","schema":{"type":"string"}},{"name":"listfilter","in":"query","description":"Comma-separated list of list ids; returns only fields related to those lists or to all lists.","schema":{"type":"string"}},{"name":"excludeHidden","in":"query","description":"Pass excludeHidden=1 to omit fields that are hidden in the Form Builder (visible flag 0).","schema":{"type":"string"}},{"name":"title_or_perstag","in":"query","description":"Return only fields whose title or personalization tag contains this text (substring match).","schema":{"type":"string"}},{"name":"perstags[]","in":"query","description":"Return only fields whose personalization tag is exactly one of the given values. Repeat the parameter for several tags: perstags[]=FIRSTNAME&perstags[]=LASTNAME.","schema":{"type":"string"}},{"name":"filters[id]","in":"query","description":"Return only the field with this id. Exact match.","schema":{"type":"string"}},{"name":"filters[title]","in":"query","description":"Return only fields with exactly this title. For a partial match use search instead.","schema":{"type":"string"}},{"name":"filters[perstag]","in":"query","description":"Return only fields with exactly this personalization tag. Example: CUSTOMER_GROUP.","schema":{"type":"string"}},{"name":"filters[type]","in":"query","description":"Return only fields of exactly this type. For several types at once use filter instead.","schema":{"type":"string"}},{"name":"filters[isrequired]","in":"query","description":"Return only fields whose isrequired flag equals this value (0 or 1).","schema":{"type":"string"}},{"name":"filters[ordernum]","in":"query","description":"Return only fields with exactly this ordernum. Exact match.","schema":{"type":"string"}},{"name":"orders[id]","in":"query","description":"Order fields by id. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[title]","in":"query","description":"Order fields by title. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[perstag]","in":"query","description":"Order fields by personalization tag. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[type]","in":"query","description":"Order fields by type. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[isrequired]","in":"query","description":"Order fields by the isrequired flag. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[ordernum]","in":"query","description":"Order fields by ordernum. ASC or DESC.","schema":{"type":"string"}},{"name":"ids[]","in":"query","description":"Field ids to fetch, passed in array form: ids[]=1&ids[]=2. Overrides limit. The comma-separated ids=1,2 form accepted by other endpoints currently fails with a 500 error on this endpoint.","schema":{"type":"string"}},{"name":"exclude_field_options","in":"query","description":"Pass exclude_field_options=1 to omit the side-loaded fieldOptions array and each field's options ids.","schema":{"type":"string"}},{"name":"exclude_field_rel","in":"query","description":"Pass exclude_field_rel=1 to omit the side-loaded fieldRels array and each field's relations ids.","schema":{"type":"string"}},{"name":"formid","in":"query","description":"Return only the custom fields that appear on this form id.","schema":{"type":"string"}},{"name":"isAi","in":"query","description":"Pass isAi=1 to add an is_ai flag to each field showing whether an AI dynamic-content block uses it.","schema":{"type":"string"}},{"name":"selected","in":"query","description":"A field id; echoes that field's id, title, and type under meta.selected.","schema":{"type":"string"}}],"responses":{"200":{"description":"The matching fields, with their options and list relationships side-loaded unless excluded. There is no error response of its own: unsupported parameters are ignored.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOptions\": [],\n    \"fieldRels\": [],\n    \"fields\": [\n        {\n            \"title\": \"Another Test Title\",\n            \"descript\": null,\n            \"type\": \"\",\n            \"isrequired\": \"0\",\n            \"perstag\": \"ANOTHER_TEST_TITLE\",\n            \"defval\": null,\n            \"show_in_list\": \"0\",\n            \"rows\": \"0\",\n            \"cols\": \"0\",\n            \"visible\": \"1\",\n            \"service\": \"\",\n            \"ordernum\": \"2\",\n            \"cdate\": \"2018-11-15T21:43:38-06:00\",\n            \"udate\": \"2018-11-15T21:43:38-06:00\",\n            \"options\": [],\n            \"relations\": [],\n            \"links\": {\n                \"options\": \"https://:account.api-us1.com/api/:version/fields/2/options\",\n                \"relations\": \"https://:account.api-us1.com/api/:version/fields/2/relations\"\n            },\n            \"id\": \"2\"\n        },\n        {\n            \"title\": \"Title\",\n            \"descript\": \"Field  description\",\n            \"type\": \"textarea\",\n            \"isrequired\": \"1\",\n            \"perstag\": \"PERSONALIZEDTAG\",\n            \"defval\": \"Default Value\",\n            \"show_in_list\": \"1\",\n            \"rows\": \"2\",\n            \"cols\": \"2\",\n            \"visible\": \"1\",\n            \"service\": \"google\",\n            \"ordernum\": \"3\",\n            \"cdate\": \"2018-11-15T21:42:40-06:00\",\n            \"udate\": \"2018-11-15T21:49:52-06:00\",\n            \"options\": [],\n            \"relations\": [],\n            \"links\": {\n                \"options\": \"https://:account.api-us1.com/api/:version/fields/1/options\",\n                \"relations\": \"https://:account.api-us1.com/api/:version/fields/1/relations\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOptions":{"type":"array","description":"Options of the returned dropdown, listbox, radio, and checkbox fields. Each entry's id is a field option id, valid only on the fieldOptions endpoints; its field property names the field definition it belongs to.","items":{"type":"object","properties":{"orderid":{"type":"string","example":"1","description":"Position of the option in the field's list of options."},"value":{"type":"string","example":"Morning","description":"Value stored when a contact picks the option."},"label":{"type":"string","example":"Morning","description":"Label shown for the option."},"isdefault":{"type":"string","example":"0","description":"1 when the option is selected by default, otherwise 0."},"field":{"type":"string","example":"7","description":"ID of the custom field definition this option belongs to. This is the id to use on the /fields/{id} endpoints."},"cdate":{"type":["string","null"],"example":"2026-09-18T09:00:00-05:00","description":"When the option was created, in ISO 8601. Null when not recorded."},"udate":{"type":["string","null"],"example":"2026-09-18T09:00:00-05:00","description":"When the option was last changed, in ISO 8601. Null when not recorded."},"links":{"type":"object","properties":{"field":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/fieldOptions/81/field","description":"URL that returns the option's field."}},"description":"URLs of the option's related reads."},"id":{"type":"string","example":"81","description":"Field option id. Valid only on the fieldOptions endpoints; never pass it to /fields/{id}."}}}},"fieldRels":{"type":"array","description":"List relationships of the returned fields.","items":{"type":"object","properties":{"field":{"type":"string","example":"7","description":"ID of the related custom field definition."},"relid":{"type":"string","example":"0","description":"List id the field is related to. 0 relates the field to every list."},"dorder":{"type":"string","example":"0","description":"Display order of the field for the list."},"cdate":{"type":["string","null"],"example":"2026-09-18T09:00:00-05:00","description":"When the relationship was created, in ISO 8601. Null when not recorded."},"id":{"type":"string","example":"1","description":"Field relationship id, used with DELETE /fieldRels/{fieldRelId}."}}}},"fields":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"Another Test Title","description":"Name of the field."},"descript":{"description":"Description of the field, shown in the app. Null or empty when none was set.","type":["string","null"]},"type":{"type":"string","example":"","description":"Field type: text, textarea, date, datetime, dropdown, listbox, radio, checkbox, hidden, lookup or calculated."},"isrequired":{"type":"string","example":"0","description":"1 when the field is required on forms, otherwise 0."},"perstag":{"type":"string","example":"ANOTHER_TEST_TITLE","description":"Personalization tag for the field, used as %PERSTAG% in messages. Uppercase letters, digits and underscores."},"defval":{"description":"Default value of the field. Null or empty when none was set.","type":["string","null"]},"show_in_list":{"type":"string","example":"0","description":"Legacy flag (0 or 1). No longer used."},"rows":{"type":"string","example":"0","description":"Height of a textarea field in rows. 0 when not set."},"cols":{"type":"string","example":"0","description":"Width of a textarea field in columns. 0 when not set."},"visible":{"type":"string","example":"1","description":"1 when the field is shown in the Form Builder, 0 when it is hidden."},"service":{"type":"string","example":"","description":"The integration that created the field, such as salesforce or shopify. Empty for fields created in the app or through the API."},"ordernum":{"type":"string","example":"2","description":"Position of the field in field lists."},"cdate":{"type":["string","null"],"example":"2018-11-15T21:43:38-06:00","description":"When the field was created, in ISO 8601. Null when not recorded."},"udate":{"type":["string","null"],"example":"2018-11-15T21:43:38-06:00","description":"When the field was last changed, in ISO 8601. Null when not recorded."},"options":{"type":"array","description":"Ids of this field's options in the side-loaded fieldOptions array. These are field option ids, never valid on /fields/{id}.","items":{"type":"string"}},"relations":{"type":"array","description":"Ids of this field's entries in the side-loaded fieldRels array.","items":{"type":"string"}},"links":{"type":"object","properties":{"options":{"type":"string","example":"https://:account.api-us1.com/api/:version/fields/2/options","description":"URL that lists the field's options."},"relations":{"type":"string","example":"https://:account.api-us1.com/api/:version/fields/2/relations","description":"URL that lists the field's list relationships."}},"description":"URLs of the field's related reads."},"id":{"type":"string","example":"2","description":"The field id. Use it with /fields/{id}; it is never a field option id."}}},"description":"The field definitions."},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2","description":"Number of matching fields, ignoring limit and offset, as a string."}},"description":"Paging information."}}}}}}},"deprecated":false}},"/fields/{id}":{"put":{"summary":"Update a contact custom field","description":"Updates a custom field definition by its field id. Only the properties present in the request are changed, plus udate and updated_by on every call. perstag is normalised on save (uppercased, A-Z, 0-9 and _ only) and regenerated from the title when blank. Changing type does not convert stored values or remove existing options; switching to textarea sets rows to 5 and cols to 40 when they are 0. Options cannot be managed here: options and relations keys in the payload are silently ignored. Manage options with the fieldOptions endpoints and list relationships with the fieldRels endpoints. 404 if no field has this id; 422 if title is emptied, contains HTML or is already used by another field, or if perstag is already used by another field or by a system personalization tag. A field cannot be changed into or out of type lookup; other type changes are unaffected. field.lookup replaces a lookup field's configuration, and is refused on a field of another type. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","operationId":"update-a-field","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom field definition to update, from the fields array of GET /fields. This is not a field option id; to change one option use PUT /fieldOptions/{id}.","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"field":{"properties":{"type":{"type":"string","description":"Field type. Options are only allowed for dropdown, listbox, radio and checkbox. A value outside this list is not rejected up front and ends in a database error or an empty type. lookup shows a field of another CRM object and holds no value of its own; it needs field.lookup and cannot be required. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","enum":["text","textarea","checkbox","radio","dropdown","hidden","listbox","date","datetime","lookup"]},"title":{"type":"string","description":"Title of the field being updated"},"descript":{"type":"string","description":"Description of field being updated"},"perstag":{"type":"string","description":"Personalization tag, used as %TAG% in content. Uppercased and stripped of everything but A-Z, 0-9 and _ on save; blank regenerates it from the title. 422 when another field or a system tag already uses it."},"defval":{"type":"string","description":"Default value of the field."},"show_in_list":{"type":["integer","boolean"],"description":"1 to show this field in the contact list view, 0 to hide it. No longer used. true and false are accepted and stored as 1 and 0.","minimum":0,"maximum":1},"rows":{"type":"integer","description":"Number of rows of a textarea field. Only meaningful for type textarea and only honoured by the legacy form and custom-field renderers.","format":"int32"},"cols":{"type":"integer","description":"Number of columns of a textarea field. Only meaningful for type textarea and only honoured by the legacy form and custom-field renderers.","format":"int32"},"visible":{"type":["integer","boolean"],"description":"1 to show this field in the Form Builder, 0 to hide it. true and false are accepted and stored as 1 and 0.","minimum":0,"maximum":1},"isrequired":{"type":"integer","format":"int32","description":"Required flag of the field: 1 when a value is required, 0 when it is optional. Must be 0 for a lookup field, whether or not field.lookup is sent."},"service":{"type":"string","description":"Free text naming the integration the field belongs to, for example salesforce or google. Empty by default and not validated."},"ordernum":{"type":"integer","format":"int32","description":"Order of appearance in the My Fields tab. Honoured on update."},"lookup":{"type":"object","description":"Configuration of a lookup field: the field of another CRM object it shows. Only accepted when the field's type is lookup. Replaces the stored configuration; omit it to keep the stored one. Stored as the field's single option row (label lookup, value the JSON-encoded configuration), which must fit 250 characters once encoded. Only for an account the crm-lookup-fields feature is on for; otherwise any request naming the lookup type or carrying field.lookup fails with 400.","required":["object","field"],"properties":{"object":{"type":"string","enum":["account","contact","deal"],"description":"The CRM object whose field is shown."},"field":{"type":"string","description":"Identifier of the field shown, on that object. Must not be blank; surrounding whitespace is trimmed."}}}},"required":[],"type":"object","description":"The properties to change. Properties left out keep their current value.","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"field":{"type":"textarea","title":"Title","descript":"Field  description","perstag":"Personalized Tag","defval":"Default Value","show_in_list":1,"rows":2,"cols":2,"visible":1,"service":"google","ordernum":3}}}}}}},"responses":{"200":{"description":"The updated field: the stored record with the values sent echoed as sent, so a value sent as a number comes back as a number.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"field\": {\n        \"title\": \"Title\",\n        \"descript\": \"Field  description\",\n        \"type\": \"textarea\",\n        \"isrequired\": 0,\n        \"perstag\": \"PERSONALIZEDTAG\",\n        \"defval\": \"Default Value\",\n        \"show_in_list\": 1,\n        \"rows\": 2,\n        \"cols\": 2,\n        \"visible\": 1,\n        \"service\": \"google\",\n        \"ordernum\": 3,\n        \"cdate\": \"2018-09-25T16:06:08-05:00\",\n        \"udate\": \"2018-09-29T18:23:20-05:00\",\n        \"links\": {\n            \"options\": \"https://:account.api-us1.com/api/:version/fields/3/options\",\n            \"relations\": \"https://:account.api-us1.com/api/:version/fields/3/relations\"\n        },\n        \"id\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"field":{"type":"object","properties":{"title":{"type":"string","example":"Title","description":"Name of the field."},"descript":{"type":["string","null"],"example":"Field  description","description":"Description of the field, shown in the app. Null or empty when none was set."},"type":{"type":"string","example":"textarea","description":"Field type: text, textarea, date, datetime, dropdown, listbox, radio, checkbox or hidden."},"isrequired":{"type":["integer","string"],"example":0,"default":0,"description":"1 when the field is required on forms, otherwise 0."},"perstag":{"type":"string","example":"PERSONALIZEDTAG","description":"Personalization tag for the field, used as %PERSTAG% in messages. Uppercase letters, digits and underscores."},"defval":{"type":["string","null"],"example":"Default Value","description":"Default value of the field. Null or empty when none was set."},"show_in_list":{"type":["integer","string"],"example":1,"default":0,"description":"Legacy flag (0 or 1). No longer used."},"rows":{"type":["integer","string"],"example":2,"default":0,"description":"Height of a textarea field in rows. 0 when not set."},"cols":{"type":["integer","string"],"example":2,"default":0,"description":"Width of a textarea field in columns. 0 when not set."},"visible":{"type":["integer","string"],"example":1,"default":0,"description":"1 when the field is shown in the Form Builder, 0 when it is hidden."},"service":{"type":"string","example":"google","description":"The integration that created the field, such as salesforce or shopify. Empty for fields created in the app or through the API."},"ordernum":{"type":["integer","string"],"example":3,"default":0,"description":"Position of the field in field lists."},"cdate":{"type":["string","null"],"example":"2018-09-25T16:06:08-05:00","description":"When the field was created, in ISO 8601. Null when not recorded."},"udate":{"type":["string","null"],"example":"2018-09-29T18:23:20-05:00","description":"When the field was last changed, in ISO 8601. Null when not recorded."},"created_timestamp":{"type":"string","example":"2019-02-25 09:00:02","description":"When the field was created, as YYYY-MM-DD HH:MM:SS rather than the ISO 8601 form cdate uses."},"updated_timestamp":{"type":"string","example":"2019-02-25 09:00:02","description":"When the field last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":"string","example":"1","description":"Id of the user who created the field."},"updated_by":{"type":"string","example":"1","description":"Id of the user who last changed the field."},"links":{"type":"object","properties":{"options":{"type":"string","example":"https://:account.api-us1.com/api/:version/fields/3/options","description":"URL that lists the field's options."},"relations":{"type":"string","example":"https://:account.api-us1.com/api/:version/fields/3/relations","description":"URL that lists the field's list relationships."}},"description":"URLs of the field's related reads."},"id":{"type":"string","example":"3","description":"The field id. Use it with /fields/{id}; it is never a field option id."}},"description":"The field definition."}}}}}},"400":{"description":"The request body is a non-empty JSON list or a single value instead of an object. Checked before anything else; an empty list, 0, false or null is read as an empty object. Also when type changes a field into or out of lookup; field.lookup is sent for a field that is not a lookup field, or is malformed or too long to store; isrequired is set on a lookup field; or the crm-lookup-fields feature is off and the request names the lookup type or carries field.lookup. Nothing is written when the request is refused.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Holds one entry that describes the problem.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code."},"title":{"type":"string","description":"Short name of the error."},"detail":{"type":"string","description":"What was wrong with the body."}}}}}}}}},"403":{"description":"The API user may not manage custom fields, or may not access the lists the field is related to.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"403. A string when the user lacks the permission to manage custom fields, or no user is attached to the request; a number, with a title, when the field is not on any of the user's lists."},"title":{"type":"string","description":"\"Forbidden\" in English. Present only with the numeric status."},"detail":{"type":"string","description":"\"Forbidden\", or with the numeric status \"You do not have permission to perform this action\"."}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to perform this action\"\n        }\n    ]\n}"}}}}},"404":{"description":"No field with this id."},"422":{"description":"title is empty, contains HTML, or is already used by another field; or perstag is already used by another field or by a system personalization tag.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry per problem.","items":{"type":"object","properties":{"title":{"type":"string","description":"What is wrong."},"detail":{"type":"string","description":"More detail. Can be empty."},"code":{"type":"string","description":"Machine-readable reason: field_missing, field_invalid or duplicate."},"error":{"type":"string","description":"Short error key. Can be empty."},"source":{"type":"object","description":"Where the problem is. pointer is /data/attributes/title or /data/attributes/perstag.","properties":{"pointer":{"type":"string","description":"The field that failed."}}}}}}}}}}}},"deprecated":false},"get":{"summary":"Get a custom field by ID","description":"Returns one custom field definition by its field id, with its options side-loaded in a fieldOptions array and its list relationships in a fieldRels array. Ids inside fieldOptions are field option ids, not field ids; they are only valid on the fieldOptions endpoints. 404 if no field has this id.","operationId":"retrieve-a-custom-field-contact","x-canonical-resource":"custom_field_definition","parameters":[{"name":"id","in":"path","description":"ID of the custom field definition to retrieve, from the fields array of GET /fields. Field option ids are a different id space and return the wrong record or 404 here.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The field, with its options and list relationships side-loaded.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"fieldOptions\": [],\n    \"fieldRels\": [\n        {\n            \"field\": \"1\",\n            \"relid\": \"0\",\n            \"dorder\": \"0\",\n            \"cdate\": \"2018-08-17T11:09:43-05:00\",\n            \"links\": [],\n            \"id\": \"1\"\n        }\n    ],\n    \"field\": {\n        \"title\": \"test\",\n        \"descript\": \"\",\n        \"type\": \"text\",\n        \"isrequired\": \"0\",\n        \"perstag\": \"TEST\",\n        \"defval\": \"\",\n        \"show_in_list\": \"0\",\n        \"rows\": \"0\",\n        \"cols\": \"0\",\n        \"visible\": \"1\",\n        \"service\": \"\",\n        \"ordernum\": \"1\",\n        \"cdate\": \"2018-08-17T11:09:43-05:00\",\n        \"udate\": \"2018-08-17T11:09:43-05:00\",\n        \"options\": [],\n        \"relations\": [\n            \"1\"\n        ],\n        \"links\": {\n            \"options\": \"https://:account.api-us1.com/api/3/fields/1/options\",\n            \"relations\": \"https://:account.api-us1.com/api/3/fields/1/relations\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"fieldOptions":{"type":"array","description":"Options of the returned field, side-loaded. Ids here are field option ids."},"fieldRels":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","example":"1","description":"Id of the field."},"relid":{"type":"string","example":"0","description":"Id of the list the field is related to. 0 relates the field to every list."},"dorder":{"type":"string","example":"0","description":"Display order of the field for the list."},"cdate":{"type":["string","null"],"example":"2018-08-17T11:09:43-05:00","description":"When the relationship was created, in ISO 8601. Null when not recorded."},"links":{"type":"array","description":"URLs of the relationship's related reads. Empty for list relationships."},"id":{"type":"string","example":"1","description":"The field relationship id. Use it with the fieldRels endpoints."}}},"description":"List relationships of the returned field, side-loaded."},"field":{"type":"object","properties":{"title":{"type":"string","example":"test","description":"Name of the field."},"descript":{"type":["string","null"],"example":"","description":"Description of the field, shown in the app. Null or empty when none was set."},"type":{"type":"string","example":"text","description":"Field type: text, textarea, date, datetime, dropdown, listbox, radio, checkbox, hidden, lookup or calculated."},"isrequired":{"type":"string","example":"0","description":"1 when the field is required on forms, otherwise 0."},"perstag":{"type":"string","example":"TEST","description":"Personalization tag for the field, used as %PERSTAG% in messages. Uppercase letters, digits and underscores."},"defval":{"type":["string","null"],"example":"","description":"Default value of the field. Null or empty when none was set."},"show_in_list":{"type":"string","example":"0","description":"Legacy flag (0 or 1). No longer used."},"rows":{"type":"string","example":"0","description":"Height of a textarea field in rows. 0 when not set."},"cols":{"type":"string","example":"0","description":"Width of a textarea field in columns. 0 when not set."},"visible":{"type":"string","example":"1","description":"1 when the field is shown in the Form Builder, 0 when it is hidden."},"service":{"type":"string","example":"","description":"The integration that created the field, such as salesforce or shopify. Empty for fields created in the app or through the API."},"ordernum":{"type":"string","example":"1","description":"Position of the field in field lists."},"cdate":{"type":["string","null"],"example":"2018-08-17T11:09:43-05:00","description":"When the field was created, in ISO 8601. Null when not recorded."},"udate":{"type":["string","null"],"example":"2018-08-17T11:09:43-05:00","description":"When the field was last changed, in ISO 8601. Null when not recorded."},"options":{"type":"array","description":"Ids of the field's options. Each id is a field option id and matches an entry in the side-loaded fieldOptions array."},"relations":{"type":"array","items":{"type":"string","example":"1"},"description":"Ids of the field's list relationships. Each id matches an entry in the side-loaded fieldRels array."},"links":{"type":"object","properties":{"options":{"type":"string","example":"https://:account.api-us1.com/api/3/fields/1/options","description":"URL that lists the field's options."},"relations":{"type":"string","example":"https://:account.api-us1.com/api/3/fields/1/relations","description":"URL that lists the field's list relationships."}},"description":"URLs of the field's related reads."},"id":{"type":"string","example":"1","description":"The field id. Use it with /fields/{id}; it is never a field option id."}},"description":"The field definition."}}}}}},"403":{"description":"Only for a user outside the Admin group calling the API directly: the field is not related to any of the user's lists or to every list.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","required":["status","title","detail"],"properties":{"status":{"type":"integer","description":"Always 403.","example":403},"title":{"type":"string","description":"\"Forbidden\" in English; it follows the API user's language.","example":"Forbidden"},"detail":{"type":"string","description":"\"You do not have permission to perform this action\" in English.","example":"You do not have permission to perform this action"}}}}}},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to perform this action\"\n        }\n    ]\n}"}}}}},"404":{"description":"No field has this id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says no field has this id.","example":"No Result found for Field with id 99"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a contact custom field","description":"Permanently deletes a custom field definition and all data stored under it: its options, every contact's saved value for the field, its list relationships, and its form placements. The id must be a custom field definition id, never a field option id; to delete a single dropdown option use DELETE /fieldOptions/{id} instead. Field ids and field option ids are separate id spaces: passing an option id here deletes whichever unrelated field happens to have that id, or returns 404 if none does. Field definition ids come from the id of each entry in the fields array of GET /fields; ids inside the side-loaded fieldOptions array are option ids and are never valid here. This delete cannot be undone. To clear one contact's value for a field without touching the field itself, use DELETE /fieldValues/{id}.","operationId":"delete-a-field","x-canonical-resource":"custom_field_definition","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the custom field definition to delete. This is not a field option id: option ids from the fieldOptions array of GET /fields are a different id space, and using one here targets an unrelated field. To delete one option use DELETE /fieldOptions/{id}.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The field was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The user lacks the permission to manage custom fields, or the field is not on any of the user's lists. If the delete itself fails, the body is instead the plain sentence \"Failed to delete field\", still sent with an application/json Content-Type. In that case the delete may have stopped partway: the field's stored values, options, list relationships, form placements and field group membership may already have been removed.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the refusal.","items":{"type":"object","properties":{"status":{"type":["string","integer"],"description":"403. A string when the user lacks the permission to manage custom fields, or no user is attached to the request; a number, with a title, when the field is not on any of the user's lists.","example":"403"},"title":{"type":"string","description":"\"Forbidden\" in English. Present only with the numeric status."},"detail":{"type":"string","description":"\"Forbidden\", or with the numeric status \"You do not have permission to perform this action\"."}}}}}},{"type":"string","example":"Failed to delete field"}]},"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to perform this action\"\n        }\n    ]\n}"}}}}},"404":{"description":"No field has this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Field with id 99\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Field with id 99","description":"Says no field has this id."}}}}}}},"deprecated":false}},"/form/automate_form":{"post":{"summary":"Create or find the form's submit automation","description":"Returns the ID of the automation that starts when this form is submitted, creating it first when the form has none: a new inactive automation named \"Automation for form <form name>\", owned by the calling user, whose start trigger is a submission of this form. When an automation with that trigger already exists its ID is returned and nothing is created, so the call is safe to repeat. Needs the automation management permission (`pg_automation_manage`). The body is read as JSON whatever the Content-Type header says. Only POST is answered; other methods get 405. Internal: backs Automate in the form builder, which then opens the automation.","operationId":"create-form-submit-automation","x-canonical-resource":"automation","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["form_id"],"properties":{"form_id":{"type":"integer","description":"ID of the form whose submission starts the automation.","example":12}}}}}},"responses":{"201":{"description":"The automation's ID, whether it was created by this call or already existed. The body is a bare JSON value, not an object, and the script sets no Content-Type header. It is `false` when creating the automation failed.","content":{"application/json":{"schema":{"type":["integer","string","boolean"],"description":"ID of the automation, as a number or a numeric string, or false when creating it failed."},"example":345}}},"400":{"description":"The body is not valid JSON, or decodes to null, false, 0 or an empty array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code as a string.","example":"400"},"detail":{"type":"string","description":"Always \"Invalid JSON payload\".","example":"Invalid JSON payload"}}}}}},"example":{"errors":[{"status":"400","detail":"Invalid JSON payload"}]}}}},"401":{"description":"No form has this `form_id`, or `form_id` is missing. The status is 401 although the caller is authenticated. The body is an empty JSON array.","content":{"application/json":{"schema":{"type":"array","maxItems":0,"items":{}},"example":[]}}},"403":{"description":"The user may not manage automations.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status.","example":403},"title":{"type":"string","description":"Short name of the HTTP status, in the user's language.","example":"Forbidden"},"detail":{"type":"string","description":"Always \"You don't have permission to perform this action.\", in the user's language.","example":"You don't have permission to perform this action."}}}}},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You don't have permission to perform this action."}]}}}}}},"deprecated":false,"x-internal":true}},"/form/delete_ecom_form":{"post":{"summary":"Remove a form embed from a Shopify store","description":"Asks the deep data integration service to remove the script tag for the form embed script `src` from the Shopify store of the given connection. Hosted adds the account ID and name and forwards the four fields; it validates none of them, and a field left out is forwarded as an empty string. Each field is read from a JSON body first, then from a form field or query parameter of the same name, so the form-encoded body the form builder sends works too. The response body is the deep data service's answer re-encoded as one JSON string, not the object inside it. Internal: backs the Shopify step of the form integration page.","operationId":"remove-form-from-shopify-store","requestBody":{"description":"The script to remove and the Shopify connection to remove it from. Sent as JSON or as form fields.","required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"properties":{"src":{"description":"URL of the form embed script whose script tag is removed from the store, `https://<account host>/f/embed.php?id=<form id>`.","type":"string","example":"https://example.activehosted.com/f/embed.php?id=4"},"connection_id":{"description":"ID of the account's Shopify connection (`/connections/{id}`).","type":"string","example":"13769"},"service":{"description":"Service of that connection, as the connection records it.","type":"string","example":"shopify"},"externalId":{"description":"External ID of that connection: the store's myshopify.com domain.","type":"string","example":"test.myshopify.com"}},"type":"object"}},"application/json":{"schema":{"properties":{"src":{"description":"URL of the form embed script whose script tag is removed from the store, `https://<account host>/f/embed.php?id=<form id>`.","type":"string","example":"https://example.activehosted.com/f/embed.php?id=4"},"connection_id":{"description":"ID of the account's Shopify connection (`/connections/{id}`).","type":"string","example":"13769"},"service":{"description":"Service of that connection, as the connection records it.","type":"string","example":"shopify"},"externalId":{"description":"External ID of that connection: the store's myshopify.com domain.","type":"string","example":"test.myshopify.com"}},"type":"object"}}}},"responses":{"200":{"description":"The deep data service accepted the request. The body is a JSON string holding the deep data service's response body; decode it a second time to read it.","content":{"application/json":{"schema":{"type":"string"},"example":"{\"success\":true}"}}},"4XX":{"description":"The deep data service refused the request. Its status code is passed through, and the body is a JSON string holding its response body.","content":{"application/json":{"schema":{"type":"string"},"example":"{\"message\":\"Unauthorized\"}"}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/form/delete_multiple":{"post":{"summary":"Delete several forms","description":"Deletes every form whose ID is in `ids`. Deleting a form also deletes the campaigns linked to it (such as its opt-in confirmation email), the form whose parent it is (its opt-in confirmation form, when it is not one itself), its submission records, its folder placements and its counters. IDs that match no form are skipped, and the answer is the same however many forms were deleted. `ids` is read from the query string, or from a form-encoded or multipart body; a JSON body is not read. Only POST is routed; other methods get 405. Internal: backs bulk delete on the forms index.","operationId":"delete-multiple-forms","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":true,"requestBody":{"description":"The forms to delete.","required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer"},"description":"IDs of the forms to delete, sent as repeated `ids[]` fields. A single `ids` field is read as a list of one.","example":[12,15]}},"required":["ids"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer"},"description":"IDs of the forms to delete, sent as repeated `ids[]` fields. A single `ids` field is read as a list of one.","example":[12,15]}},"required":["ids"]}}}},"responses":{"200":{"description":"Always, once the IDs have been processed. The script writes JSON without setting a Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","description":"Always `{\"success\": true}`.","properties":{"success":{"type":"boolean","description":"Always true.","example":true}}}}},"example":{"meta":{"success":true}}}}}},"deprecated":false,"x-internal":true}},"/form/deletescreenshot":{"post":{"summary":"Delete a form's screenshot","description":"Deletes the most recent screenshot recorded for the form, the preview image shown on the forms index. The form itself is not looked up: an ID with no screenshot answers `{\"success\": false}` whether or not the form exists. Send `id` in the query string or as a form field in a form-encoded body; a JSON body is not read. Legacy endpoint with no method guard: every method gets the same answer, but only POST deletes the screenshot. Internal.","operationId":"delete-form-screenshot","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"query","description":"ID of the form. May be sent as a form field instead.","required":false,"schema":{"type":"integer"},"example":12}],"requestBody":{"description":"`id` as a form field, when it is not in the query string.","required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the form.","example":12}}}}}},"responses":{"200":{"description":"`{\"success\": true}` when a screenshot was found (and, for POST, deleted); `{\"success\": false}` when the form has none. When `id` is missing or 0 the body is empty. The script writes JSON without setting a Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"True when a screenshot was found and deleted, false when the form has no screenshot."}}},"example":{"success":true}}}}},"deprecated":false,"x-internal":true}},"/form/duplicate":{"post":{"summary":"Duplicate a form","description":"Copies the form under the name \"<name> (Copy)\", in the user's language, and returns the copy's ID and name. The copy starts active even when the original is paused. Copying a form that is not itself an opt-in confirmation form also copies its opt-in confirmation email campaign and its opt-in confirmation form, and links both to the copy. A preference center form can only be copied while the account has fewer than 20 preference centers. Send `id` in the query string or as a form field in a form-encoded body; a JSON body is not read. The React forms app sends it in the query string and the Ember app as a form field. Only POST is routed; other methods get 405. Internal: backs Duplicate on the forms index.","operationId":"copy-a-form","x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"id","in":"query","description":"ID of the form to copy. May be sent as a form field instead.","required":false,"schema":{"type":"integer"},"example":12}],"requestBody":{"description":"`id` as a form field, when it is not in the query string.","required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the form to copy.","example":12}}}}}},"responses":{"200":{"description":"The copy. When `id` is missing or 0, or no form has it, the body is empty and nothing is copied. The script writes JSON without setting a Content-Type header.","content":{"application/json":{"schema":{"type":"object","required":["success","form"],"properties":{"success":{"type":"boolean","description":"Always true.","example":true},"form":{"type":"object","description":"The new form.","required":["id","name"],"properties":{"id":{"type":["integer","string"],"description":"ID of the copy.","example":31},"name":{"type":"string","description":"Name of the copy: the original's name followed by \" (Copy)\" in the user's language.","example":"Newsletter signup (Copy)"}}}}},"example":{"success":true,"form":{"id":31,"name":"Newsletter signup (Copy)"}}}}},"403":{"description":"The form is a preference center and the account already has 20.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status.","example":403},"title":{"type":"string","description":"Short name of the HTTP status, in the user's language.","example":"Forbidden"},"detail":{"type":"string","description":"Always \"You have reached your limit of 20 Preference Centers\".","example":"You have reached your limit of 20 Preference Centers"}}}}},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You have reached your limit of 20 Preference Centers"}]}}}}}},"deprecated":false,"x-internal":true}},"/form/ecom_form_status":{"get":{"summary":"Retrieve the form embed status of a Shopify store","description":"Asks the deep data integration service whether a form embed is active in the Shopify store of the given connection, and returns its answer with its status code. Hosted adds the account ID and name to the four query parameters and forwards them without validating any. When the deep data service answers with JSON the body is that JSON unchanged; Hosted does not shape it. Internal: backs the Shopify step of the form integration page.","operationId":"retrieve-shopify-form-embed-status","parameters":[{"name":"connection_id","in":"query","description":"ID of the account's Shopify connection (`/connections/{id}`).","required":false,"schema":{"type":"string"},"example":"13769"},{"name":"service","in":"query","description":"Service of that connection, as the connection records it.","required":false,"schema":{"type":"string"},"example":"shopify"},{"name":"externalId","in":"query","description":"External ID of that connection: the store's myshopify.com domain.","required":false,"schema":{"type":"string"},"example":"test.myshopify.com"},{"name":"src","in":"query","description":"URL of a form embed script, forwarded when given. The app does not send it.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"The deep data service's answer, passed through as it sent it.","content":{"application/json":{"schema":{"description":"Defined by the deep data service, not by Hosted.","type":"object","additionalProperties":true},"example":{"status":"inactive","method":"theme","form":null}}}},"4XX":{"description":"The deep data service refused the request. Its status code is passed through; a JSON body is passed through unchanged, any other body is returned as one JSON string.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"string"}]},"example":"Unauthorized Access to Shopify API"}}}},"x-canonical-resource":"forms","x-internal":true}},"/form/formprocessing":{"get":{"summary":"Retrieve the user's time zone","description":"The calling user's time zone and its current offset from UTC. Takes no parameters. Only GET is answered; any other method gets 405 with `Allow: GET` and an empty body. Internal.","operationId":"retrieve-form-processing-time-zone","x-canonical-resource":"forms","responses":{"200":{"description":"The user's time zone.","content":{"application/json":{"schema":{"type":"object","required":["timeOffset","timezone"],"properties":{"timeOffset":{"type":"number","description":"Current offset of the user's time zone from UTC, in hours, daylight saving included. A whole number for most zones; fractional for zones such as Asia/Kolkata (5.5).","example":-5},"timezone":{"type":"string","description":"The user's time zone, as an IANA name.","example":"America/Chicago"}}},"example":{"timeOffset":-5,"timezone":"America/Chicago"}}}}},"deprecated":false,"x-internal":true}},"/form/formstatistics":{"get":{"summary":"Retrieve a form's usage statistics","description":"How many times the form was submitted and how many contacts it created, including those since deleted. Only GET is answered; any other method gets 405 with `Allow: GET` and an empty body. Internal: backs the statistics view on the forms index.","operationId":"retrieve-form-usage-statistics","x-canonical-resource":"forms","parameters":[{"name":"id","in":"query","description":"ID of the form. Without it, or with 0, the answer is 200 with an empty body and no Content-Type.","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"The form's statistics. An ID that matches no form answers with every count at 0.","content":{"application/json":{"schema":{"type":"object","required":["submits","contacts","contacts_deleted"],"properties":{"submits":{"type":["string","integer"],"description":"Number of submissions recorded for the form. A count, usually as a numeric string; the number 0 when there is nothing to count.","example":"42"},"contacts":{"type":["string","integer"],"description":"Number of distinct contacts the form created: submitters whose contact record was created no earlier than 60 seconds before the form subscribed them to a list, plus submitters whose contact has since been deleted. A count, usually as a numeric string; the number 0 when there is nothing to count.","example":"17"},"contacts_deleted":{"type":["string","integer"],"description":"Number of distinct submitters whose contact has since been deleted. Included in `contacts`. A count, usually as a numeric string; the number 0 when there is nothing to count.","example":"2"}}},"example":{"submits":"42","contacts":"17","contacts_deleted":"2"}}}}},"deprecated":false,"x-internal":true}},"/form/hide_tip":{"get":{"summary":"Retrieve whether the form builder tip is dismissed","description":"Whether the inspector tip in the form builder has been dismissed. The setting is account-wide, so a dismissal by any user hides the tip for every user. Legacy endpoint with no method guard: GET reads and POST sets; any other method gets 200 with an empty body and changes nothing. Internal: read when the form builder opens.","operationId":"retrieve-form-builder-tip-dismissal","x-canonical-resource":"forms","responses":{"200":{"description":"The JSON number 1 when the tip has been dismissed, 0 when it has not. The body is a bare number, not an object.","content":{"application/json":{"schema":{"type":"integer","enum":[0,1],"description":"1: dismissed. 0: not dismissed."},"example":1}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Dismiss the form builder tip","description":"Dismisses the inspector tip in the form builder for every user on the account, by setting the account-wide setting `forms.hide_tip` to 1. Takes no body. Nothing in the API undoes it, and repeating it changes nothing. Legacy endpoint with no method guard: GET reads and POST sets; any other method gets 200 with an empty body and changes nothing. Internal: called when a user closes the tip.","operationId":"dismiss-form-builder-tip","x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"The tip is dismissed. The body is empty."}},"deprecated":false,"x-internal":true}},"/form/html":{"get":{"summary":"Retrieve a form's embed HTML","description":"The HTML that embeds the form in a page: its styles, markup and script, as the full embed option of the form integration page shows it. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses. Internal: backs the full embed code on the form integration page.","operationId":"retrieve-form-embed-code","x-canonical-resource":"forms","parameters":[{"name":"id","in":"query","description":"ID of the form.","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"The embed HTML. When `id` is missing or 0, or no form has it, the body is empty.","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/form/image":{"post":{"summary":"Upload an image for a form","description":"Stores an uploaded image in the account's image storage, under the calling user's username (and the session's upload folder, when one is set), and returns the stored path as plain text. The file name is lower-cased, spaces become underscores, and every character other than a letter, digit, dot, underscore or dash is dropped. Only names ending in .gif, .jpg, .jpeg, .png or .bmp are stored, and none containing `.php`. An image already stored under the same name is replaced. Legacy endpoint with no method guard: any other method gets 200 with an empty body and stores nothing. Internal.","operationId":"upload-form-image","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The image."},"iefile":{"type":"string","format":"binary","description":"The image, under the field name older Internet Explorer uploads used. Read only when `file` is absent or has no file name."}}}}}},"responses":{"200":{"description":"The path the image was stored under, as plain text: `<username>/<file name>`, or `<username>/<upload folder>/<file name>`. When nothing was stored (no file, or a refused name) the body is not a usable path.","content":{"text/plain":{"schema":{"type":"string"},"example":"jdoe/logo.png"}}}},"deprecated":false,"x-internal":true}},"/form/migrate":{"get":{"summary":"Migrate legacy forms","description":"Converts the account's forms from the legacy form table (`em_old_form`) into forms of the current form builder, keeping each form's ID: every legacy form with target 1, and every one with target 8 that has a base form. The legacy form's lists, opt-in settings, thank-you content and fields are carried over, and its old screenshot is deleted. Writes one `Migrating <name>...<br/>` line per form, as HTML. It does not skip forms that were migrated before. Answers only an ActiveCampaign staff (ARC) session on the account, or a local development install; anyone else gets 200 with an empty body and nothing is migrated. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is documented because the output is meant for a browser, and it writes despite the verb. Internal: a one-off migration tool.","operationId":"migrate-legacy-forms","x-canonical-resource":"forms","responses":{"200":{"description":"One progress line per migrated form, or an empty body when the caller is not allowed to migrate.","content":{"text/html":{"schema":{"type":"string"},"example":"Migrating Newsletter signup...<br/>Migrating Contact us...<br/>"}}}},"deprecated":false,"x-internal":true}},"/form/optin":{"post":{"description":"","operationId":"post_formoptin","x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":""}},"parameters":[]}},"/form/save_ecom_form":{"post":{"summary":"Embed a form in a Shopify store","description":"Asks the deep data integration service to add the form embed script `src` to the Shopify store of the given connection, as a script tag. Hosted adds the account ID and name and forwards the four fields; it validates none of them, and a field left out is forwarded as an empty string. Each field is read from a JSON body first, then from a form field or query parameter of the same name, so the form-encoded body the form builder sends works too. The response body is the deep data service's answer re-encoded as one JSON string, not the object inside it. Internal: backs the Shopify step of the form integration page.","operationId":"add-form-to-shopify-store","requestBody":{"description":"The script to add and the Shopify connection to add it to. Sent as JSON or as form fields.","required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"properties":{"src":{"description":"URL of the form embed script to add to the store, `https://<account host>/f/embed.php?id=<form id>`.","type":"string","example":"https://example.activehosted.com/f/embed.php?id=4"},"connection_id":{"description":"ID of the account's Shopify connection (`/connections/{id}`).","type":"string","example":"13769"},"service":{"description":"Service of that connection, as the connection records it.","type":"string","example":"shopify"},"externalId":{"description":"External ID of that connection: the store's myshopify.com domain.","type":"string","example":"test.myshopify.com"}},"type":"object"}},"application/json":{"schema":{"properties":{"src":{"description":"URL of the form embed script to add to the store, `https://<account host>/f/embed.php?id=<form id>`.","type":"string","example":"https://example.activehosted.com/f/embed.php?id=4"},"connection_id":{"description":"ID of the account's Shopify connection (`/connections/{id}`).","type":"string","example":"13769"},"service":{"description":"Service of that connection, as the connection records it.","type":"string","example":"shopify"},"externalId":{"description":"External ID of that connection: the store's myshopify.com domain.","type":"string","example":"test.myshopify.com"}},"type":"object"}}}},"responses":{"200":{"description":"The deep data service accepted the request. The body is a JSON string holding the deep data service's response body; decode it a second time to read it.","content":{"application/json":{"schema":{"type":"string"},"example":"{\"success\":true}"}}},"4XX":{"description":"The deep data service refused the request. Its status code is passed through, and the body is a JSON string holding its response body.","content":{"application/json":{"schema":{"type":"string"},"example":"{\"message\":\"Unauthorized\"}"}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/form/screenshot":{"post":{"summary":"Request a new screenshot of a form","description":"Asks the screenshot service for a new screenshot of the form, the preview image on the forms index: the form's latest screenshot record gets the new screenshot URL, or a record is created when it has none. The ID is read only from a form field in the body; neither the query string nor a JSON body is read. Not available on a local development install. Legacy endpoint with no method guard: any other method gets 200 with an empty body and requests nothing. Internal: the form builder calls it after a form is saved.","operationId":"request-form-screenshot","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"requestBody":{"description":"The form to take a screenshot of.","required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the form.","example":12}},"required":["id"]}}}},"responses":{"200":{"description":"Plain text `Screenshot of Form successfully requested` when the screenshot was requested. When `id` is missing or empty, or on a local development install, the body is instead a JSON failure object (with a Content-Type of application/json) and nothing is requested; its message is \"No Form specified to take screenshot of.\" or \"Form Screenshots do not work in developer mode\".","content":{"text/plain":{"schema":{"type":"string"},"example":"Screenshot of Form successfully requested"},"application/json":{"schema":{"type":"object","properties":{"success":{"type":"integer","description":"0: the request failed.","example":0},"message":{"type":"string","description":"Why it failed, in the user's language."},"result_code":{"type":"integer","description":"Legacy external-API envelope: the same as `success`. Present only on requests the API treats as external.","example":0},"result_message":{"type":"string","description":"Legacy external-API envelope: the same as `message`. Present only on requests the API treats as external."},"result_output":{"type":"string","description":"Legacy external-API envelope: always `json`. Present only on requests the API treats as external.","example":"json"}},"required":["success","message"]},"example":{"success":0,"message":"No Form specified to take screenshot of."}}}}},"deprecated":false,"x-internal":true}},"/form/sift":{"get":{"summary":"Answer a GET on the form Sift endpoint","description":"Does nothing and always answers 200 with an empty JSON object. The form Sift endpoint used to be a script that answered every method; GET is still routed so callers and probes that send it keep getting a 200. To report a form update, use POST. Internal.","operationId":"retrieve-form-sift-noop","responses":{"200":{"description":"Always. The body is an empty JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}}},"x-canonical-resource":"forms","x-internal":true},"post":{"summary":"Report a form update to Sift","description":"Sends the form as the form builder holds it to Sift, the fraud detection service, as a form update event attributed to the calling user, so form content can be screened for abuse. The form builder calls it when the user leaves the builder or turns the form into an automation. Nothing is stored in Hosted. While the account's `sift-form-content-update` feature flag is off the body is still validated but no event is sent, and the answer is the same 204. The body must be JSON: a form-encoded body fails with 400 before it is read. Internal.","operationId":"record-form-update-for-sift","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSiftRequest"}}}},"responses":{"204":{"description":"The event was sent, or the feature flag is off and nothing was sent. No body."},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status.","type":"string","example":"400"},"detail":{"description":"What went wrong. One of: \"Request body is empty.\", \"Could not decode request body.\", or a message that the JSON did not decode to an array.","type":"string","example":"Could not decode request body."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Could not decode request body."}]}}}},"422":{"description":"`id` or `form` is missing, `id` is blank, or a field has the wrong JSON type (for example a number for `id`, or a string for `form`).","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What went wrong. One of: \"Form ID must not be blank.\", \"Form data must not be null.\", \"Unexpected type\".","type":"string","example":"Form ID must not be blank."},"source":{"description":"Which field failed.","properties":{"pointer":{"description":"`/data/attributes/` followed by the field name.","type":"string","example":"/data/attributes/id"}},"type":"object"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Form ID must not be blank.","source":{"pointer":"/data/attributes/id"}}]}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/form/sitescreenshot":{"get":{"summary":"Retrieve a site preview screenshot URL","description":"Builds a signed URL2PNG URL that renders a page of the customer's site, full page at a `w` by `h` viewport, to preview the form over it. `excludeform=1` is appended to the page `url`, which stops the form embed script on that page from drawing the form into the render. Hosted only builds and signs the URL; URL2PNG renders the page when the URL is fetched. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses. Internal: backs the site preview in the form builder.","operationId":"retrieve-form-site-preview-url","x-canonical-resource":"forms","parameters":[{"name":"id","in":"query","description":"ID of the form. It is only checked to exist; the URL does not depend on it.","required":true,"schema":{"type":"integer"},"example":12},{"name":"url","in":"query","description":"URL of the site page to render behind the form.","required":false,"schema":{"type":"string"},"example":"https://example.com/pricing"},{"name":"w","in":"query","description":"Viewport width in pixels.","required":false,"schema":{"type":"integer"},"example":1024},{"name":"h","in":"query","description":"Viewport height in pixels.","required":false,"schema":{"type":"integer"},"example":768}],"responses":{"200":{"description":"The screenshot URL. When `id` is missing or 0, or no form has it, the body is empty. The script writes JSON without setting a Content-Type header.","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"URL2PNG URL of the rendered page: `https://api.url2png.com/v6/<api key>/<token>/png/?url=<page url with excludeform=1, URL-encoded>&viewport=<w>x<h>&fullpage=true`."}}}}}}},"deprecated":false,"x-internal":true}},"/form/switchtohtml":{"post":{"summary":"Convert a campaign's designer message to HTML","description":"Converts the message of a campaign built in the legacy campaign designer into a plain HTML message: renders the designer content to HTML, sanitises it, saves it as the message's HTML, deletes the designer instance, and detaches the campaign from its base template. It cannot be undone through the API. Despite the path, it acts on a campaign, not a form. Send `id` in the query string or as a form field in a form-encoded body; a JSON body is not read. Failures answer 200 with `success: 0`. Legacy endpoint with no method guard: any HTTP method converts the same way; POST is documented and is what the designer sends. Internal: backs Switch to HTML in the campaign designer's settings.","operationId":"convert-campaign-designer-message-to-html","x-canonical-resource":"campaign","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"query","description":"ID of the campaign. May be sent as a form field instead.","required":false,"schema":{"type":"integer"},"example":88}],"requestBody":{"description":"`id` as a form field, when it is not in the query string.","required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the campaign.","example":88}}}}}},"responses":{"200":{"description":"`{\"success\": 1}` when the message was converted. `{\"success\": 0, \"message\": ...}` when it was not; the message, in the user's language, is one of \"Campaign id not given.\", \"Campaign does not exist.\", \"Campaign has no message.\", \"Could not retrieve instance.\". The script writes JSON without setting a Content-Type header.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"integer","enum":[0,1],"description":"1: converted. 0: not converted; see `message`."},"message":{"type":"string","description":"Why the conversion did not happen. Present only when `success` is 0."}}},"example":{"success":1}}}}},"deprecated":false,"x-internal":true}},"/formLabels":{"post":{"summary":"Create a form label","description":"Puts a label on a form by creating the association between them. Send the form and label IDs in a formLabel object. The label must exist and must not be an archived initiative, and the form must exist. When the form already has the label, nothing is created and the call answers 200 with a message instead of the association. To label several forms at once, use POST /formLabels/bulkCreate. Internal: backs putting a form in a label or an initiative in the app.","operationId":"create-a-form-label","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["formLabel"],"properties":{"formLabel":{"required":["form","label"],"properties":{"form":{"description":"ID of the form to label, a number or a numeric string","type":["integer","string"],"example":3},"label":{"description":"ID of the label to put on the form, a number or a numeric string","type":["integer","string"],"example":7}},"type":"object"}},"type":"object"},"examples":{"Request Example":{"summary":"Label form 3 with label 7","value":{"formLabel":{"form":3,"label":7}}}}}}},"responses":{"200":{"description":"The form already has this label. Nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the form and label IDs that are already associated","type":"string","example":"FormFolder with form id 3 and folder id 7 already exists"}},"type":"object"}}}},"201":{"description":"The association was created. formLabel holds it with the form and label as sent; the timestamps are not read back.","content":{"application/json":{"schema":{"properties":{"formLabel":{"$ref":"#/components/schemas/FormLabel"}},"type":"object"},"example":{"formLabel":{"form":3,"label":7,"links":{"labels":"https://:account.api-us1.com/api/3/formLabels/12/labels","forms":"https://:account.api-us1.com/api/3/formLabels/12/forms"},"id":"12"}}}}},"400":{"description":"The body is not a JSON object, has no formLabel object, or formLabel lacks a numeric form or label.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What went wrong. One of: \"A form label must be provided\", \"A form id must be provided\", \"A folder or label id must be provided\", or \"Request body must be a JSON object, array given.\"","type":"string","example":"A form id must be provided"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"A form id must be provided"}]}}}},"403":{"description":"The label is an archived initiative, which cannot take new forms.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 7 is archived and cannot have forms associated with it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 7 is archived and cannot have forms associated with it."}]}}}},"404":{"description":"The label or the form does not exist. The label is checked first.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing record: Folder for the label, Form for the form","type":"string","example":"No Result found for Form with id 3"}},"type":"object"}}}}},"x-canonical-resource":"form_label","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"List form labels","description":"Lists the associations between forms and labels, in pages of 20 by default. Each one says which label a form carries; the label itself is read with GET /labels/{id}. Filters and ordering are not supported: filters[...] and orders[...] parameters are ignored. Internal: backs the app's form label and initiative views.","operationId":"list-form-labels","x-canonical-resource":"form_label","parameters":[{"name":"limit","in":"query","description":"Number of associations to return, 20 when left out and at most 100. The value null returns up to 1,000. Ignored when ids is given.","schema":{"type":["integer","string"]},"example":20},{"name":"offset","in":"query","description":"Number of associations to skip before the first one returned.","schema":{"type":"integer","default":0},"example":0},{"name":"ids","in":"query","description":"Return only these associations: their IDs, separated by commas. The page size becomes the number of IDs given.","schema":{"type":"string"},"example":"12,13"},{"name":"include_folder","in":"query","description":"1 adds the label's name (title) and colour (color) to each association, and leaves out associations whose label no longer exists.","schema":{"type":"integer","enum":[0,1]},"example":1},{"name":"include","in":"query","description":"Related records to return beside the associations, separated by commas: labels adds the labels under labels, forms adds the forms under forms.","schema":{"type":"string"},"example":"labels"}],"responses":{"200":{"description":"A page of associations. formLabels is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","required":["formLabels","meta"],"properties":{"formLabels":{"type":"array","description":"The associations on this page","items":{"$ref":"#/components/schemas/FormLabel"}},"labels":{"type":"array","description":"The labels the associations point to. Present only with include=labels.","items":{"type":"object"}},"forms":{"type":"array","description":"The forms the associations point to, as stored. Present only with include=forms.","items":{"type":"object"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Number of associations that match, across all pages","example":4}}}}},"example":{"formLabels":[{"form":"3","label":"7","created_timestamp":"2026-09-23 15:37:14","updated_timestamp":"2026-09-23 15:37:14","created_by":"1","updated_by":"1","links":{"labels":"https://:account.api-us1.com/api/3/formLabels/12/labels","forms":"https://:account.api-us1.com/api/3/formLabels/12/forms"},"id":"12"}],"meta":{"total":1}}}}}},"deprecated":false,"x-internal":true}},"/formLabels/bulkCreate":{"post":{"summary":"Create form labels in bulk","description":"Puts labels on forms in one call. The body is a JSON array of form and label ID pairs, not wrapped in a key. Every label named in the request is checked first: when one does not exist the call answers 404, and when one is an archived initiative it answers 403; either way nothing is created. Then each pair is checked on its own. A pair without a numeric form or label is left out and reported in errors with its position in the array. Repeated pairs are created once. A pair whose form or label does not exist, or whose form already has the label, is skipped without being reported. The rest are created together. Internal: backs putting several forms in a label or an initiative at once in the app.","operationId":"bulk-create-form-labels","requestBody":{"description":"The form and label pairs to create, as a JSON array","required":true,"content":{"application/json":{"schema":{"type":"array","items":{"required":["form","label"],"properties":{"form":{"description":"ID of the form to label, a number or a numeric string","type":["integer","string"],"example":3},"label":{"description":"ID of the label to put on the form, a number or a numeric string","type":["integer","string"],"example":7}},"type":"object"}},"examples":{"Request Example":{"summary":"Label two forms with label 7","value":[{"form":3,"label":7},{"form":4,"label":7}]}}}}},"responses":{"200":{"description":"Nothing was created: the array was empty, or no pair was left to create.","content":{"application/json":{"schema":{"required":["message","meta"],"properties":{"message":{"description":"\"No data provided\" for an empty or missing array, otherwise \"No valid labels provided\"","type":"string","example":"No valid labels provided"},"errors":{"description":"The pairs left out for a missing or non-numeric form or label, as on the 201 response. Absent when the array was empty.","type":"array","items":{"properties":{"index":{"description":"Position of the pair in the request array, from 0","type":"integer","example":0},"error":{"description":"Why the pair was left out","type":"string","example":"A folder or label id must be provided"}},"type":"object"}},"meta":{"properties":{"success":{"description":"False when any pair was reported in errors, otherwise true","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}},"201":{"description":"At least one association was created.","content":{"application/json":{"schema":{"required":["message","added","errors","meta"],"properties":{"message":{"description":"Always \"Labels created successfully\"","type":"string","example":"Labels created successfully"},"added":{"description":"Number of associations created","type":"integer","example":2},"errors":{"description":"The pairs left out for a missing or non-numeric form or label; empty when none were","type":"array","items":{"properties":{"index":{"description":"Position of the pair in the request array, from 0","type":"integer","example":1},"error":{"description":"Why the pair was left out: \"A form id must be provided\" or \"A folder or label id must be provided\"","type":"string","example":"A form id must be provided"}},"type":"object"}},"meta":{"properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"message":"Labels created successfully","added":2,"errors":[],"meta":{"success":true}}}}},"403":{"description":"A label in the request is an archived initiative. Nothing was created.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 7 is archived and cannot have forms associated with it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 7 is archived and cannot have forms associated with it."}]}}}},"404":{"description":"A label in the request does not exist. Nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing label","type":"string","example":"No Result found for Folder with id 7"}},"type":"object"}}}},"500":{"description":"Saving the associations failed. Nothing was created.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Error creating labels - unable to insert new labels in rel table\"","type":"string","example":"Error creating labels - unable to insert new labels in rel table"},"errors":{"description":"The pairs left out before saving, as on the 201 response","type":"array","items":{"type":"object"}},"meta":{"properties":{"success":{"description":"Always false","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"form_label","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/formLabels/bulkDelete":{"delete":{"summary":"Delete form labels in bulk","description":"Takes labels off forms by deleting the associations named in ids. The forms and labels themselves are not deleted. Every association is checked before any is deleted: when one does not exist the call answers 404, and when one has an archived initiative as its label it answers 403; either way nothing is deleted. Without ids the call deletes nothing and answers 200. Internal: backs taking several forms out of a label or an initiative at once in the app.","operationId":"bulk-delete-form-labels","parameters":[{"name":"ids","in":"query","description":"IDs of the associations to delete, separated by commas, as returned by GET /formLabels. They are not label IDs. Send one comma-separated value: ids[] is not accepted.","required":false,"schema":{"type":"string"},"example":"12,13"}],"responses":{"200":{"description":"The associations were deleted, or ids was empty and nothing was.","content":{"application/json":{"schema":{"required":["message","meta"],"properties":{"message":{"description":"\"Labels deleted successfully\", or \"Nothing to delete\" when ids was empty","type":"string","example":"Labels deleted successfully"},"meta":{"properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}},"type":"object"}}}},"403":{"description":"An association in ids has an archived initiative as its label. Nothing was deleted.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 7 is archived and cannot have forms removed from it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 7 is archived and cannot have forms removed from it."}]}}}},"404":{"description":"An association in ids does not exist, or its label no longer exists. Nothing was deleted.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing record","type":"string","example":"No Result found for FormFolder with id 13"}},"type":"object"}}}},"500":{"description":"Deleting the associations failed.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed","type":"string","example":"Error deleting labels - unable to delete labels from rel table"},"meta":{"properties":{"success":{"description":"Always false","type":"boolean","example":false}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"form_label","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/formLabels/{id}":{"delete":{"summary":"Delete a form label","description":"Takes a label off a form by deleting their association. The form and the label themselves are not deleted. An association whose label is an archived initiative cannot be deleted. To delete several at once, use DELETE /formLabels/bulkDelete. Internal: backs taking a form out of a label or an initiative in the app.","operationId":"delete-a-form-label","parameters":[{"name":"id","in":"path","description":"ID of the association, as returned by GET /formLabels. It is not the label ID.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The association was deleted. The body is an empty object.","content":{"application/json":{"schema":{"description":"Empty object","type":"object"},"example":{}}}},"403":{"description":"The label is an archived initiative, whose forms cannot be removed.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status","type":"integer","example":403},"title":{"description":"Short name of the HTTP status","type":"string","example":"Forbidden"},"detail":{"description":"Names the archived initiative","type":"string","example":"Initiative with id 7 is archived and cannot have forms removed from it."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Initiative with id 7 is archived and cannot have forms removed from it."}]}}}},"404":{"description":"No association has this ID, or its label no longer exists.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing record: FormFolder for the association, Folder for its label","type":"string","example":"No Result found for FormFolder with id 12"}},"type":"object"}}}}},"x-canonical-resource":"form_label","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"get":{"summary":"Retrieve a form label","description":"Reads one association between a form and a label by its ID. Internal: backs the app's form label views.","operationId":"retrieve-a-form-label","x-canonical-resource":"form_label","parameters":[{"name":"id","in":"path","required":true,"description":"ID of the association, as returned by GET /formLabels. It is not the label ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The association","content":{"application/json":{"schema":{"type":"object","required":["formLabel"],"properties":{"formLabel":{"$ref":"#/components/schemas/FormLabel"}}},"example":{"formLabel":{"form":"3","label":"7","created_timestamp":"2026-09-23 15:37:14","updated_timestamp":"2026-09-23 15:37:14","created_by":"1","updated_by":"1","links":{"labels":"https://:account.api-us1.com/api/3/formLabels/12/labels","forms":"https://:account.api-us1.com/api/3/formLabels/12/forms"},"id":"12"}}}}},"404":{"description":"No association has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the missing association","example":"No Result found for FormFolder with id 12"}}}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update a form label","description":"Internal. Moves an association to another form or another label, in place. PATCH /formLabels/{id} does the same thing. Unlike POST /formLabels, nothing is checked: not that the form or the label exists, not that the label is an archived initiative, and not that the form already has the label. Only form and label (or their column names, formid and folderid) can change; fields left out keep their current value, and any other key in formLabel is ignored. To change which labels a form carries, delete the association with DELETE /formLabels/{id} and create one with POST /formLabels instead.","operationId":"update-a-form-label","x-canonical-resource":"form_label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the association, as returned by GET /formLabels. It is not the label ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"formLabel":{"type":"object","description":"The fields to change. Fields left out keep their current value.","properties":{"form":{"type":["integer","string"],"description":"ID of the form to move the association to. Not checked.","example":4},"label":{"type":["integer","string"],"description":"ID of the label to point the association at. Not checked.","example":7}}}}},"examples":{"Request Example":{"value":{"formLabel":{"form":4}}}}}}},"responses":{"200":{"description":"The association with the change applied. Values sent in the body are echoed as sent; the rest are as stored.","content":{"application/json":{"schema":{"type":"object","required":["formLabel"],"properties":{"formLabel":{"$ref":"#/components/schemas/FormLabel"}}},"example":{"formLabel":{"form":4,"label":"7","created_timestamp":"2026-09-23 15:37:14","updated_timestamp":"2026-09-23 15:37:14","created_by":"1","updated_by":"1","links":{"labels":"https://:account.api-us1.com/api/3/formLabels/12/labels","forms":"https://:account.api-us1.com/api/3/formLabels/12/forms"},"id":"12"}}}}},"400":{"description":"The body is JSON but not an object, such as an array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry per error. This request fails with a single error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"Names the JSON type that was sent","example":"Request body must be a JSON object, array given."}}}}}}}}},"404":{"description":"No association has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the missing association","example":"No Result found for FormFolder with id 12"}}}}}}},"deprecated":false,"x-internal":true},"patch":{"summary":"Patch a form label","description":"Internal. Moves an association to another form or another label, in place. PUT /formLabels/{id} does the same thing. Unlike POST /formLabels, nothing is checked: not that the form or the label exists, not that the label is an archived initiative, and not that the form already has the label. Only form and label (or their column names, formid and folderid) can change; fields left out keep their current value, and any other key in formLabel is ignored. To change which labels a form carries, delete the association with DELETE /formLabels/{id} and create one with POST /formLabels instead.","operationId":"patch-a-form-label","x-canonical-resource":"form_label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the association, as returned by GET /formLabels. It is not the label ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"formLabel":{"type":"object","description":"The fields to change. Fields left out keep their current value.","properties":{"form":{"type":["integer","string"],"description":"ID of the form to move the association to. Not checked.","example":4},"label":{"type":["integer","string"],"description":"ID of the label to point the association at. Not checked.","example":7}}}}},"examples":{"Request Example":{"value":{"formLabel":{"form":4}}}}}}},"responses":{"200":{"description":"The association with the change applied. Values sent in the body are echoed as sent; the rest are as stored.","content":{"application/json":{"schema":{"type":"object","required":["formLabel"],"properties":{"formLabel":{"$ref":"#/components/schemas/FormLabel"}}},"example":{"formLabel":{"form":4,"label":"7","created_timestamp":"2026-09-23 15:37:14","updated_timestamp":"2026-09-23 15:37:14","created_by":"1","updated_by":"1","links":{"labels":"https://:account.api-us1.com/api/3/formLabels/12/labels","forms":"https://:account.api-us1.com/api/3/formLabels/12/forms"},"id":"12"}}}}},"400":{"description":"The body is JSON but not an object, such as an array.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry per error. This request fails with a single error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"HTTP status code, the same as the response status","example":400},"title":{"type":"string","description":"Short name of the HTTP status","example":"Bad Request"},"detail":{"type":"string","description":"Names the JSON type that was sent","example":"Request body must be a JSON object, array given."}}}}}}}}},"404":{"description":"No association has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the missing association","example":"No Result found for FormFolder with id 12"}}}}}}},"deprecated":false,"x-internal":true}},"/forms":{"get":{"summary":"List all forms","description":"List the account's forms with their settings, fields and actions. Each form's `public_url` is its public link and `embed_code` is the snippet to place it on a website. `url` is the builder's preview website, not the public link.","operationId":"forms-1","x-canonical-resource":"forms","parameters":[{"name":"limit","in":"query","description":"Number of forms to return. Defaults to 20, and values above 100 are reduced to 100.","schema":{"type":"integer","format":"int32","default":20,"maximum":100}},{"name":"offset","in":"query","description":"Number of forms to skip, for paging.","schema":{"type":"integer","format":"int32","default":0}},{"name":"ids","in":"query","description":"Return only these forms. One id, or several separated by commas. Supersedes `limit`, which becomes the number of ids given.","schema":{"type":"string"},"example":"12,15"},{"name":"search","in":"query","description":"Return only forms whose name contains this text.","schema":{"type":"string"}},{"name":"layout[]","in":"query","description":"Return only forms with these layouts, sent as `layout[]=<layout>` once per layout. A single `layout=<layout>` works too.","schema":{"type":"array","items":{"type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"]}},"example":["inline-form","modal"]},{"name":"label","in":"query","description":"Return only forms in this folder (form label), by its id. `-1` returns forms in no folder; `0` returns every form, as leaving it out does.","schema":{"type":"integer","format":"int32"}},{"name":"filter","in":"query","description":"Return only forms with an action of this type.","schema":{"type":"string","enum":["subscribe-to-list","subscribe-to-sms-list","add-a-tag","add-to-deal","email-results","manage-preferences"]}},{"name":"branding","in":"query","description":"`true` lists only forms that show the ActiveCampaign branding badge (`style.ac_branding`), `false` only forms that don't, including forms that never set it. Left out or empty: every form. Any other value returns `422`.","required":false,"schema":{"type":"boolean"}},{"name":"sort","in":"query","description":"Order of the forms, by name A to Z when left out or not one of these: `name` or `nameD` by name, `layout` or `layoutD` by layout, `entries` or `entriesD` by number of submissions, `cdateA` or `cdateD` by created date. The values ending in D sort descending. Forms that tie are ordered newest id first.","schema":{"type":"string","enum":["name","nameD","layout","layoutD","entries","entriesD","cdateA","cdateD"],"default":"name"}},{"name":"include_folder","in":"query","description":"`1` adds each form's folders (form labels) to it as `labelsData`. Any other value leaves them out.","schema":{"type":"integer","enum":[1]}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"forms\": [\n        {\n            \"name\": \"Testing\",\n            \"action\": \"\",\n            \"actiondata\": {\n                \"actions\": [\n                    {\n                        \"type\": \"subscribe-to-list\",\n                        \"email\": \"johndoe@example.com\",\n                        \"list\": \"1\"\n                    }\n                ]\n            },\n            \"submit\": \"show-thank-you\",\n            \"submitdata\": {\n                \"url\": \"\"\n            },\n            \"url\": \"\",\n            \"layout\": \"inline-form\",\n            \"title\": \"\",\n            \"body\": \"\",\n            \"button\": \"Submit\",\n            \"thanks\": \"Thanks for signing up!\",\n            \"style\": {\n                \"background\": \"FFFFFF\",\n                \"dark\": true,\n                \"fontcolor\": \"000000\",\n                \"layout\": \"normal\",\n                \"border\": {\n                    \"width\": 0,\n                    \"style\": \"solid\",\n                    \"color\": \"B0B0B0\",\n                    \"radius\": 0\n                },\n                \"width\": 500,\n                \"ac_branding\": true,\n                \"button\": {\n                    \"padding\": 10,\n                    \"background\": \"333333\",\n                    \"fontcolor\": \"FFFFFF\",\n                    \"border\": {\n                        \"radius\": 4,\n                        \"color\": \"333333\",\n                        \"style\": \"solid\",\n                        \"width\": 0\n                    }\n                }\n            },\n            \"options\": {\n                \"blanks_overwrite\": true,\n                \"confaction\": \"show-message\",\n                \"sendoptin\": true,\n                \"optin_id\": 1,\n                \"optin_created\": true,\n                \"confform\": \"2\"\n            },\n            \"cfields\": [\n                {\n                    \"type\": \"header\",\n                    \"header\": \"Subscribe for Email Updates\",\n                    \"class\": \"_x41699710\"\n                },\n                {\n                    \"type\": \"html\",\n                    \"html\": \"<p>Add a descriptive message telling what your visitor is signing up for here.</p>\",\n                    \"class\": \"_x50329289\"\n                },\n                {\n                    \"header\": \"Full Name\",\n                    \"type\": \"fullname\",\n                    \"default_text\": \"Type your name\",\n                    \"class\": \"_x67999677\"\n                },\n                {\n                    \"header\": \"Email\",\n                    \"type\": \"email\",\n                    \"default_text\": \"Type your email\",\n                    \"required\": true,\n                    \"class\": \"_x68140262\"\n                }\n            ],\n            \"parentformid\": \"0\",\n            \"userid\": \"1\",\n            \"addressid\": \"0\",\n            \"cdate\": \"2018-08-17T13:47:31-05:00\",\n            \"udate\": \"2018-08-17T13:47:38-05:00\",\n            \"entries\": \"0\",\n            \"aid\": \"0\",\n            \"defaultscreenshot\": \"http://img-us1.com/default-form.gif\",\n            \"recent\": [],\n            \"contacts\": 0,\n            \"deals\": 0,\n            \"links\": {\n                \"address\": \"https://:account.api-us1.com/api/3/forms/1/address\"\n            },\n            \"id\": \"1\",\n            \"address\": null\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"forms":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Testing"},"action":{"type":"string","example":""},"actiondata":{"type":"object","properties":{"actions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"subscribe-to-list"},"email":{"type":"string","example":"johndoe@example.com"},"list":{"type":"string","example":"1"}}}}}},"submit":{"type":"string","example":"show-thank-you"},"submitdata":{"type":"object","properties":{"url":{"type":"string","example":"","description":"Address the contact is redirected to after submitting, used when `submit` is `open-url`. It is not the form's public link."}}},"url":{"type":"string","example":"","description":"Website URL the form builder shows behind the form as a preview background. It is not the form's public link (see `public_url`) and is often empty."},"public_url":{"type":"string","example":"https://example.activehosted.com/f/1","description":"The form's public link, on the account's custom domain when one is set. Read-only."},"embed_code":{"type":"string","example":"<div class=\"_form_1\"></div><script src=\"https://example.activehosted.com/f/embed.php?id=1\" charset=\"utf-8\"></script>","description":"HTML snippet that places the form on a website. Inline and preference-center forms render into the `<div>` placeholder; other layouts load from the script alone. Show it as text to copy, do not render it. Read-only."},"layout":{"type":"string","example":"inline-form"},"title":{"type":"string","example":""},"body":{"type":"string","example":""},"button":{"type":"string","example":"Submit"},"thanks":{"type":"string","example":"Thanks for signing up!"},"style":{"type":"object","properties":{"background":{"type":"string","example":"FFFFFF"},"dark":{"type":"boolean","example":true,"default":true},"fontcolor":{"type":"string","example":"000000"},"layout":{"type":"string","example":"normal"},"border":{"type":"object","properties":{"width":{"type":"integer","example":0,"default":0},"style":{"type":"string","example":"solid"},"color":{"type":"string","example":"B0B0B0"},"radius":{"type":"integer","example":0,"default":0}}},"width":{"type":"integer","example":500,"default":0},"ac_branding":{"type":"boolean","example":true,"default":true},"button":{"type":"object","properties":{"padding":{"type":"integer","example":10,"default":0},"background":{"type":"string","example":"333333"},"fontcolor":{"type":"string","example":"FFFFFF"},"border":{"type":"object","properties":{"radius":{"type":"integer","example":4,"default":0},"color":{"type":"string","example":"333333"},"style":{"type":"string","example":"solid"},"width":{"type":"integer","example":0,"default":0}}}}}}},"options":{"type":"object","properties":{"blanks_overwrite":{"type":"boolean","example":true,"default":true},"confaction":{"type":"string","example":"show-message"},"sendoptin":{"type":"boolean","example":true,"default":true},"optin_id":{"type":"integer","example":1,"default":0},"optin_created":{"type":"boolean","example":true,"default":true},"confform":{"type":"string","example":"2"}}},"cfields":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"header"},"header":{"type":"string","example":"Subscribe for Email Updates"},"class":{"type":"string","example":"_x41699710"}}}},"parentformid":{"type":"string","example":"0"},"userid":{"type":"string","example":"1"},"addressid":{"type":"string","example":"0"},"cdate":{"type":"string","example":"2018-08-17T13:47:31-05:00"},"udate":{"type":"string","example":"2018-08-17T13:47:38-05:00"},"entries":{"type":"string","example":"0"},"aid":{"type":"string","example":"0"},"defaultscreenshot":{"type":"string","example":"http://img-us1.com/default-form.gif"},"recent":{"type":"array"},"contacts":{"type":"integer","example":0,"default":0},"deals":{"type":"integer","example":0,"default":0},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/forms/1/address"}}},"id":{"type":"string","example":"1"},"address":{}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Not a boolean":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"branding must be true or false\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/branding\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422},"title":{"type":"string","example":"Invalid attribute"},"detail":{"type":"string","example":"branding must be true or false"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/branding"}}}}}}}}}}}},"deprecated":false},"post":{"description":"Creates a new form from the body. Requires the permission to edit forms.","summary":"Create a form","operationId":"post_forms","x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"requestBody":{"description":"The form to create, in a form object","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it. The keys saved are name, action, actiondata, submit, submitdata, url, layout, title, body, button, thanks, style, options, cfields, parentformid, addressid and source; any other key is ignored. options.paused is ignored: a new form always starts active.","properties":{"name":{"description":"Name of the form. HTML in it is filtered out.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown. Layouts other than inline-form, ipad and chat need a plan with modal forms, and preference-center needs a plan with Preference Centers; an account has at most 20 Preference Center forms. When the account already has a chat form, a chat layout returns that form instead of creating one.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"}},"type":"object"}},"type":"object"},"examples":{"Your New Form":{"summary":"Your New Form","value":{"form":{"name":"Your New Form","layout":"inline-form"}}}}}}},"responses":{"200":{"description":"The layout is chat and the account already has a chat form. Nothing was created; form is the existing chat form.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"201":{"description":"The form was created.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"},"examples":{"Your New Form":{"summary":"Your New Form","value":"{\n    \"form\": {\n        \"name\": \"Your New Form\",\n        \"action\": \"\",\n        \"actiondata\": {\n            \"actions\": [\n                {\n                    \"type\": \"email-results\",\n                    \"email\": \"johndoe@example.com\",\n                    \"fromname\": \"John Doe\",\n                    \"fromemail\": \"johndoe@example.com\",\n                    \"subject\": \"Form submission results\"\n                }\n            ]\n        },\n        \"submit\": \"show-thank-you\",\n        \"submitdata\": {\n            \"url\": \"\"\n        },\n        \"url\": \"\",\n        \"layout\": \"inline-form\",\n        \"title\": \"\",\n        \"body\": \"\",\n        \"button\": \"Submit\",\n        \"thanks\": \"Thanks for signing up!\",\n        \"style\": {\n            \"background\": \"FFFFFF\",\n            \"dark\": true,\n            \"fontcolor\": \"000000\",\n            \"layout\": \"normal\",\n            \"border\": {\n                \"width\": 0,\n                \"style\": \"solid\",\n                \"color\": \"B0B0B0\",\n                \"radius\": 0\n            },\n            \"width\": 500,\n            \"ac_branding\": true,\n            \"button\": {\n                \"padding\": 10,\n                \"background\": \"333333\",\n                \"fontcolor\": \"FFFFFF\",\n                \"border\": {\n                    \"radius\": 4,\n                    \"color\": \"333333\",\n                    \"style\": \"solid\",\n                    \"width\": 0\n                }\n            },\n            \"customcss\": \"\"\n        },\n        \"options\": {\n            \"blanks_overwrite\": true,\n            \"confaction\": \"show-message\"\n        },\n        \"cfields\": [\n            {\n                \"type\": \"header\",\n                \"header\": \"Contact Us\",\n                \"class\": \"_x29498744\",\n                \"required_options\": {}\n            },\n            {\n                \"type\": \"html\",\n                \"html\": \"<p>Please provide the information below and we'll be in touch soon.</p>\",\n                \"class\": \"_x14271862\",\n                \"required_options\": {}\n            },\n            {\n                \"header\": \"Full Name\",\n                \"type\": \"fullname\",\n                \"default_text\": \"\",\n                \"class\": \"_x13100531\",\n                \"required_options\": {},\n                \"required\": true\n            },\n            {\n                \"header\": \"Email\",\n                \"type\": \"email\",\n                \"default_text\": \"\",\n                \"required\": true,\n                \"class\": \"_x37378733\",\n                \"required_options\": {}\n            },\n            {\n                \"type\": \"organization\",\n                \"header\": \"Company\",\n                \"default_text\": \"\",\n                \"class\": \"_x16906569\",\n                \"required_options\": {},\n                \"required\": false\n            },\n            {\n                \"id\": \"13\",\n                \"header\": \"Role in Company\",\n                \"required\": true,\n                \"class\": \"_field13\",\n                \"required_options\": {}\n            },\n            {\n                \"id\": \"46\",\n                \"header\": \"What do you need help with?\",\n                \"required\": true,\n                \"class\": \"_field46\",\n                \"required_options\": {}\n            }\n        ],\n        \"parentformid\": \"0\",\n        \"userid\": \"1\",\n        \"addressid\": \"0\",\n        \"cdate\": \"2018-10-07T09:12:46-06:00\",\n        \"udate\": \"2018-10-12T11:18:52-06:00\",\n        \"entries\": \"0\",\n        \"aid\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/forms/13/address\"\n        },\n        \"id\": \"13\",\n        \"address\": null\n    }\n}"}}}}},"403":{"description":"The user may not edit forms, or the form is a Preference Center and the account already has 20.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string for the missing permission, a number for the Preference Center limit","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent with the Preference Center limit only.","type":"string","example":"Forbidden"},"detail":{"description":"\"Forbidden\" when the user may not edit forms, or \"You have reached your limit of 20 Preference Centers\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"The layout is not on the account's plan, or an option is invalid: options.blocked_email_domains, options.block_personal_email_providers, the paused message and link options, or the SMS confirmation messages.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per invalid field","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422. Absent when the layout is refused.","type":"integer","example":422},"title":{"description":"Short name of the HTTP status, or the reason when the layout is refused","type":"string","example":"Unprocessable Entity"},"detail":{"description":"What is wrong with the field. Empty when the layout is refused.","type":"string","example":"Each blocked email domain must be a valid domain, such as example.com or *.example.com."},"code":{"description":"Error code. Sent only when the layout is refused.","type":"string","example":"field_invalid"},"source":{"description":"The field at fault","properties":{"pointer":{"description":"The field, as /data/attributes/ followed by its name: layout, or the key in options","type":"string","example":"/data/attributes/blocked_email_domains"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"parameters":[]}},"/forms/duplicate":{"post":{"summary":"Create a form (duplicate path)","description":"Creates a new form from the body, exactly as POST /forms does. Despite the path, nothing is copied: no existing form is read. The route keeps a URL working that the earlier API v3 dispatcher answered as a create. To copy a form, use POST /form/duplicate with the ID of the form to copy. Requires the permission to edit forms.","operationId":"create-a-form-via-duplicate-path","requestBody":{"description":"The form to create, in a form object","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it. The keys saved are name, action, actiondata, submit, submitdata, url, layout, title, body, button, thanks, style, options, cfields, parentformid, addressid and source; any other key is ignored. options.paused is ignored: a new form always starts active.","properties":{"name":{"description":"Name of the form. HTML in it is filtered out.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown. Layouts other than inline-form, ipad and chat need a plan with modal forms, and preference-center needs a plan with Preference Centers; an account has at most 20 Preference Center forms. When the account already has a chat form, a chat layout returns that form instead of creating one.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"}},"type":"object"}},"type":"object"},"examples":{"Request Example":{"summary":"A minimal inline form","value":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}}}}},"responses":{"200":{"description":"The layout is chat and the account already has a chat form. Nothing was created; form is the existing chat form.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"201":{"description":"The form was created.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or the form is a Preference Center and the account already has 20.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string for the missing permission, a number for the Preference Center limit","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent with the Preference Center limit only.","type":"string","example":"Forbidden"},"detail":{"description":"\"Forbidden\" when the user may not edit forms, or \"You have reached your limit of 20 Preference Centers\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"The layout is not on the account's plan, or an option is invalid: options.blocked_email_domains, options.block_personal_email_providers, the paused message and link options, or the SMS confirmation messages.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per invalid field","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422. Absent when the layout is refused.","type":"integer","example":422},"title":{"description":"Short name of the HTTP status, or the reason when the layout is refused","type":"string","example":"Unprocessable Entity"},"detail":{"description":"What is wrong with the field. Empty when the layout is refused.","type":"string","example":"Each blocked email domain must be a valid domain, such as example.com or *.example.com."},"code":{"description":"Error code. Sent only when the layout is refused.","type":"string","example":"field_invalid"},"source":{"description":"The field at fault","properties":{"pointer":{"description":"The field, as /data/attributes/ followed by its name: layout, or the key in options","type":"string","example":"/data/attributes/blocked_email_domains"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/forms/duplicate/{id}":{"post":{"summary":"Create a form (duplicate path with an ID)","description":"Creates a new form from the body, exactly as POST /forms does. Despite the path, nothing is copied: the ID in the path is not read. The route keeps a URL working that the earlier API v3 dispatcher answered as a create. To copy a form, use POST /form/duplicate with the ID of the form to copy. Requires the permission to edit forms.","operationId":"create-a-form-via-duplicate-path-with-id","parameters":[{"name":"id","in":"path","description":"Not used: the form is created from the body alone, whatever ID is here.","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"The form to create, in a form object","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it. The keys saved are name, action, actiondata, submit, submitdata, url, layout, title, body, button, thanks, style, options, cfields, parentformid, addressid and source; any other key is ignored. options.paused is ignored: a new form always starts active.","properties":{"name":{"description":"Name of the form. HTML in it is filtered out.","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown. Layouts other than inline-form, ipad and chat need a plan with modal forms, and preference-center needs a plan with Preference Centers; an account has at most 20 Preference Center forms. When the account already has a chat form, a chat layout returns that form instead of creating one.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"}},"type":"object"}},"type":"object"},"examples":{"Request Example":{"summary":"A minimal inline form","value":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}}}}},"responses":{"200":{"description":"The layout is chat and the account already has a chat form. Nothing was created; form is the existing chat form.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"201":{"description":"The form was created.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or the form is a Preference Center and the account already has 20.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string for the missing permission, a number for the Preference Center limit","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent with the Preference Center limit only.","type":"string","example":"Forbidden"},"detail":{"description":"\"Forbidden\" when the user may not edit forms, or \"You have reached your limit of 20 Preference Centers\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"The layout is not on the account's plan, or an option is invalid: options.blocked_email_domains, options.block_personal_email_providers, the paused message and link options, or the SMS confirmation messages.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per invalid field","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422. Absent when the layout is refused.","type":"integer","example":422},"title":{"description":"Short name of the HTTP status, or the reason when the layout is refused","type":"string","example":"Unprocessable Entity"},"detail":{"description":"What is wrong with the field. Empty when the layout is refused.","type":"string","example":"Each blocked email domain must be a valid domain, such as example.com or *.example.com."},"code":{"description":"Error code. Sent only when the layout is refused.","type":"string","example":"field_invalid"},"source":{"description":"The field at fault","properties":{"pointer":{"description":"The field, as /data/attributes/ followed by its name: layout, or the key in options","type":"string","example":"/data/attributes/blocked_email_domains"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}":{"get":{"summary":"Retrieve a form","description":"Retrieve a form's settings, fields and actions. `public_url` is the form's public link and `embed_code` is the snippet to place the form on a website. `url` is the builder's preview website, not the public link.","operationId":"retrieve-forms","x-canonical-resource":"forms","parameters":[{"name":"id","in":"path","description":"ID of the form to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"form\": {\n        \"name\": \"Test Form\",\n        \"action\": \"\",\n        \"actiondata\": {\n            \"actions\": [\n                {\n                    \"type\": \"email-results\",\n                    \"email\": \"johndoe@example.com\",\n                    \"fromname\": \"John Doe\",\n                    \"fromemail\": \"johndoe@example.com\",\n                    \"subject\": \"Form submission results\"\n                }\n            ]\n        },\n        \"submit\": \"show-thank-you\",\n        \"submitdata\": {\n            \"url\": \"\"\n        },\n        \"url\": \"\",\n        \"layout\": \"inline-form\",\n        \"title\": \"\",\n        \"body\": \"\",\n        \"button\": \"Submit\",\n        \"thanks\": \"Thanks for signing up!\",\n        \"style\": {\n            \"background\": \"FFFFFF\",\n            \"dark\": true,\n            \"fontcolor\": \"000000\",\n            \"layout\": \"normal\",\n            \"border\": {\n                \"width\": 0,\n                \"style\": \"solid\",\n                \"color\": \"B0B0B0\",\n                \"radius\": 0\n            },\n            \"width\": 500,\n            \"ac_branding\": true,\n            \"button\": {\n                \"padding\": 10,\n                \"background\": \"333333\",\n                \"fontcolor\": \"FFFFFF\",\n                \"border\": {\n                    \"radius\": 4,\n                    \"color\": \"333333\",\n                    \"style\": \"solid\",\n                    \"width\": 0\n                }\n            },\n            \"customcss\": \"\"\n        },\n        \"options\": {\n            \"blanks_overwrite\": true,\n            \"confaction\": \"show-message\"\n        },\n        \"cfields\": [\n            {\n                \"type\": \"header\",\n                \"header\": \"Contact Us\",\n                \"class\": \"_x29498744\",\n                \"required_options\": {}\n            },\n            {\n                \"type\": \"html\",\n                \"html\": \"<p>Please provide the information below and we'll be in touch soon.</p>\",\n                \"class\": \"_x14271862\",\n                \"required_options\": {}\n            },\n            {\n                \"header\": \"Full Name\",\n                \"type\": \"fullname\",\n                \"default_text\": \"\",\n                \"class\": \"_x13100531\",\n                \"required_options\": {},\n                \"required\": true\n            },\n            {\n                \"header\": \"Email\",\n                \"type\": \"email\",\n                \"default_text\": \"\",\n                \"required\": true,\n                \"class\": \"_x37378733\",\n                \"required_options\": {}\n            },\n            {\n                \"type\": \"organization\",\n                \"header\": \"Company\",\n                \"default_text\": \"\",\n                \"class\": \"_x16906569\",\n                \"required_options\": {},\n                \"required\": false\n            },\n            {\n                \"id\": \"13\",\n                \"header\": \"Role in Company\",\n                \"required\": true,\n                \"class\": \"_field13\",\n                \"required_options\": {}\n            },\n            {\n                \"id\": \"46\",\n                \"header\": \"What do you need help with?\",\n                \"required\": true,\n                \"class\": \"_field46\",\n                \"required_options\": {}\n            }\n        ],\n        \"parentformid\": \"0\",\n        \"userid\": \"1\",\n        \"addressid\": \"0\",\n        \"cdate\": \"2018-10-07T09:12:46-06:00\",\n        \"udate\": \"2018-10-12T11:18:52-06:00\",\n        \"entries\": \"0\",\n        \"aid\": null,\n        \"links\": {\n            \"address\": \"https://:account.api-us1.com/api/3/forms/13/address\"\n        },\n        \"id\": \"13\",\n        \"address\": null\n    }\n}"}},"schema":{"type":"object","properties":{"form":{"type":"object","properties":{"name":{"type":"string","example":"Test Form"},"action":{"type":"string","example":""},"actiondata":{"type":"object","properties":{"actions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"email-results"},"email":{"type":"string","example":"johndoe@example.com"},"fromname":{"type":"string","example":"John Doe"},"fromemail":{"type":"string","example":"johndoe@example.com"},"subject":{"type":"string","example":"Form submission results"}}}}}},"submit":{"type":"string","example":"show-thank-you"},"submitdata":{"type":"object","properties":{"url":{"type":"string","example":"","description":"Address the contact is redirected to after submitting, used when `submit` is `open-url`. It is not the form's public link."}}},"url":{"type":"string","example":"","description":"Website URL the form builder shows behind the form as a preview background. It is not the form's public link (see `public_url`) and is often empty."},"public_url":{"type":"string","example":"https://example.activehosted.com/f/1","description":"The form's public link, on the account's custom domain when one is set. Read-only."},"embed_code":{"type":"string","example":"<div class=\"_form_1\"></div><script src=\"https://example.activehosted.com/f/embed.php?id=1\" charset=\"utf-8\"></script>","description":"HTML snippet that places the form on a website. Inline and preference-center forms render into the `<div>` placeholder; other layouts load from the script alone. Show it as text to copy, do not render it. Read-only."},"layout":{"type":"string","example":"inline-form"},"title":{"type":"string","example":""},"body":{"type":"string","example":""},"button":{"type":"string","example":"Submit"},"thanks":{"type":"string","example":"Thanks for signing up!"},"style":{"type":"object","properties":{"background":{"type":"string","example":"FFFFFF"},"dark":{"type":"boolean","example":true,"default":true},"fontcolor":{"type":"string","example":"000000"},"layout":{"type":"string","example":"normal"},"border":{"type":"object","properties":{"width":{"type":"integer","example":0,"default":0},"style":{"type":"string","example":"solid"},"color":{"type":"string","example":"B0B0B0"},"radius":{"type":"integer","example":0,"default":0}}},"width":{"type":"integer","example":500,"default":0},"ac_branding":{"type":"boolean","example":true,"default":true},"button":{"type":"object","properties":{"padding":{"type":"integer","example":10,"default":0},"background":{"type":"string","example":"333333"},"fontcolor":{"type":"string","example":"FFFFFF"},"border":{"type":"object","properties":{"radius":{"type":"integer","example":4,"default":0},"color":{"type":"string","example":"333333"},"style":{"type":"string","example":"solid"},"width":{"type":"integer","example":0,"default":0}}}}},"customcss":{"type":"string","example":""}}},"options":{"type":"object","properties":{"blanks_overwrite":{"type":"boolean","example":true,"default":true},"confaction":{"type":"string","example":"show-message"}}},"cfields":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"header"},"header":{"type":"string","example":"Contact Us"},"class":{"type":"string","example":"_x29498744"},"required_options":{"type":"object","properties":{}}}}},"parentformid":{"type":"string","example":"0"},"userid":{"type":"string","example":"1"},"addressid":{"type":"string","example":"0"},"cdate":{"type":"string","example":"2018-10-07T09:12:46-06:00"},"udate":{"type":"string","example":"2018-10-12T11:18:52-06:00"},"entries":{"type":"string","example":"0"},"aid":{},"links":{"type":"object","properties":{"address":{"type":"string","example":"https://:account.api-us1.com/api/3/forms/13/address"}}},"id":{"type":"string","example":"13"},"address":{}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Form with id 7\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Form with id 7"}}}}}}},"deprecated":false},"delete":{"description":"","operationId":"delete_forms{id}","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"responses":{"200":{"description":"","content":{"application/json":{"examples":{"Form deleted":{"summary":"Form deleted","value":"{}"}}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"form id","schema":{"type":"integer"}}]},"put":{"description":"","operationId":"put_forms{id}","x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"responses":{"200":{"description":""}},"parameters":[{"name":"id","in":"path","required":true,"description":"","schema":{"type":"integer"}}]},"patch":{"summary":"Update a form (PATCH)","description":"Saves changes to a form. PUT /forms/{id} runs the same update; PATCH is not a partial update of nested objects. The body, the HTML filtering of the name, body, thank-you message and HTML fields, and the checks are the same as PUT. Saving also requests a new screenshot of the form, and when its subscribe-to-list actions change, rebuilds the list associations of the automations that start when the form is submitted. Requires the permission to edit forms. Internal: answered because the whitelist routes PATCH to the same action as PUT.","operationId":"patch-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form to update","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"The form, in a form object","required":true,"content":{"application/json":{"schema":{"required":["form"],"properties":{"form":{"description":"The form, in the shape GET /forms/{id} returns it. Keys left out keep their stored value, but actiondata, submitdata, style, options and cfields are each stored whole, so send the complete object. The keys saved are name, action, actiondata, submit, submitdata, url, layout, title, body, button, thanks, style, options, cfields, parentformid, addressid and source; any other key is ignored. options.paused keeps its stored value whatever is sent: only PUT /forms/{id}/pause and PUT /forms/{id}/resume change it.","properties":{"layout":{"description":"How the form is shown. When layout is left out, or is not inline-form, ipad or chat, and options is left out, null or not an object, the stored options are kept. Layouts other than inline-form, ipad and chat need a plan with modal forms, and preference-center needs a plan with Preference Centers.","type":"string","enum":["inline-form","floating-box","floating-bar","modal","preference-center","chat","ipad"],"example":"inline-form"},"name":{"description":"Name of the form. HTML in it is filtered out.","type":"string","example":"Newsletter signup"},"actiondata":{"description":"What happens on submit. A subscribe action naming a list that no longer exists is dropped.","properties":{"actions":{"description":"The actions, each with a type and its settings","type":"array","items":{"type":"object"}}},"type":"object"},"aid":{"description":"ID of the address to set on the form's opt-in email campaign, the campaign linked to the form. Not stored on the form.","type":"integer","example":2}},"type":"object"}},"type":"object"},"examples":{"Request Example":{"summary":"Rename an inline form","value":{"form":{"name":"Newsletter signup","layout":"inline-form"}}}}}}},"responses":{"200":{"description":"The form was saved.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form as saved","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"layout":{"description":"How the form is shown","type":"string","example":"inline-form"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form","type":"string","example":"No Result found for Form with id 42"}},"type":"object"}}}},"422":{"description":"The layout is not on the account's plan, or an option is invalid: options.blocked_email_domains, options.block_personal_email_providers, the paused message and link options, or the SMS confirmation messages.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per invalid field","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422. Absent when the layout is refused.","type":"integer","example":422},"title":{"description":"Short name of the HTTP status, or the reason when the layout is refused","type":"string","example":"Unprocessable Entity"},"detail":{"description":"What is wrong with the field. Empty when the layout is refused.","type":"string","example":"Each blocked email domain must be a valid domain, such as example.com or *.example.com."},"code":{"description":"Error code. Sent only when the layout is refused.","type":"string","example":"field_invalid"},"source":{"description":"The field at fault","properties":{"pointer":{"description":"The field, as /data/attributes/ followed by its name: layout, or the key in options","type":"string","example":"/data/attributes/blocked_email_domains"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}/allowPersonalEmailProviders":{"put":{"summary":"Allow personal email addresses on a form","description":"Makes the form take submissions from personal email providers, such as gmail.com, again, by setting `options.block_personal_email_providers` to `false`. Domains on `options.blocked_email_domains` stay blocked, gmail.com included if it is listed there. Allowing when they are already allowed changes nothing and succeeds. Use `PUT /forms/{id}/blockPersonalEmailProviders` to block them again. Requires the permission to edit forms. While the `forms-block-email-domains` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-block-email-domains` feature is released.","operationId":"allow-personal-email-providers-on-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"Personal email providers are allowed. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"block_personal_email_providers":{"description":"Whether the form refuses personal email providers: `false` after this call","type":"boolean","example":false}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, or the `forms-block-email-domains` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message while the feature is disabled, as for an unknown route","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the method and path","type":"string","example":"No route found for \"PUT /api/3/forms/42/allowPersonalEmailProviders\""}},"type":"object"}}},"type":"object"},"example":{"message":"No Result found for Form with id 42"}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}/blockPersonalEmailProviders":{"put":{"summary":"Block personal email addresses on a form","description":"Makes the form refuse submissions from personal email providers, such as gmail.com, yahoo.com and outlook.com, by setting `options.block_personal_email_providers` to `true`. The providers come from a list ActiveCampaign keeps, so they need not be added to `options.blocked_email_domains` one by one; the domains on that list stay blocked as before. Blocking when they are already blocked changes nothing and succeeds. Use `PUT /forms/{id}/allowPersonalEmailProviders` to take them again. Preference Center forms take no typed email address, so this has no effect on one. Requires the permission to edit forms. While the `forms-block-email-domains` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-block-email-domains` feature is released.","operationId":"block-personal-email-providers-on-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"Personal email providers are blocked. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"block_personal_email_providers":{"description":"Whether the form refuses personal email providers: `true` after this call","type":"boolean","example":true}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, or the `forms-block-email-domains` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message while the feature is disabled, as for an unknown route","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the method and path","type":"string","example":"No route found for \"PUT /api/3/forms/42/blockPersonalEmailProviders\""}},"type":"object"}}},"type":"object"},"example":{"message":"No Result found for Form with id 42"}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}/blockedEmailDomains":{"post":{"summary":"Block email domains on a form","description":"Adds email domains to the form's `options.blocked_email_domains`, so the form refuses submissions from addresses at them. Each domain is trimmed and lowercased, and a leading `@` or `*@` is dropped, as `PUT /forms/{id}` does: `@Competitor.com` is stored as `competitor.com`. `example.com` blocks addresses at example.com only; `*.example.com` blocks every subdomain of example.com but not example.com itself, so add both to block both. Domains already on the list are left as they are, so the request is safe to repeat. A form blocks at most 100 domains. Use `DELETE /forms/{id}/blockedEmailDomains` to unblock one, and `PUT /forms/{id}/blockPersonalEmailProviders` to block personal providers such as gmail.com without listing them. Preference Center forms take no typed email address, so a list on one has no effect. The form builder saves the whole list with the form, so a save from a builder opened before this call puts back the list it loaded. Requires the permission to edit forms. While the `forms-block-email-domains` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-block-email-domains` feature is released.","operationId":"add-blocked-email-domains-to-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"description":"The domains to block","required":true,"content":{"application/json":{"schema":{"required":["domains"],"properties":{"domains":{"description":"Domains to block, at least one, such as example.com or *.example.com. One invalid entry fails the request and nothing is added.","type":"array","items":{"type":"string"},"example":["competitor.com","*.example.com"]}},"type":"object"},"examples":{"Request Example":{"summary":"Block a competitor and every subdomain of example.com","value":{"domains":["competitor.com","*.example.com"]}}}}}},"responses":{"200":{"description":"The domains are blocked. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"blocked_email_domains":{"description":"Every domain the form now blocks, the ones it blocked before first","type":"array","items":{"type":"string"},"example":["competitor.com","*.example.com"]}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, or the `forms-block-email-domains` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message while the feature is disabled, as for an unknown route","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the method and path","type":"string","example":"No route found for \"POST /api/3/forms/42/blockedEmailDomains\""}},"type":"object"}}},"type":"object"},"example":{"message":"No Result found for Form with id 42"}}}},"422":{"description":"domains is missing or empty, an entry isn't a domain, or the form would block more than 100 domains. Nothing is added.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\"","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong","type":"string","example":"Each blocked email domain must be a valid domain, such as example.com or *.example.com."},"source":{"description":"The field at fault","properties":{"pointer":{"description":"Always /data/attributes/domains","type":"string","example":"/data/attributes/domains"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"forms","x-destructive":false,"x-bulk-operation":true,"x-internal":true},"delete":{"summary":"Unblock an email domain on a form","description":"Removes one domain from the form's `options.blocked_email_domains`, so the form takes submissions from addresses at it again. Pass the domain in the `domain` query parameter. It is cleaned as it was when added, so `@Competitor.com` removes `competitor.com`. Removing `*.example.com` leaves `example.com` blocked if it is on the list, and the other way round. To unblock personal providers such as gmail.com, use `PUT /forms/{id}/allowPersonalEmailProviders`. Requires the permission to edit forms. While the `forms-block-email-domains` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-block-email-domains` feature is released.","operationId":"remove-a-blocked-email-domain-from-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"domain","in":"query","description":"The blocked domain to remove, such as competitor.com or *.example.com","required":true,"schema":{"type":"string"},"example":"competitor.com"}],"responses":{"200":{"description":"The domain is unblocked. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"blocked_email_domains":{"description":"Every domain the form still blocks","type":"array","items":{"type":"string"},"example":["*.example.com"]}},"type":"object"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The domain query parameter is missing, blank, or not a domain.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 400","type":"integer","example":400},"title":{"description":"Short name of the HTTP status","type":"string","example":"Bad Request"},"detail":{"description":"What is wrong with the domain parameter","type":"string","example":"Send the domain to unblock in the domain query parameter."}},"type":"object"}}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, the form doesn't block this domain, or the `forms-block-email-domains` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message when the form doesn't block the domain, or while the feature is disabled","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the domain, or the method and path while the feature is disabled","type":"string","example":"Form 42 doesn't block competitor.com."}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"404","detail":"Form 42 doesn't block competitor.com."}]}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}/html":{"get":{"summary":"Retrieve a form's HTML","description":"Returns the HTML that embeds the form on a page, rendered by the server, as text/html rather than JSON. While the form is paused and the forms-pause feature is on for the account, the body is what the form's script embed shows instead: the paused message for an inline form whose owner set a message or button of their own, otherwise an empty body. Requires the permission to edit forms. Internal: serves the form's full HTML embed code.","operationId":"retrieve-a-forms-html","parameters":[{"name":"id","in":"path","description":"ID of the form","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The form's HTML. Empty when the form is paused and its embed shows nothing.","content":{"text/html":{"schema":{"type":"string","example":"...<form method=\"POST\" action=\"https://:account.activehosted.com/proc.php\" id=\"_form_42_\" class=\"_form _form_42 _inline-form\" novalidate data-styles-version=\"5\">...</form>..."}}}},"403":{"description":"The user may not edit forms.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"403"},"detail":{"description":"Always \"You do not have permission to view forms\"","type":"string","example":"You do not have permission to view forms"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"You do not have permission to view forms"}]}}}},"404":{"description":"No form has this ID.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the missing form","type":"string","example":"No form found with id 42"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"404","detail":"No form found with id 42"}]}}}}},"x-canonical-resource":"forms","x-internal":true}},"/forms/{id}/pause":{"put":{"summary":"Pause a form","description":"Pauses a form without deleting it. While it is paused, it accepts no new submissions and visitors see a paused message in place of its fields: the form's own `options.paused_message`, with a button from `options.paused_link_text` and `options.paused_link_url` when both are set, or a default message. The form's public link always shows that message. An inline form's embed shows it only when the form has its own message or button, and renders nothing otherwise; the embeds of pop-up layouts render nothing. Those options are saved with `POST /forms` and `PUT /forms/{id}`. Only `options.paused` changes, to `true`: the form keeps its ID, settings and embed code. Pausing a paused form changes nothing and succeeds. A Preference Center can't be paused: contacts reach it from the links in every email, so this returns `422` for one. Use `PUT /forms/{id}/resume` to take submissions again, and `GET /forms?paused=true` to list paused forms. Requires the permission to edit forms. While the `forms-pause` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-pause` feature is released.","operationId":"pause-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form to pause","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The form is paused. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"paused":{"description":"Whether the form is paused: `true` after this call","type":"boolean","example":true}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, or the `forms-pause` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message while the feature is disabled, as for an unknown route","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the method and path","type":"string","example":"No route found for \"PUT /api/3/forms/42/pause\""}},"type":"object"}}},"type":"object"},"example":{"message":"No Result found for Form with id 42"}}}},"422":{"description":"The form is a Preference Center, which can't be paused. Nothing is changed.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, 422","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\"","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the form can't be paused","type":"string","example":"Preference Centers can't be paused: contacts reach them from the links in your emails."},"source":{"description":"The field at fault","properties":{"pointer":{"description":"Always /data/attributes/layout","type":"string","example":"/data/attributes/layout"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/forms/{id}/resume":{"put":{"summary":"Resume a paused form","description":"Resumes a paused form: it accepts submissions again, and its public link and embeds show its fields. Only `options.paused` changes, to `false`; the paused message and button stay saved for the next pause. Resuming a form that isn't paused changes nothing and succeeds. Use `PUT /forms/{id}/pause` to pause it again. Requires the permission to edit forms. While the `forms-pause` feature is disabled for the account, this endpoint returns `404`. Internal: until the `forms-pause` feature is released.","operationId":"resume-a-form","parameters":[{"name":"id","in":"path","description":"ID of the form to resume","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The form is active. The body is the form as `GET /forms/{id}` returns it, read after the change.","content":{"application/json":{"schema":{"properties":{"form":{"description":"The form, in the shape `GET /forms/{id}` returns it","properties":{"id":{"description":"ID of the form","type":"string","example":"42"},"name":{"description":"Name of the form","type":"string","example":"Newsletter signup"},"options":{"description":"The form's options","properties":{"paused":{"description":"Whether the form is paused: `false` after this call","type":"boolean","example":false}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The user may not edit forms, or may not edit this form.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per error. This request fails with a single error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status: a string when the user may not edit forms, a number when they may not edit this form","type":["string","integer"],"example":"403"},"title":{"description":"Short name of the HTTP status. Sent only when the user may not edit this form.","type":"string","example":"Forbidden"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"No form has this ID, or the `forms-pause` feature is disabled for the account.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing form. Sent when no form has this ID.","type":"string","example":"No Result found for Form with id 42"},"errors":{"description":"Sent instead of message while the feature is disabled, as for an unknown route","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string, the same as the response status","type":"string","example":"404"},"detail":{"description":"Names the method and path","type":"string","example":"No route found for \"PUT /api/3/forms/42/resume\""}},"type":"object"}}},"type":"object"},"example":{"message":"No Result found for Form with id 42"}}}}},"x-canonical-resource":"forms","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/geoAddresses":{"get":{"summary":"List all geo addresses","description":"Lists the locations that contact IP addresses have resolved to across the account. Normally one location is stored per pair of coordinates and is shared by every address and contact that resolves there. There are no filters and no sort options; locations come in no guaranteed order. Use limit and offset to page, or ids to fetch specific locations.","operationId":"list-all-geo-addresses","x-canonical-resource":"geoIps","parameters":[{"name":"ids","in":"query","description":"Comma-separated list of location ids to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return for each call. Default is 20; maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"A page of locations.","content":{"application/json":{"schema":{"type":"object","properties":{"geoAddresses":{"type":"array","description":"The locations on this page.","items":{"$ref":"#/components/schemas/GeoAddress"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, ignoring limit and offset.","example":2}}}}}}}}},"deprecated":false}},"/geoAddresses/{id}":{"get":{"summary":"Retrieve a geo address","description":"Returns one location. Returns 404 if no location has the id.","operationId":"retrieve-a-geo-address","x-canonical-resource":"geoIps","parameters":[{"name":"id","in":"path","description":"ID of the location.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The location.","content":{"application/json":{"schema":{"type":"object","properties":{"geoAddress":{"description":"The location.","allOf":[{"$ref":"#/components/schemas/GeoAddress"}]}}}}}},"404":{"description":"No location has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no location has the id.","example":"No Result found for Geoaddr with id 100"}}}}}}},"deprecated":false}},"/geoIps":{"get":{"summary":"List all geo IP entries","description":"Lists the IP addresses recorded for contacts across the account. An entry is recorded when a contact does something from an IPv4 address that resolves to a location, for example when the contact opens or clicks a campaign, submits a form, or is added through the v1 API with an IP address. The same contact, campaign and location is recorded once. The entries' locations are included in a top-level `geoAddresses` array. There are no filters and no sort options; entries come in no guaranteed order. Use limit and offset to page, or ids to fetch specific entries.","operationId":"list-all-geo-ips","x-canonical-resource":"geoIps","parameters":[{"name":"ids","in":"query","description":"Comma-separated list of geo IP entry ids to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return for each call. Default is 20; maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"A page of geo IP entries, with their locations.","content":{"application/json":{"schema":{"type":"object","properties":{"geoAddresses":{"type":"array","description":"The locations of the entries on this page, each listed once. Absent (or shorter) when entries on the page have no location.","items":{"$ref":"#/components/schemas/GeoAddress"}},"geoIps":{"type":"array","description":"The geo IP entries on this page.","items":{"$ref":"#/components/schemas/GeoIp"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, ignoring limit and offset.","example":2}}}}}}}}},"deprecated":false}},"/geoIps/{id}":{"get":{"summary":"Retrieve a geo IP entry","description":"Returns one geo IP entry with its location in a top-level `geoAddresses` array. The array is absent when the entry has no location. Returns 404 if no geo IP entry has the id.","operationId":"retrieve-a-geo-ip","x-canonical-resource":"geoIps","parameters":[{"name":"id","in":"path","description":"ID of the geo IP entry.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The geo IP entry and its location.","content":{"application/json":{"schema":{"type":"object","properties":{"geoAddresses":{"type":"array","description":"The entry's location. Absent when the entry has no location.","items":{"$ref":"#/components/schemas/GeoAddress"}},"geoIp":{"description":"The geo IP entry.","allOf":[{"$ref":"#/components/schemas/GeoIp"}]}}}}}},"404":{"description":"No geo IP entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no geo IP entry has the id.","example":"No Result found for Geoip with id 100"}}}}}}},"deprecated":false}},"/geoIps/{id}/geoAddress":{"get":{"summary":"Retrieve the location of a geo IP entry","description":"Returns the location that one geo IP entry resolved to. The id is the id of the geo IP entry, not of a contact or a location. Returns an empty object `{}` when the entry has no location, for example when the location record was removed. Returns 404 if no geo IP entry has the id.","operationId":"retrieve-a-contacts-geo-ip-address","x-canonical-resource":"geoIps","parameters":[{"name":"id","in":"path","description":"ID of the geo IP entry.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The location the entry resolved to, or an empty object when it has none.","content":{"application/json":{"schema":{"type":"object","properties":{"geoAddress":{"description":"The location.","allOf":[{"$ref":"#/components/schemas/GeoAddress"}]}}}}}},"404":{"description":"No geo IP entry has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Explains that no geo IP entry has the id.","example":"No Result found for Geoip with id 100"}}}}}}},"deprecated":false}},"/globalData/account":{"get":{"summary":"Retrieve the account values the app starts with","description":"The account's settings, plan, entitlements, contact and sending usage under acct, as seen by the signed-in user. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-account","responses":{"200":{"description":"The account values","content":{"application/json":{"schema":{"properties":{"acct":{"$ref":"#/components/schemas/GlobalDataAccount","description":"The account values."}},"type":"object"}}}},"500":{"description":"Reading one of the values threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/globalData/admin":{"get":{"summary":"Retrieve the signed-in user's admin record","description":"The legacy admin record of the signed-in user under admin: the user's em_user row without password and apikey, merged with the permissions, limits and branding of the user's groups, plus the locale of the user's language. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-admin","responses":{"200":{"description":"The admin record","content":{"application/json":{"schema":{"properties":{"admin":{"$ref":"#/components/schemas/GlobalDataAdmin","description":"The admin record."}},"type":"object"}}}},"500":{"description":"Building the record threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"account_user","x-internal":true}},"/globalData/branding":{"get":{"summary":"Retrieve the account's branding","description":"The account-wide branding settings under branding, with the app page template split around its %NAV% and %PAGECONTENT% placeholders so the app can render its own navigation and content inside it. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-branding","responses":{"200":{"description":"The branding","content":{"application/json":{"schema":{"properties":{"branding":{"$ref":"#/components/schemas/GlobalDataBranding","description":"The branding."}},"type":"object"}}}},"500":{"description":"Building the branding threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"brandings","x-internal":true}},"/globalData/connections":{"get":{"summary":"List all of the account's connections","description":"Every integration connection on the account, connected, in error or disconnected, in the /connections resource format. The list sits under connections.connections: the outer key is this endpoint's, the inner one the collection's JSON API name. It is neither paginated nor filtered. It backs the app UI and is not meant for API clients.","operationId":"list-all-global-data-connections","responses":{"200":{"description":"The connections","content":{"application/json":{"schema":{"properties":{"connections":{"description":"The connections as a JSON API collection.","properties":{"connections":{"description":"Every connection on the account; empty when there is none.","type":"array","items":{"$ref":"#/components/schemas/GlobalDataConnection"}}},"type":"object"}},"type":"object"}}}},"500":{"description":"Reading the connections threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"connections","x-internal":true}},"/globalData/featureFlags":{"get":{"summary":"Retrieve feature flag values for the signed-in user","description":"LaunchDarkly flag values for the account and user under featureFlags, keyed by flag key. Without flags every flag comes from one all-flags evaluation, which records no evaluation events in LaunchDarkly; with flags only the named flags are evaluated, one by one, which does record them (use it for flags in an experiment). If the all-flags evaluation returns nothing, the configured defaults are returned instead. The response is marked Cache-Control: private. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-feature-flags","parameters":[{"name":"flags","in":"query","description":"Comma-separated flag keys to evaluate; blank entries and duplicates are dropped. A key LaunchDarkly does not know gets its configured default, or false. When set, clientSideOnly is ignored.","required":false,"schema":{"type":"string"},"example":"nrx-report-migration,ox-reboarding"},{"name":"clientSideOnly","in":"query","description":"When true (1, true, on or yes), only the flags made available to client-side SDKs in LaunchDarkly are returned. All flags are still fetched; the filtering only trims the response. Ignored when flags is set.","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The flag values","content":{"application/json":{"schema":{"properties":{"featureFlags":{"description":"Flag values keyed by flag key: a boolean for on/off flags, the variation value for multivariate ones. An empty object when there are none.","type":"object","additionalProperties":true}},"type":"object"},"example":{"featureFlags":{"nrx-report-migration":"enabled","ox-reboarding":false}}}}},"500":{"description":"Evaluating the flags threw.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always this fixed text.","type":"string","example":"An exception occurred."},"exception":{"description":"The exception object, which serializes to an empty object.","type":"object","example":{}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/globalData/nrxStatus":{"get":{"summary":"Retrieve whether campaign reports use NRX tracking data","description":"nrxTrackingEnabled says whether the account's campaign reports read NRX tracking data. The nrx-report-migration flag decides it when set to enabled or disabled; otherwise it is true only when the account's NRX readiness check (NRX_slo_readiness_check v2, v3 or v4 in NRX_config) passes and both React campaign report launch flags are on. A readiness query that fails counts as false. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-nrx-status","responses":{"200":{"description":"The NRX status","content":{"application/json":{"schema":{"properties":{"nrxTrackingEnabled":{"description":"True when campaign reports read NRX tracking data.","type":"boolean","example":true}},"type":"object"}}}},"500":{"description":"Evaluating the status threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/globalData/pendoConfig":{"get":{"summary":"Retrieve the Pendo configuration for the signed-in user","description":"The visitor and account metadata and the API key the app passes to Pendo, under pendoConfig. It is built once and kept in the session for six hours per user, so values can be up to six hours old; clear_pendo rebuilds it. The response is marked Cache-Control: private. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-pendo-config","parameters":[{"name":"clear_pendo","in":"query","description":"Any value other than empty or 0 rebuilds the configuration instead of reading the session copy, and stores the new one.","required":false,"schema":{"type":"string"},"example":"1"}],"responses":{"200":{"description":"The Pendo configuration","content":{"application/json":{"schema":{"properties":{"pendoConfig":{"$ref":"#/components/schemas/GlobalDataPendoConfig","description":"The Pendo configuration."}},"type":"object"}}}},"500":{"description":"Building the configuration threw. The cause is logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/globalData/persTags":{"get":{"summary":"List personalization tags by object type","description":"The personalization tags the signed-in user can insert into content, grouped by object type under tags. filters picks the groups; without it all four are returned. It backs the app UI and is not meant for API clients.","operationId":"list-all-global-data-personalization-tags","parameters":[{"name":"filters[]","in":"query","description":"Object types to return, repeated for more than one: filters[]=DEALS&filters[]=CONTACT. Unknown values are ignored; omitted or empty returns every type. A plain filters=DEALS (not a list) fails with 500.","required":false,"schema":{"type":"array","items":{"type":"string","enum":["ECOMMERCE","DEALS","ACCOUNT","CONTACT"]}}}],"responses":{"200":{"description":"The tags","content":{"application/json":{"schema":{"properties":{"tags":{"$ref":"#/components/schemas/GlobalDataPersonalizationTags","description":"The tags by object type."}},"type":"object"}}}},"500":{"description":"filters was not a list, or reading the tags threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"personalizations","x-internal":true}},"/globalData/regions":{"get":{"summary":"List the data regions and which one serves the account","description":"Always the us and eu regions under regions. currentRegion is true for the one whose two-letter prefix starts the AWS region this Hosted deployment runs in (AWS_REGION, us-east-1 by default); both are false when it matches neither. It backs the app UI and is not meant for API clients.","operationId":"list-all-global-data-regions","responses":{"200":{"description":"The regions","content":{"application/json":{"schema":{"properties":{"regions":{"description":"The regions, keyed by region prefix.","properties":{"us":{"description":"The US region.","properties":{"currentRegion":{"description":"True when the account is served from the US region.","type":"boolean","example":true}},"type":"object"},"eu":{"description":"The EU region.","properties":{"currentRegion":{"description":"True when the account is served from the EU region.","type":"boolean","example":false}},"type":"object"}},"type":"object"}},"type":"object"},"example":{"regions":{"us":{"currentRegion":true},"eu":{"currentRegion":false}}}}}},"500":{"description":"Reading the region threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/globalData/tplShareHost":{"get":{"summary":"Retrieve the host of shared automation links","description":"The hostname shared automation and template links use (the TPLSHARE_HOST environment setting, such as tplshare.com), under tplShareHost. The app builds share links as http://<host>/<hash>, and importing an automation from a link accepts only this host. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-template-share-host","responses":{"200":{"description":"The host","content":{"application/json":{"schema":{"properties":{"tplShareHost":{"description":"Hostname of the template sharing site, without scheme.","type":"string","example":"tplshare.com"}},"type":"object"}}}},"500":{"description":"Building the response threw. The cause is logged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"automation","x-internal":true}},"/globalData/user":{"get":{"summary":"Retrieve the signed-in user's settings","description":"The signed-in user's stored settings under user, as em_user columns, with main_admin, main_admin_group and email_hash added. Password, salt and apikey are not included. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-user","responses":{"200":{"description":"The user","content":{"application/json":{"schema":{"properties":{"user":{"$ref":"#/components/schemas/GlobalDataUser","description":"The user."}},"type":"object"}}}},"500":{"description":"Reading the user threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"account_user","x-internal":true}},"/globalData/userJson":{"get":{"summary":"Retrieve the signed-in user in the /users resource format","description":"The signed-in user as a JSON API document under userJson: the user as GET /users/{id} formats it, plus any related collection already loaded on the session user. It backs the app UI and is not meant for API clients.","operationId":"retrieve-global-data-user-json","responses":{"200":{"description":"The user document","content":{"application/json":{"schema":{"properties":{"userJson":{"$ref":"#/components/schemas/GlobalDataUserJson","description":"The user document."}},"type":"object"}}}},"500":{"description":"Building the document threw.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalDataErrorResponse"}}}}},"x-canonical-resource":"account_user","x-internal":true}},"/goal/goalStats":{"get":{"summary":"Retrieve goal stats","description":"Completion statistics for one automation goal, ranked against the other goals in the same automation. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses.","operationId":"retrieve-goal-stats","x-canonical-resource":"automation","parameters":[{"name":"goal","in":"query","description":"ID of the automation goal.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalStats"}}}},"403":{"description":"The `goal` query parameter is missing or empty. The body is plain text (`goal_id is required` / `goal is required`), not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No goal with this ID"}},"deprecated":false}},"/goal/showcase":{"get":{"summary":"Retrieve goal showcase","description":"How many contacts entered the goal's automation, plus the top ten tags, top ten lists and time-to-goal buckets among contacts who reached the goal. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses.","operationId":"retrieve-goal-showcase","x-canonical-resource":"automation","parameters":[{"name":"goal","in":"query","description":"ID of the automation goal.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalShowcase"}}}},"403":{"description":"The `goal` query parameter is missing or empty. The body is plain text (`goal_id is required` / `goal is required`), not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false}},"/goals":{"get":{"summary":"List all goals","description":"Automation goals. Read-only resource: POST, PUT and DELETE are not routed.","operationId":"list-all-goals","x-canonical-resource":"automation","parameters":[{"name":"limit","in":"query","description":"Number of goals to return.","schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of goals to skip, for paging.","schema":{"type":"integer","format":"int32"}},{"name":"search","in":"query","description":"Return only goals whose name contains every space-separated word.","schema":{"type":"string"}},{"name":"filters[seriesid]","in":"query","description":"Return only goals in this automation.","schema":{"type":"integer","format":"int32"}},{"name":"filters[blockid]","in":"query","description":"Return only the goal held by this automation block.","schema":{"type":"integer","format":"int32"}},{"name":"with_success","in":"query","description":"Set to any non-empty value to add per-goal `completed`, `entered` and `rate` under `meta.success`, and to restrict results to goals with tracking enabled or at least one completion.","schema":{"type":"string"}},{"name":"without_deleted","in":"query","description":"Set to any non-empty value to exclude goals whose automation block was deleted.","schema":{"type":"string"}},{"name":"orders[success]","in":"query","description":"Order by success rate (`ASC` or `DESC`). Applies the same filter as `with_success`, but `meta.success` is only returned when `with_success` is also set.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Comma-separated relationships to sideload: `automation`, `automationBlock`, `contactGoals`.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of goals under goals, with the number of matching goals in meta.total and, with with_success, each goal's completion figures in meta.success.","content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"$ref":"#/components/schemas/Goal"},"description":"The goals on this page. An empty list when there are none."},"meta":{"type":"object","properties":{"total":{"type":["integer","string"],"description":"Number of matching goals, without limit and offset.","example":1},"success":{"type":"object","description":"Present only when with_success is set. Completion figures for each goal on this page, keyed by goal ID. An empty page returns an empty array [] instead of an object.","additionalProperties":{"type":"object","properties":{"completed":{"type":["integer","string","null"],"description":"Number of times a contact reached the goal. Null when no contact has reached it.","example":"1"},"entered":{"type":["integer","string","null"],"description":"Number of times a contact entered the goal's automation. Null when completed is null.","example":"2"},"rate":{"type":["integer","string"],"description":"completed divided by entered, as a fraction from 0 to 1 rather than a percentage, e.g. \"0.5000\". 0 when entered is null or 0.","example":"0.5000"}},"description":"Completion figures for one goal."}}},"description":"Paging information, plus completion figures when with_success is set."}}},"examples":{"Result":{"value":{"goals":[{"blockid":"57","seriesid":"12","name":"Made a purchase","cdate":"2026-08-20T10:15:00-05:00","dirty_stats":"0","links":{"automation":"https://example.api-us1.com/api/3/goals/3/automation","automationBlock":"https://example.api-us1.com/api/3/goals/3/automationBlock","contactGoals":"https://example.api-us1.com/api/3/goals/3/contactGoals"},"id":"3","automation":"12","automationBlock":"57"}],"meta":{"total":1}}}}}}}},"deprecated":false}},"/goals/{id}":{"get":{"summary":"Retrieve a goal","description":"Returns one automation goal by ID. Read-only resource: PUT and DELETE are not routed.","operationId":"retrieve-a-goal","x-canonical-resource":"automation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"},"description":"ID of the goal."}],"responses":{"200":{"description":"The goal under goal.","content":{"application/json":{"schema":{"type":"object","properties":{"goal":{"$ref":"#/components/schemas/Goal","description":"The requested goal."}}},"examples":{"Result":{"value":{"goal":{"blockid":"57","seriesid":"12","name":"Made a purchase","cdate":"2026-08-20T10:15:00-05:00","dirty_stats":"0","links":{"automation":"https://example.api-us1.com/api/3/goals/3/automation","automationBlock":"https://example.api-us1.com/api/3/goals/3/automationBlock","contactGoals":"https://example.api-us1.com/api/3/goals/3/contactGoals"},"id":"3","automation":"12","automationBlock":"57"}}}}}}},"404":{"description":"No goal has this id. Body: message, \"No Result found for Goal with id\" followed by the id as a whole number.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says that no goal has the id.","example":"No Result found for Goal with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for Goal with id 100"}}}}}}},"deprecated":false}},"/group/bulk_delete":{"delete":{"summary":"Delete multiple groups","description":"Delete several user groups in a single request and move everything that referenced them to another group.\n\nUsers and deal groups belonging to the deleted groups are reassigned to the group given in `to`, and the deleted groups are removed from any automations they were assigned to. Parameters are sent as query string or form parameters, not as a JSON body; `POST` is accepted with the same parameters. `from` must be sent as an array, even when deleting a single group.","operationId":"bulk-delete-groups","x-canonical-resource":"group","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"from","in":"query","description":"IDs of the groups to delete. Must be sent as an array. Example: from[]=5&from[]=6","schema":{"type":"array","items":{"type":"integer","format":"int32"}},"required":true},{"name":"to","in":"query","description":"ID of the group that users and deal groups from the deleted groups are reassigned to.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"meta\": {\n        \"success\": true\n    }\n}"}},"schema":{"type":"object","properties":{"meta":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"A \\\"from\\\" parameter is required.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"A \"from\" parameter is required."}}}}}}},"deprecated":false}},"/groupDefinitions":{"post":{"summary":"Create a Custom Field Group","description":"Create a Custom Field Group","operationId":"create-a-custom-field-group","x-canonical-resource":"groupDefinitions","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["groupDefinition"],"properties":{"groupDefinition":{"type":"object","required":["groupType","label"],"properties":{"groupType":{"type":"integer","format":"int32","description":"The id of the group type the field group belongs to. List valid ids via GET /groupTypes.","example":1},"label":{"type":"string","description":"Field Group Name","example":"Group Name Here"}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groupDefinition\": {\n        \"id\": 22,\n        \"type_id\": 1,\n        \"label\": \"Group Name Here\",\n        \"ordernum\": 4,\n        \"created_by\": 1,\n        \"updated_by\": 1,\n        \"links\": {\n            \"groupMembers\": \"https://account.api-us1.com/api/3/groupMembers?group_id=22\",\n            \"groupType\": \"https://account.api-us1.com/api/3/groupTypes/1\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"groupDefinition":{"type":"object","properties":{"id":{"type":"integer","example":22,"default":0},"type_id":{"type":"integer","example":1,"default":0},"label":{"type":"string","example":"Group Name Here"},"ordernum":{"type":"integer","example":4,"default":0},"created_by":{"type":"integer","example":1,"default":0},"updated_by":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"groupMembers":{"type":"string","example":"https://account.api-us1.com/api/3/groupMembers?group_id=22"},"groupType":{"type":"string","example":"https://account.api-us1.com/api/3/groupTypes/1"}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/groupLimits":{"get":{"summary":"List All Group Limits","description":"","operationId":"list-all-group-limits","x-canonical-resource":"groupLimits","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n\t\"groupLimits\": [\n\t\t{\n\t\t\t\"groupid\": \"1\",\n\t\t\t\"limitMail\": \"0\",\n\t\t\t\"limitMailType\": \"month\",\n\t\t\t\"limitContact\": \"0\",\n\t\t\t\"limitList\": \"0\",\n\t\t\t\"limitCampaign\": \"0\",\n\t\t\t\"limitCampaignType\": \"month\",\n\t\t\t\"limitAttachment\": \"-1\",\n\t\t\t\"limitUser\": \"0\",\n\t\t\t\"abuseRatio\": \"4\",\n\t\t\t\"forceSenderInfo\": \"0\",\n\t\t\t\"links\": {\n\t\t\t\t\"group\": \"https://:account.api-us1.com/api/3/groupLimits/1/group\"\n\t\t\t},\n\t\t\t\"id\": \"1\",\n\t\t\t\"group\": \"1\"\n\t\t},\n\t\t{\n\t\t\t\"groupid\": \"2\",\n\t\t\t\"limitMail\": \"0\",\n\t\t\t\"limitMailType\": \"month\",\n\t\t\t\"limitContact\": \"0\",\n\t\t\t\"limitList\": \"0\",\n\t\t\t\"limitCampaign\": \"0\",\n\t\t\t\"limitCampaignType\": \"month\",\n\t\t\t\"limitAttachment\": \"-1\",\n\t\t\t\"limitUser\": \"0\",\n\t\t\t\"abuseRatio\": \"4\",\n\t\t\t\"forceSenderInfo\": \"0\",\n\t\t\t\"links\": {\n\t\t\t\t\"group\": \"https://:account.api-us1.com/api/3/groupLimits/2/group\"\n\t\t\t},\n\t\t\t\"id\": \"2\",\n\t\t\t\"group\": \"2\"\n\t\t},\n\t\t{\n\t\t\t\"groupid\": \"3\",\n\t\t\t\"limitMail\": \"0\",\n\t\t\t\"limitMailType\": \"month\",\n\t\t\t\"limitContact\": \"0\",\n\t\t\t\"limitList\": \"0\",\n\t\t\t\"limitCampaign\": \"0\",\n\t\t\t\"limitCampaignType\": \"month\",\n\t\t\t\"limitAttachment\": \"-1\",\n\t\t\t\"limitUser\": \"0\",\n\t\t\t\"abuseRatio\": \"4\",\n\t\t\t\"forceSenderInfo\": \"0\",\n\t\t\t\"links\": {\n\t\t\t\t\"group\": \"https://:account.api-us1.com/api/3/groupLimits/3/group\"\n\t\t\t},\n\t\t\t\"id\": \"3\",\n\t\t\t\"group\": \"3\"\n\t\t},\n\t\t{\n\t\t\t\"groupid\": \"4\",\n\t\t\t\"limitMail\": \"0\",\n\t\t\t\"limitMailType\": \"month\",\n\t\t\t\"limitContact\": \"0\",\n\t\t\t\"limitList\": \"0\",\n\t\t\t\"limitCampaign\": \"0\",\n\t\t\t\"limitCampaignType\": \"month\",\n\t\t\t\"limitAttachment\": \"-1\",\n\t\t\t\"limitUser\": \"0\",\n\t\t\t\"abuseRatio\": \"4\",\n\t\t\t\"forceSenderInfo\": \"0\",\n\t\t\t\"links\": {\n\t\t\t\t\"group\": \"https://:account.api-us1.com/api/3/groupLimits/4/group\"\n\t\t\t},\n\t\t\t\"id\": \"4\",\n\t\t\t\"group\": \"4\"\n\t\t}\n\t],\n\t\"meta\": {\n\t\t\"total\": \"4\"\n\t}\n}"}},"schema":{"type":"object","properties":{"groupLimits":{"type":"array","items":{"type":"object","properties":{"groupid":{"type":"string","example":"1"},"limitMail":{"type":"string","example":"0"},"limitMailType":{"type":"string","example":"month"},"limitContact":{"type":"string","example":"0"},"limitList":{"type":"string","example":"0"},"limitCampaign":{"type":"string","example":"0"},"limitCampaignType":{"type":"string","example":"month"},"limitAttachment":{"type":"string","example":"-1"},"limitUser":{"type":"string","example":"0"},"abuseRatio":{"type":"string","example":"4"},"forceSenderInfo":{"type":"string","example":"0"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/groupLimits/1/group"}}},"id":{"type":"string","example":"1"},"group":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"4"}}}}}}}}},"deprecated":false}},"/groupMembers":{"post":{"summary":"Add Custom Field to Field Group","description":"","operationId":"add-custom-field-to-field-group","x-canonical-resource":"groupMembers","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"groupMember":{"properties":{"rel_id":{"type":"integer","description":"Custom field ID","format":"int32"},"group_id":{"type":"integer","format":"int32"},"groupDefinition":{"type":["integer","string"],"description":"Alias of group_id, used when group_id is absent."}},"required":[],"type":"object"}},"additionalProperties":false},"examples":{"POST":{"value":{"groupMember":{"rel_id":"10","group_id":"1"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groupMember\": {\n        \"id\": 87,\n        \"group_id\": 1,\n        \"rel_id\": 10,\n        \"ordernum\": 18,\n        \"created_by\": 1,\n        \"updated_by\": 1,\n        \"links\": {\n            \"groupDefinition\": \"https://:account.api-us1.com/api/3/groupDefinitions/1\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"groupMember":{"type":"object","properties":{"id":{"type":"integer","example":87,"default":0},"group_id":{"type":"integer","example":1,"default":0},"rel_id":{"type":"integer","example":10,"default":0},"ordernum":{"type":"integer","example":18,"default":0},"created_by":{"type":"integer","example":1,"default":0},"updated_by":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"groupDefinition":{"type":"string","example":"https://:account.api-us1.com/api/3/groupDefinitions/1"}}}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"rel_id left blank":{"value":"{\n    \"message\": \"Client error: `POST https://groups.example.com/member` resulted in a `400 Bad Request` response:\\n{\\\"message\\\": {\\\"rel_id\\\": \\\"rel_id is required\\\"}}\\n\\n\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Client error: `POST https://groups.example.com/member` resulted in a `400 Bad Request` response:\n{\"message\": {\"rel_id\": \"rel_id is required\"}}\n\n"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for GroupDefinition with id 94\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for GroupDefinition with id 94"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The field title was not provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The field title was not provided."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"}}}}}}}}}},"deprecated":false},"get":{"summary":"Get All Custom Field Groups","description":"","operationId":"get-all-custom-field-groups","x-canonical-resource":"groupMembers","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groupDefinitions\": [\n        {\n            \"id\": 1,\n            \"type_id\": 1,\n            \"label\": \"{**DEFAULT**}\",\n            \"ordernum\": 1,\n            \"links\": {\n                \"groupMembers\": \"https://account.api-us1.com/api/3/groupMembers?group_id=1\",\n                \"groupType\": \"https://account.api-us1.com/api/3/groupTypes/1\"\n            }\n        },\n        {\n            \"id\": 2,\n            \"type_id\": 2,\n            \"label\": \"{**DEAL_DEFAULT**}\",\n            \"ordernum\": 2,\n            \"links\": {\n                \"groupMembers\": \"https://account.api-us1.com/api/3/groupMembers?group_id=2\",\n                \"groupType\": \"https://account.api-us1.com/api/3/groupTypes/2\"\n            }\n        },\n        {\n            \"id\": 3,\n            \"type_id\": 3,\n            \"label\": \"{**ACCOUNT_DEFAULT**}\",\n            \"ordernum\": 3,\n            \"links\": {\n                \"groupMembers\": \"https://account.api-us1.com/api/3/groupMembers?group_id=3\",\n                \"groupType\": \"https://account.api-us1.com/api/3/groupTypes/3\"\n            }\n        },\n        {\n            \"id\": 21,\n            \"type_id\": 1,\n            \"label\": \"CustomName\",\n            \"ordernum\": 3,\n            \"links\": {\n                \"groupMembers\": \"https://account.api-us1.com/api/3/groupMembers?group_id=21\",\n                \"groupType\": \"https://account.api-us1.com/api/3/groupTypes/1\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"groupDefinitions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1,"default":0},"type_id":{"type":"integer","example":1,"default":0},"label":{"type":"string","example":"{**DEFAULT**}"},"ordernum":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"groupMembers":{"type":"string","example":"https://account.api-us1.com/api/3/groupMembers?group_id=1"},"groupType":{"type":"string","example":"https://account.api-us1.com/api/3/groupTypes/1"}}}}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/groupMembers/{groupId}":{"put":{"summary":"Update Custom Field Field Group","description":"","operationId":"update-custom-field-field-group","x-canonical-resource":"groupMembers","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"groupId","in":"path","description":"Field group ID (see notes)","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"groupMember":{"type":"object","properties":{"group_id":{"type":"integer"},"groupDefinition":{"type":["integer","string"],"description":"Alias of group_id, used when group_id is absent."},"ordernum":{"type":"integer"}}}},"additionalProperties":false},"examples":{"POST":{"value":{"groupMember":{"group_id":1,"ordernum":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groupMember\": {\n        \"id\": 87,\n        \"group_id\": 1,\n        \"rel_id\": 10,\n        \"ordernum\": 18,\n        \"created_by\": 1,\n        \"updated_by\": 1,\n        \"links\": {\n            \"groupDefinition\": \"https://:account.api-us1.com/api/3/groupDefinitions/1\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"groupMember":{"type":"object","properties":{"id":{"type":"integer","example":87,"default":0},"group_id":{"type":"integer","example":1,"default":0},"rel_id":{"type":"integer","example":10,"default":0},"ordernum":{"type":"integer","example":18,"default":0},"created_by":{"type":"integer","example":1,"default":0},"updated_by":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"groupDefinition":{"type":"string","example":"https://:account.api-us1.com/api/3/groupDefinitions/1"}}}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"rel_id left blank":{"value":"{\n    \"message\": \"Client error: `POST https://groups.example.com/member` resulted in a `400 Bad Request` response:\\n{\\\"message\\\": {\\\"rel_id\\\": \\\"rel_id is required\\\"}}\\n\\n\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Client error: `POST https://groups.example.com/member` resulted in a `400 Bad Request` response:\n{\"message\": {\"rel_id\": \"rel_id is required\"}}\n\n"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for GroupDefinition with id 94\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for GroupDefinition with id 94"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The field title was not provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The field title was not provided."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete Custom Field Field Group","description":"","operationId":"delete-custom-field-field-group","x-canonical-resource":"groupMembers","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"groupId","in":"path","description":"Group ID","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false,"requestBody":{"content":{"application/json":{"schema":{},"examples":{"POST":{"value":{"groupMember":{"rel_id":"10","ordernum":null,"group_id":"1"}}}}}}}},"get":{"summary":"Get Custom Field Group by ID","description":"","operationId":"get-custom-field-to-field-group","x-canonical-resource":"groupMembers","parameters":[{"name":"groupId","in":"path","description":"Group ID","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groupMember\": {\n        \"id\": 89,\n        \"group_id\": 1,\n        \"rel_id\": 5,\n        \"ordernum\": 20,\n        \"links\": {\n            \"groupDefinition\": \"https://:account.api-us1.com/api/3/groupDefinitions/1\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"groupMember":{"type":"object","properties":{"id":{"type":"integer","example":89,"default":0},"group_id":{"type":"integer","example":1,"default":0},"rel_id":{"type":"integer","example":5,"default":0},"ordernum":{"type":"integer","example":20,"default":0},"links":{"type":"object","properties":{"groupDefinition":{"type":"string","example":"https://:account.api-us1.com/api/3/groupDefinitions/1"}}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 404,\n            \"title\": \"Not Found\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":404,"default":0},"title":{"type":"string","example":"Not Found"}}}}}}}}}},"deprecated":false,"requestBody":{"content":{"application/json":{"schema":{},"examples":{"POST":{"value":{"groupMember":{"rel_id":"10","ordernum":null,"group_id":"1"}}}}}}}}},"/groupTypesSync":{"post":{"summary":"Reconcile custom field group members with the contact fields","description":"Makes the members of the contact custom field (`em_field`) group type match the account's contact fields: every field that is in none of the type's groups is added to the type's default group, and every member whose field no longer exists is deleted. Only the first group type in the body is read. A type other than `em_field` is a no-op, and so is a type that has no members at all: nothing is added to an empty type. The queue HTTP service calls it with the list a `GET /groupTypes` call produced, when that call queued the sync (a feature flag decides) instead of running it inline. The body is used as sent: its type ID, label and default group ID are not checked against the stored group type. Exceptions during the sync are logged and still answered with 200. Internal: queue callback.","operationId":"sync-group-type-members","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupTypesSyncRequest"},"example":{"groupTypes":[{"id":1,"label":"em_field","default_group_id":1}]}}}},"responses":{"200":{"description":"The sync ran, was skipped, or failed and was logged. The body is always an empty array.","content":{"application/json":{"schema":{"type":"array","items":{},"maxItems":0},"example":[]}}},"500":{"description":"The body is not a JSON object, or its `groupTypes` list is empty.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"groupMembers","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/groups":{"post":{"summary":"Create a group","description":"","operationId":"create-a-new-group","x-canonical-resource":"groups","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"group":{"properties":{"title":{"type":"string","description":"Title of the group to be created"},"descript":{"type":"string","description":"Group description"},"pgMessageAdd":{"type":"boolean","description":"Permission for adding messages","default":false},"pgListAdd":{"type":"boolean","description":"Permission for adding lists","default":false},"pgListEdit":{"type":"boolean","description":"Permission for editing lists","default":false},"pgListDelete":{"type":"boolean","description":"Permission for deleting lists","default":false},"pgListHeaders":{"type":"boolean","description":"Permission for managing custom email headers","default":false},"pgListEmailaccount":{"type":"boolean","description":"Permission for managing Unsubscribe By Email","default":false},"pgListBounce":{"type":"boolean","description":"Permission for accessing list bounce settings","default":false},"pgMessageEdit":{"type":"boolean","description":"Permission for editing messages","default":false},"pgMessageDelete":{"type":"boolean","description":"Permission for deleting messages","default":false},"pgMessageSend":{"type":"boolean","description":"Permission for sending messages","default":false},"pgContactAdd":{"type":"boolean","description":"Permission for adding contacts","default":false},"pgContactEdit":{"type":"boolean","description":"Permission for editing contacts","default":false},"pgContactDelete":{"type":"boolean","description":"Permission for deleting contacts","default":false},"pgContactMerge":{"type":"boolean","description":"Permission for merging contacts","default":false},"pgContactImport":{"type":"boolean","description":"Permission for importing contacts","default":false},"pgContactApprove":{"type":"boolean","description":"Permission for approving contacts","default":false},"pgContactExport":{"type":"boolean","description":"Permission for exporting contacts","default":false},"pgContactSync":{"type":"boolean","description":"Permission for syncing contacts","default":false},"pgContactFilters":{"type":"boolean","description":"Permission for managing contact list segments","default":false},"pgContactActions":{"type":"boolean","description":"Permission for managing contact actions","default":false},"pgContactFields":{"type":"boolean","description":"Permission for managing contact custom fields","default":false},"pgGroupAdd":{"type":"boolean","description":"Permission for adding groups","default":false},"pgGroupEdit":{"type":"boolean","description":"Permission for editing groups","default":false},"pgGroupDelete":{"type":"boolean","description":"Permission for deleting groups","default":false},"pgTemplateAdd":{"type":"boolean","description":"Permission for adding templates","default":false},"pgTemplateEdit":{"type":"boolean","description":"Permission for editing templates","default":false},"pgTemplateDelete":{"type":"boolean","description":"Permission for deleting templates","default":false},"pgPersonalizationAdd":{"type":"boolean","description":"Permission for adding personalization tags","default":false},"pgPersonalizationEdit":{"type":"boolean","description":"Permission for editing personalization tags","default":false},"pgPersonalizationDelete":{"type":"boolean","description":"Permission for deleting personalization tags","default":false},"pgAutomationManage":{"type":"boolean","default":false},"pgFormEdit":{"type":"boolean","description":"Permission for editing subscription forms","default":false},"pgReportsCampaign":{"type":"boolean","description":"Permission for viewing campaign reports","default":false},"pgReportsList":{"type":"boolean","description":"Permission for viewing list reports","default":false},"pgReportsUser":{"type":"boolean","description":"Permission for viewing user reports","default":false},"pgStartupReports":{"type":"boolean","description":"Campaign ID of last campaign report viewed to decide whether to show link on startup","default":false},"pgReportsTrend":{"type":"boolean","description":"Permission for viewing trend reports","default":false},"pgStartupGettingstarted":{"type":"boolean","description":"Whether or not to show the \"getting started\" tutorial on overview page","default":false},"pgDeal":{"type":"boolean","description":"Permission for viewing deals","default":false},"pgDealDelete":{"type":"boolean","description":"Permission for deleting deals","default":false},"pgDealReassign":{"type":"boolean","description":"Permission for reassigning deals","default":false},"pgDealGroupAdd":{"type":"boolean","description":"Permission for adding deal groups","default":false},"pgDealGroupEdit":{"type":"boolean","description":"Permission for editing deal groups","default":false},"pgDealGroupDelete":{"type":"boolean","description":"Permission for deleting deals groups","default":false},"pgSavedResponsesManage":{"type":"boolean","description":"Permission for managing saved responses","default":false},"pgTagManage":{"type":"boolean","description":"Permission for managing tags","default":false},"reqApproval":{"type":"boolean","description":"Whether or not this group requires all campaigns to be approved","default":false},"reqApproval1st":{"type":"boolean","description":"Whether or not this group requires first campaign to be approved","default":false},"reqApprovalNotify":{"type":"string","description":"Who to notify for approval related issues (email)"},"socialdata":{"type":"boolean","description":"Whether or not to show social links in campaigns sent from this group","default":false},"pgAccountAdd":{"type":"boolean"},"pgAccountDelete":{"type":"boolean"},"pgAccountEdit":{"type":"boolean"},"pgAccountExport":{"type":"boolean"},"pgAccountImport":{"type":"boolean"},"pgAccountManageCustomField":{"type":"boolean"},"pgAccountNoteAdd":{"type":"boolean"},"pgAccountNoteDelete":{"type":"boolean"},"pgAccountNoteEdit":{"type":"boolean"},"pgAccountReassign":{"type":"boolean"},"pgAutomationRead":{"type":"boolean","description":"Read-only access to automations for the group's users, stored outside the group record. Changing it requires the pg_automation_manage permission; null is treated as not sent."},"pgContactResubscribe":{"type":"boolean"},"pgDealExport":{"type":"boolean"},"pgDealFields":{"type":"boolean"},"pgDealImport":{"type":"boolean"},"pgDealListAll":{"type":"boolean"},"pgDealManageRoles":{"type":"boolean"},"pgDealNoteAdd":{"type":"boolean"},"pgDealNoteDelete":{"type":"boolean"},"pgDealNoteEdit":{"type":"boolean"},"pgInboxManageAvailability":{"type":"boolean"},"pgInboxManageOwnAvailability":{"type":"boolean"},"pgInboxView":{"type":"boolean"},"pgInboxViewAvailability":{"type":"boolean"},"pgLandingPagesAccess":{"type":"boolean"},"pgReportsDeal":{"type":"boolean"},"pgReportsSalesEngagement":{"type":"boolean"},"pgSmsCampaignManage":{"type":"boolean"},"pgSmsCampaignSend":{"type":"boolean"},"pgSmsCampaignView":{"type":"boolean"},"pgSmsKeywordManage":{"type":"boolean"},"pgSmsKeywordView":{"type":"boolean"},"pgSmsRegistration":{"type":"boolean"},"pgSmsReporting":{"type":"boolean"},"pgSmsSendingOptions":{"type":"boolean"},"pgWhatsappCreateFlows":{"type":"boolean"},"pgWhatsappCreateTemplates":{"type":"boolean"},"pgWhatsappDeleteFlows":{"type":"boolean"},"pgWhatsappDeleteTemplates":{"type":"boolean"},"pgWhatsappUpdateFlows":{"type":"boolean"},"pgWhatsappUpdateSettings":{"type":"boolean"},"pgWhatsappUseInbox":{"type":"boolean"},"pgWhatsappViewAllConversations":{"type":"boolean"},"pgWhatsappViewFlows":{"type":"boolean"},"pgWhatsappViewReports":{"type":"boolean"},"pg_web_personalization_manage":{"type":"boolean"}},"required":["title"],"type":"object"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"group":{"title":"TEST TITLE","descript":"Description Text","pgListAdd":1,"pgListEdit":1,"pgListDelete":1,"pgListHeaders":1,"pgListEmailaccount":1,"pgListBounce":1,"pgMessageAdd":1,"pgMessageEdit":1,"pgMessageDelete":1,"pgMessageSend":1,"pgContactAdd":1,"pgContactEdit":1,"pgContactDelete":1,"pgContactMerge":1,"pgContactImport":1,"pgContactApprove":1,"pgContactExport":1,"pgContactSync":1,"pgContactFilters":1,"pgContactActions":1,"pgContactFields":1,"pgGroupAdd":1,"pgGroupEdit":1,"pgGroupDelete":1,"pgTemplateAdd":1,"pgTemplateEdit":1,"pgTemplateDelete":1,"pgPersonalizationAdd":1,"pgPersonalizationEdit":1,"pgPersonalizationDelete":1,"pgAutomationManage":1,"pgFormEdit":1,"pgReportsCampaign":1,"pgReportsList":1,"pgReportsUser":1,"pgReportsTrend":1,"pgStartupReports":1,"pgStartupGettingstarted":1,"pgDeal":1,"pgDealDelete":1,"pgDealReassign":1,"pgDealGroupAdd":1,"pgDealGroupEdit":1,"pgDealGroupDelete":1,"pgSavedResponsesManage":1,"reqApproval":1,"reqApproval1st":1,"reqApprovalNotify":"johndoe@example.com","socialdata":0}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"group\": {\n        \"title\": \"My Groups Title\",\n        \"p_admin\": 1,\n        \"links\": {\n            \"userGroups\": \"https://:account.api-us1.com/api/:version/groups/7/userGroups\",\n            \"groupLimit\": \"https://:account.api-us1.com/api/:version/groups/7/groupLimit\",\n            \"dealGroupGroups\": \"https://:account.api-us1.com/api/:version/groups/7/dealGroupGroups\",\n            \"listGroups\": \"https://:account.api-us1.com/api/:version/groups/7/listGroups\",\n            \"addressGroups\": \"https://:account.api-us1.com/api/:version/groups/7/addressGroups\",\n            \"automationGroups\": \"https://:account.api-us1.com/api/:version/groups/7/automationGroups\"\n        },\n        \"id\": \"7\"\n    }\n}"}},"schema":{"type":"object","properties":{"group":{"type":"object","properties":{"title":{"type":"string","example":"My Groups Title"},"p_admin":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"userGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/userGroups"},"groupLimit":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/groupLimit"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/dealGroupGroups"},"listGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/listGroups"},"addressGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/addressGroups"},"automationGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/automationGroups"}}},"id":{"type":"string","example":"7"}}}}}}}}},"deprecated":false},"get":{"summary":"List all groups","description":"","operationId":"list-all-groups","x-canonical-resource":"groups","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"groups\": [\n        {\n            \"title\": \"TEST TITLE\",\n            \"descript\": \"This is a group for admin users (people that can manage content)\",\n            \"unsubscribelink\": \"0\",\n            \"optinconfirm\": \"0\",\n            \"p_admin\": \"1\",\n            \"pgListAdd\": \"1\",\n            \"pgListEdit\": \"1\",\n            \"pgListDelete\": \"1\",\n            \"pgListHeaders\": \"1\",\n            \"pgListEmailaccount\": \"1\",\n            \"pgListBounce\": \"1\",\n            \"pgMessageAdd\": \"1\",\n            \"pgMessageEdit\": \"1\",\n            \"pgMessageDelete\": \"1\",\n            \"pgMessageSend\": \"1\",\n            \"pgContactAdd\": \"1\",\n            \"pgContactEdit\": \"1\",\n            \"pgContactDelete\": \"1\",\n            \"pgContactMerge\": \"1\",\n            \"pgContactImport\": \"1\",\n            \"pgContactApprove\": \"1\",\n            \"pgContactExport\": \"1\",\n            \"pgContactSync\": \"1\",\n            \"pgContactFilters\": \"1\",\n            \"pgContactActions\": \"0\",\n            \"pgContactFields\": \"1\",\n            \"pg_user_add\": \"1\",\n            \"pg_user_edit\": \"1\",\n            \"pg_user_delete\": \"1\",\n            \"pgGroupAdd\": \"1\",\n            \"pgGroupEdit\": \"1\",\n            \"pgGroupDelete\": \"1\",\n            \"pgTemplateAdd\": \"1\",\n            \"pgTemplateEdit\": \"1\",\n            \"pgTemplateDelete\": \"1\",\n            \"pgPersonalizationAdd\": \"1\",\n            \"pgPersonalizationEdit\": \"1\",\n            \"pgPersonalizationDelete\": \"1\",\n            \"pgAutomationManage\": \"1\",\n            \"pgFormEdit\": \"1\",\n            \"pgReportsCampaign\": \"1\",\n            \"pgReportsList\": \"1\",\n            \"pgReportsUser\": \"1\",\n            \"pgReportsTrend\": \"1\",\n            \"pgStartupReports\": \"1\",\n            \"pgStartupGettingstarted\": \"1\",\n            \"pgDeal\": \"1\",\n            \"pgDealDelete\": \"1\",\n            \"pgDealReassign\": \"1\",\n            \"pgDealGroupAdd\": \"1\",\n            \"pgDealGroupEdit\": \"1\",\n            \"pgDealGroupDelete\": \"1\",\n            \"pgSavedResponsesManage\": \"1\",\n            \"sdate\": \"2018-09-20T10:51:14-05:00\",\n            \"reqApproval\": \"0\",\n            \"reqApproval1st\": \"2\",\n            \"reqApprovalNotify\": \"\",\n            \"socialdata\": \"0\",\n            \"links\": {\n                \"userGroups\": \"https://:account.api-us1.com/api/3/groups/3/userGroups\",\n                \"groupLimit\": \"https://:account.api-us1.com/api/3/groups/3/groupLimit\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/groups/3/dealGroupGroups\",\n                \"listGroups\": \"https://:account.api-us1.com/api/3/groups/3/listGroups\",\n                \"addressGroups\": \"https://:account.api-us1.com/api/3/groups/3/addressGroups\",\n                \"automationGroups\": \"https://:account.api-us1.com/api/3/groups/3/automationGroups\"\n            },\n            \"id\": \"3\"\n        },\n        {\n            \"title\": \"TEST TITLE\",\n            \"descript\": null,\n            \"unsubscribelink\": \"0\",\n            \"optinconfirm\": \"0\",\n            \"p_admin\": \"1\",\n            \"pgListAdd\": \"0\",\n            \"pgListEdit\": \"0\",\n            \"pgListDelete\": \"0\",\n            \"pgListHeaders\": \"0\",\n            \"pgListEmailaccount\": \"0\",\n            \"pgListBounce\": \"0\",\n            \"pgMessageAdd\": \"0\",\n            \"pgMessageEdit\": \"0\",\n            \"pgMessageDelete\": \"0\",\n            \"pgMessageSend\": \"0\",\n            \"pgContactAdd\": \"0\",\n            \"pgContactEdit\": \"0\",\n            \"pgContactDelete\": \"0\",\n            \"pgContactMerge\": \"0\",\n            \"pgContactImport\": \"0\",\n            \"pgContactApprove\": \"0\",\n            \"pgContactExport\": \"0\",\n            \"pgContactSync\": \"0\",\n            \"pgContactFilters\": \"0\",\n            \"pgContactActions\": \"0\",\n            \"pgContactFields\": \"0\",\n            \"pg_user_add\": \"0\",\n            \"pg_user_edit\": \"0\",\n            \"pg_user_delete\": \"0\",\n            \"pgGroupAdd\": \"0\",\n            \"pgGroupEdit\": \"0\",\n            \"pgGroupDelete\": \"0\",\n            \"pgTemplateAdd\": \"0\",\n            \"pgTemplateEdit\": \"0\",\n            \"pgTemplateDelete\": \"0\",\n            \"pgPersonalizationAdd\": \"0\",\n            \"pgPersonalizationEdit\": \"0\",\n            \"pgPersonalizationDelete\": \"0\",\n            \"pgAutomationManage\": \"0\",\n            \"pgFormEdit\": \"0\",\n            \"pgReportsCampaign\": \"0\",\n            \"pgReportsList\": \"0\",\n            \"pgReportsUser\": \"0\",\n            \"pgReportsTrend\": \"1\",\n            \"pgStartupReports\": \"0\",\n            \"pgStartupGettingstarted\": \"1\",\n            \"pgDeal\": \"1\",\n            \"pgDealDelete\": \"1\",\n            \"pgDealReassign\": \"1\",\n            \"pgDealGroupAdd\": \"1\",\n            \"pgDealGroupEdit\": \"1\",\n            \"pgDealGroupDelete\": \"1\",\n            \"pgSavedResponsesManage\": \"0\",\n            \"sdate\": null,\n            \"reqApproval\": \"0\",\n            \"reqApproval1st\": \"2\",\n            \"reqApprovalNotify\": \"\",\n            \"socialdata\": \"0\",\n            \"links\": {\n                \"userGroups\": \"https://:account.api-us1.com/api/3/groups/5/userGroups\",\n                \"groupLimit\": \"https://:account.api-us1.com/api/3/groups/5/groupLimit\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/groups/5/dealGroupGroups\",\n                \"listGroups\": \"https://:account.api-us1.com/api/3/groups/5/listGroups\",\n                \"addressGroups\": \"https://:account.api-us1.com/api/3/groups/5/addressGroups\",\n                \"automationGroups\": \"https://:account.api-us1.com/api/3/groups/5/automationGroups\"\n            },\n            \"id\": \"5\"\n        },\n        {\n            \"title\": \"TEST TITLE\",\n            \"descript\": null,\n            \"unsubscribelink\": \"0\",\n            \"optinconfirm\": \"0\",\n            \"p_admin\": \"1\",\n            \"pgListAdd\": \"0\",\n            \"pgListEdit\": \"0\",\n            \"pgListDelete\": \"0\",\n            \"pgListHeaders\": \"0\",\n            \"pgListEmailaccount\": \"0\",\n            \"pgListBounce\": \"0\",\n            \"pgMessageAdd\": \"0\",\n            \"pgMessageEdit\": \"0\",\n            \"pgMessageDelete\": \"0\",\n            \"pgMessageSend\": \"0\",\n            \"pgContactAdd\": \"0\",\n            \"pgContactEdit\": \"0\",\n            \"pgContactDelete\": \"0\",\n            \"pgContactMerge\": \"0\",\n            \"pgContactImport\": \"0\",\n            \"pgContactApprove\": \"0\",\n            \"pgContactExport\": \"0\",\n            \"pgContactSync\": \"0\",\n            \"pgContactFilters\": \"0\",\n            \"pgContactActions\": \"0\",\n            \"pgContactFields\": \"0\",\n            \"pg_user_add\": \"0\",\n            \"pg_user_edit\": \"0\",\n            \"pg_user_delete\": \"0\",\n            \"pgGroupAdd\": \"0\",\n            \"pgGroupEdit\": \"0\",\n            \"pgGroupDelete\": \"0\",\n            \"pgTemplateAdd\": \"0\",\n            \"pgTemplateEdit\": \"0\",\n            \"pgTemplateDelete\": \"0\",\n            \"pgPersonalizationAdd\": \"0\",\n            \"pgPersonalizationEdit\": \"0\",\n            \"pgPersonalizationDelete\": \"0\",\n            \"pgAutomationManage\": \"0\",\n            \"pgFormEdit\": \"0\",\n            \"pgReportsCampaign\": \"0\",\n            \"pgReportsList\": \"0\",\n            \"pgReportsUser\": \"0\",\n            \"pgReportsTrend\": \"1\",\n            \"pgStartupReports\": \"0\",\n            \"pgStartupGettingstarted\": \"1\",\n            \"pgDeal\": \"1\",\n            \"pgDealDelete\": \"1\",\n            \"pgDealReassign\": \"1\",\n            \"pgDealGroupAdd\": \"1\",\n            \"pgDealGroupEdit\": \"1\",\n            \"pgDealGroupDelete\": \"1\",\n            \"pgSavedResponsesManage\": \"0\",\n            \"sdate\": null,\n            \"reqApproval\": \"0\",\n            \"reqApproval1st\": \"2\",\n            \"reqApprovalNotify\": \"\",\n            \"socialdata\": \"0\",\n            \"links\": {\n                \"userGroups\": \"https://:account.api-us1.com/api/3/groups/6/userGroups\",\n                \"groupLimit\": \"https://:account.api-us1.com/api/3/groups/6/groupLimit\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/groups/6/dealGroupGroups\",\n                \"listGroups\": \"https://:account.api-us1.com/api/3/groups/6/listGroups\",\n                \"addressGroups\": \"https://:account.api-us1.com/api/3/groups/6/addressGroups\",\n                \"automationGroups\": \"https://:account.api-us1.com/api/3/groups/6/automationGroups\"\n            },\n            \"id\": \"6\"\n        },\n        {\n            \"title\": \"TEST TITLE\",\n            \"descript\": null,\n            \"unsubscribelink\": \"0\",\n            \"optinconfirm\": \"0\",\n            \"p_admin\": \"1\",\n            \"pgListAdd\": \"0\",\n            \"pgListEdit\": \"0\",\n            \"pgListDelete\": \"0\",\n            \"pgListHeaders\": \"0\",\n            \"pgListEmailaccount\": \"0\",\n            \"pgListBounce\": \"0\",\n            \"pgMessageAdd\": \"0\",\n            \"pgMessageEdit\": \"0\",\n            \"pgMessageDelete\": \"0\",\n            \"pgMessageSend\": \"0\",\n            \"pgContactAdd\": \"0\",\n            \"pgContactEdit\": \"0\",\n            \"pgContactDelete\": \"0\",\n            \"pgContactMerge\": \"0\",\n            \"pgContactImport\": \"0\",\n            \"pgContactApprove\": \"0\",\n            \"pgContactExport\": \"0\",\n            \"pgContactSync\": \"0\",\n            \"pgContactFilters\": \"0\",\n            \"pgContactActions\": \"0\",\n            \"pgContactFields\": \"0\",\n            \"pg_user_add\": \"0\",\n            \"pg_user_edit\": \"0\",\n            \"pg_user_delete\": \"0\",\n            \"pgGroupAdd\": \"0\",\n            \"pgGroupEdit\": \"0\",\n            \"pgGroupDelete\": \"0\",\n            \"pgTemplateAdd\": \"0\",\n            \"pgTemplateEdit\": \"0\",\n            \"pgTemplateDelete\": \"0\",\n            \"pgPersonalizationAdd\": \"0\",\n            \"pgPersonalizationEdit\": \"0\",\n            \"pgPersonalizationDelete\": \"0\",\n            \"pgAutomationManage\": \"0\",\n            \"pgFormEdit\": \"0\",\n            \"pgReportsCampaign\": \"0\",\n            \"pgReportsList\": \"0\",\n            \"pgReportsUser\": \"0\",\n            \"pgReportsTrend\": \"1\",\n            \"pgStartupReports\": \"0\",\n            \"pgStartupGettingstarted\": \"1\",\n            \"pgDeal\": \"1\",\n            \"pgDealDelete\": \"1\",\n            \"pgDealReassign\": \"1\",\n            \"pgDealGroupAdd\": \"1\",\n            \"pgDealGroupEdit\": \"1\",\n            \"pgDealGroupDelete\": \"1\",\n            \"pgSavedResponsesManage\": \"0\",\n            \"sdate\": null,\n            \"reqApproval\": \"0\",\n            \"reqApproval1st\": \"2\",\n            \"reqApprovalNotify\": \"\",\n            \"socialdata\": \"0\",\n            \"links\": {\n                \"userGroups\": \"https://:account.api-us1.com/api/3/groups/7/userGroups\",\n                \"groupLimit\": \"https://:account.api-us1.com/api/3/groups/7/groupLimit\",\n                \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/groups/7/dealGroupGroups\",\n                \"listGroups\": \"https://:account.api-us1.com/api/3/groups/7/listGroups\",\n                \"addressGroups\": \"https://:account.api-us1.com/api/3/groups/7/addressGroups\",\n                \"automationGroups\": \"https://:account.api-us1.com/api/3/groups/7/automationGroups\"\n            },\n            \"id\": \"7\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"4\"\n    }\n}"}},"schema":{"type":"object","properties":{"groups":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"TEST TITLE"},"descript":{"type":"string","example":"This is a group for admin users (people that can manage content)"},"unsubscribelink":{"type":"string","example":"0"},"optinconfirm":{"type":"string","example":"0"},"p_admin":{"type":"string","example":"1"},"pgListAdd":{"type":"string","example":"1"},"pgListEdit":{"type":"string","example":"1"},"pgListDelete":{"type":"string","example":"1"},"pgListHeaders":{"type":"string","example":"1"},"pgListEmailaccount":{"type":"string","example":"1"},"pgListBounce":{"type":"string","example":"1"},"pgMessageAdd":{"type":"string","example":"1"},"pgMessageEdit":{"type":"string","example":"1"},"pgMessageDelete":{"type":"string","example":"1"},"pgMessageSend":{"type":"string","example":"1"},"pgContactAdd":{"type":"string","example":"1"},"pgContactEdit":{"type":"string","example":"1"},"pgContactDelete":{"type":"string","example":"1"},"pgContactMerge":{"type":"string","example":"1"},"pgContactImport":{"type":"string","example":"1"},"pgContactApprove":{"type":"string","example":"1"},"pgContactExport":{"type":"string","example":"1"},"pgContactSync":{"type":"string","example":"1"},"pgContactFilters":{"type":"string","example":"1"},"pgContactActions":{"type":"string","example":"0"},"pgContactFields":{"type":"string","example":"1"},"pg_user_add":{"type":"string","example":"1"},"pg_user_edit":{"type":"string","example":"1"},"pg_user_delete":{"type":"string","example":"1"},"pgGroupAdd":{"type":"string","example":"1"},"pgGroupEdit":{"type":"string","example":"1"},"pgGroupDelete":{"type":"string","example":"1"},"pgTemplateAdd":{"type":"string","example":"1"},"pgTemplateEdit":{"type":"string","example":"1"},"pgTemplateDelete":{"type":"string","example":"1"},"pgPersonalizationAdd":{"type":"string","example":"1"},"pgPersonalizationEdit":{"type":"string","example":"1"},"pgPersonalizationDelete":{"type":"string","example":"1"},"pgAutomationManage":{"type":"string","example":"1"},"pgFormEdit":{"type":"string","example":"1"},"pgReportsCampaign":{"type":"string","example":"1"},"pgReportsList":{"type":"string","example":"1"},"pgReportsUser":{"type":"string","example":"1"},"pgReportsTrend":{"type":"string","example":"1"},"pgStartupReports":{"type":"string","example":"1"},"pgStartupGettingstarted":{"type":"string","example":"1"},"pgDeal":{"type":"string","example":"1"},"pgDealDelete":{"type":"string","example":"1"},"pgDealReassign":{"type":"string","example":"1"},"pgDealGroupAdd":{"type":"string","example":"1"},"pgDealGroupEdit":{"type":"string","example":"1"},"pgDealGroupDelete":{"type":"string","example":"1"},"pgSavedResponsesManage":{"type":"string","example":"1"},"sdate":{"type":"string","example":"2018-09-20T10:51:14-05:00"},"reqApproval":{"type":"string","example":"0"},"reqApproval1st":{"type":"string","example":"2"},"reqApprovalNotify":{"type":"string","example":""},"socialdata":{"type":"string","example":"0"},"links":{"type":"object","properties":{"userGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/userGroups"},"groupLimit":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/groupLimit"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/dealGroupGroups"},"listGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/listGroups"},"addressGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/addressGroups"},"automationGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/automationGroups"}}},"id":{"type":"string","example":"3"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"4"}}}}}}}}},"deprecated":false}},"/groups/{id}":{"get":{"summary":"Retrieve a group","description":"","operationId":"retrieve-a-group","x-canonical-resource":"groups","parameters":[{"name":"id","in":"path","description":"ID of the group to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"group\": {\n        \"title\": \"TEST TITLE\",\n        \"descript\": \"This is a group for admin users (people that can manage content)\",\n        \"unsubscribelink\": \"0\",\n        \"optinconfirm\": \"0\",\n        \"p_admin\": \"1\",\n        \"pgListAdd\": \"1\",\n        \"pgListEdit\": \"1\",\n        \"pgListDelete\": \"1\",\n        \"pgListHeaders\": \"1\",\n        \"pgListEmailaccount\": \"1\",\n        \"pgListBounce\": \"1\",\n        \"pgMessageAdd\": \"1\",\n        \"pgMessageEdit\": \"1\",\n        \"pgMessageDelete\": \"1\",\n        \"pgMessageSend\": \"1\",\n        \"pgContactAdd\": \"1\",\n        \"pgContactEdit\": \"1\",\n        \"pgContactDelete\": \"1\",\n        \"pgContactMerge\": \"1\",\n        \"pgContactImport\": \"1\",\n        \"pgContactApprove\": \"1\",\n        \"pgContactExport\": \"1\",\n        \"pgContactSync\": \"1\",\n        \"pgContactFilters\": \"1\",\n        \"pgContactActions\": \"0\",\n        \"pgContactFields\": \"1\",\n        \"pg_user_add\": \"1\",\n        \"pg_user_edit\": \"1\",\n        \"pg_user_delete\": \"1\",\n        \"pgGroupAdd\": \"1\",\n        \"pgGroupEdit\": \"1\",\n        \"pgGroupDelete\": \"1\",\n        \"pgTemplateAdd\": \"1\",\n        \"pgTemplateEdit\": \"1\",\n        \"pgTemplateDelete\": \"1\",\n        \"pgPersonalizationAdd\": \"1\",\n        \"pgPersonalizationEdit\": \"1\",\n        \"pgPersonalizationDelete\": \"1\",\n        \"pgAutomationManage\": \"1\",\n        \"pgFormEdit\": \"1\",\n        \"pgReportsCampaign\": \"1\",\n        \"pgReportsList\": \"1\",\n        \"pgReportsUser\": \"1\",\n        \"pgReportsTrend\": \"1\",\n        \"pgStartupReports\": \"1\",\n        \"pgStartupGettingstarted\": \"1\",\n        \"pgDeal\": \"1\",\n        \"pgDealDelete\": \"1\",\n        \"pgDealReassign\": \"1\",\n        \"pgDealGroupAdd\": \"1\",\n        \"pgDealGroupEdit\": \"1\",\n        \"pgDealGroupDelete\": \"1\",\n        \"pgSavedResponsesManage\": \"1\",\n        \"sdate\": \"2018-09-20T10:51:14-05:00\",\n        \"reqApproval\": \"0\",\n        \"reqApproval1st\": \"2\",\n        \"reqApprovalNotify\": \"\",\n        \"socialdata\": \"0\",\n        \"links\": {\n            \"userGroups\": \"https://:account.api-us1.com/api/3/groups/3/userGroups\",\n            \"groupLimit\": \"https://:account.api-us1.com/api/3/groups/3/groupLimit\",\n            \"dealGroupGroups\": \"https://:account.api-us1.com/api/3/groups/3/dealGroupGroups\",\n            \"listGroups\": \"https://:account.api-us1.com/api/3/groups/3/listGroups\",\n            \"addressGroups\": \"https://:account.api-us1.com/api/3/groups/3/addressGroups\",\n            \"automationGroups\": \"https://:account.api-us1.com/api/3/groups/3/automationGroups\"\n        },\n        \"id\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"group":{"type":"object","properties":{"title":{"type":"string","example":"TEST TITLE"},"descript":{"type":"string","example":"This is a group for admin users (people that can manage content)"},"unsubscribelink":{"type":"string","example":"0"},"optinconfirm":{"type":"string","example":"0"},"p_admin":{"type":"string","example":"1"},"pgListAdd":{"type":"string","example":"1"},"pgListEdit":{"type":"string","example":"1"},"pgListDelete":{"type":"string","example":"1"},"pgListHeaders":{"type":"string","example":"1"},"pgListEmailaccount":{"type":"string","example":"1"},"pgListBounce":{"type":"string","example":"1"},"pgMessageAdd":{"type":"string","example":"1"},"pgMessageEdit":{"type":"string","example":"1"},"pgMessageDelete":{"type":"string","example":"1"},"pgMessageSend":{"type":"string","example":"1"},"pgContactAdd":{"type":"string","example":"1"},"pgContactEdit":{"type":"string","example":"1"},"pgContactDelete":{"type":"string","example":"1"},"pgContactMerge":{"type":"string","example":"1"},"pgContactImport":{"type":"string","example":"1"},"pgContactApprove":{"type":"string","example":"1"},"pgContactExport":{"type":"string","example":"1"},"pgContactSync":{"type":"string","example":"1"},"pgContactFilters":{"type":"string","example":"1"},"pgContactActions":{"type":"string","example":"0"},"pgContactFields":{"type":"string","example":"1"},"pg_user_add":{"type":"string","example":"1"},"pg_user_edit":{"type":"string","example":"1"},"pg_user_delete":{"type":"string","example":"1"},"pgGroupAdd":{"type":"string","example":"1"},"pgGroupEdit":{"type":"string","example":"1"},"pgGroupDelete":{"type":"string","example":"1"},"pgTemplateAdd":{"type":"string","example":"1"},"pgTemplateEdit":{"type":"string","example":"1"},"pgTemplateDelete":{"type":"string","example":"1"},"pgPersonalizationAdd":{"type":"string","example":"1"},"pgPersonalizationEdit":{"type":"string","example":"1"},"pgPersonalizationDelete":{"type":"string","example":"1"},"pgAutomationManage":{"type":"string","example":"1"},"pgFormEdit":{"type":"string","example":"1"},"pgReportsCampaign":{"type":"string","example":"1"},"pgReportsList":{"type":"string","example":"1"},"pgReportsUser":{"type":"string","example":"1"},"pgReportsTrend":{"type":"string","example":"1"},"pgStartupReports":{"type":"string","example":"1"},"pgStartupGettingstarted":{"type":"string","example":"1"},"pgDeal":{"type":"string","example":"1"},"pgDealDelete":{"type":"string","example":"1"},"pgDealReassign":{"type":"string","example":"1"},"pgDealGroupAdd":{"type":"string","example":"1"},"pgDealGroupEdit":{"type":"string","example":"1"},"pgDealGroupDelete":{"type":"string","example":"1"},"pgSavedResponsesManage":{"type":"string","example":"1"},"sdate":{"type":"string","example":"2018-09-20T10:51:14-05:00"},"reqApproval":{"type":"string","example":"0"},"reqApproval1st":{"type":"string","example":"2"},"reqApprovalNotify":{"type":"string","example":""},"socialdata":{"type":"string","example":"0"},"links":{"type":"object","properties":{"userGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/userGroups"},"groupLimit":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/groupLimit"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/dealGroupGroups"},"listGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/listGroups"},"addressGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/addressGroups"},"automationGroups":{"type":"string","example":"https://:account.api-us1.com/api/3/groups/3/automationGroups"}}},"id":{"type":"string","example":"3"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Group with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Group with id 10"}}}}}}},"deprecated":false},"put":{"summary":"Update a group","description":"","operationId":"update-a-group","x-canonical-resource":"groups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the group to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"group":{"properties":{"title":{"type":"string"},"descript":{"type":"string","description":"Group description"},"pgMessageAdd":{"type":"boolean","description":"Permission for adding messages","default":false},"pgListAdd":{"type":"boolean","description":"Permission for adding lists","default":false},"pgListEdit":{"type":"boolean","description":"Permission for editing lists","default":false},"pgListDelete":{"type":"boolean","description":"Permission for deleting lists","default":false},"pgListHeaders":{"type":"boolean","description":"Permission for managing custom email headers","default":false},"pgListEmailaccount":{"type":"boolean","description":"Permission for managing Unsubscribe By Email","default":false},"pgListBounce":{"type":"boolean","description":"Permission for accessing list bounce settings","default":false},"pgMessageEdit":{"type":"boolean","description":"Permission for editing messages","default":false},"pgMessageDelete":{"type":"boolean","description":"Permission for deleting messages","default":false},"pgMessageSend":{"type":"boolean","description":"Permission for sending messages","default":false},"pgContactAdd":{"type":"boolean","description":"Permission for adding contacts","default":false},"pgContactEdit":{"type":"boolean","description":"Permission for editing contacts","default":false},"pgContactDelete":{"type":"boolean","description":"Permission for deleting contacts","default":false},"pgContactMerge":{"type":"boolean","description":"Permission for merging contacts","default":false},"pgContactImport":{"type":"boolean","description":"Permission for importing contacts","default":false},"pgContactApprove":{"type":"boolean","description":"Permission for approving contacts","default":false},"pgContactExport":{"type":"boolean","description":"Permission for exporting contacts","default":false},"pgContactSync":{"type":"boolean","description":"Permission for syncing contacts","default":false},"pgContactFilters":{"type":"boolean","description":"Permission for managing contact list segments","default":false},"pgContactActions":{"type":"boolean","description":"Permission for managing contact actions","default":false},"pgContactFields":{"type":"boolean","description":"Permission for managing contact custom fields","default":false},"pgGroupAdd":{"type":"boolean","description":"Permission for adding groups","default":false},"pgGroupEdit":{"type":"boolean","description":"Permission for editing groups","default":false},"pgGroupDelete":{"type":"boolean","description":"Permission for deleting groups","default":false},"pgTemplateAdd":{"type":"boolean","description":"Permission for adding templates","default":false},"pgTemplateEdit":{"type":"boolean","description":"Permission for editing templates","default":false},"pgTemplateDelete":{"type":"boolean","description":"Permission for deleting templates","default":false},"pgPersonalizationAdd":{"type":"boolean","description":"Permission for adding personalization tags","default":false},"pgPersonalizationEdit":{"type":"boolean","description":"Permission for editing personalization tags","default":false},"pgPersonalizationDelete":{"type":"boolean","description":"Permission for deleting personalization tags","default":false},"pgAutomationManage":{"type":"boolean","default":false},"pgFormEdit":{"type":"boolean","description":"Permission for editing subscription forms","default":false},"pgReportsCampaign":{"type":"boolean","description":"Permission for viewing campaign reports","default":false},"pgReportsList":{"type":"boolean","description":"Permission for viewing list reports","default":false},"pgReportsUser":{"type":"boolean","description":"Permission for viewing user reports","default":false},"pgStartupReports":{"type":"boolean","description":"Campaign ID of last campaign report viewed to decide whether to show link on startup","default":false},"pgReportsTrend":{"type":"boolean","description":"Permission for viewing trend reports","default":false},"pgStartupGettingstarted":{"type":"boolean","description":"Whether or not to show the \"getting started\" tutorial on overview page","default":false},"pgDeal":{"type":"boolean","description":"Permission for viewing deals","default":false},"pgDealDelete":{"type":"boolean","description":"Permission for deleting deals","default":false},"pgDealReassign":{"type":"boolean","description":"Permission for reassigning deals","default":false},"pgDealGroupAdd":{"type":"boolean","description":"Permission for adding deal groups","default":false},"pgDealGroupEdit":{"type":"boolean","description":"Permission for editing deal groups","default":false},"pgDealGroupDelete":{"type":"boolean","description":"Permission for deleting deals groups","default":false},"pgSavedResponsesManage":{"type":"boolean","description":"Permission for managing saved responses","default":false},"reqApproval":{"type":"boolean","description":"Whether or not this group requires all campaigns to be approved","default":false},"reqApproval1st":{"type":"boolean","description":"Whether or not this group requires first campaign to be approved","default":false},"reqApprovalNotify":{"type":"string","description":"Who to notify for approval related issues (email)"},"socialdata":{"type":"boolean","description":"Whether or not to show social links in campaigns sent from this group","default":false},"pgAccountAdd":{"type":"boolean"},"pgAccountDelete":{"type":"boolean"},"pgAccountEdit":{"type":"boolean"},"pgAccountExport":{"type":"boolean"},"pgAccountImport":{"type":"boolean"},"pgAccountManageCustomField":{"type":"boolean"},"pgAccountNoteAdd":{"type":"boolean"},"pgAccountNoteDelete":{"type":"boolean"},"pgAccountNoteEdit":{"type":"boolean"},"pgAccountReassign":{"type":"boolean"},"pgAutomationRead":{"type":"boolean","description":"Read-only access to automations for the group's users, stored outside the group record. Changing it requires the pg_automation_manage permission; null is treated as not sent."},"pgContactResubscribe":{"type":"boolean"},"pgDealExport":{"type":"boolean"},"pgDealFields":{"type":"boolean"},"pgDealImport":{"type":"boolean"},"pgDealListAll":{"type":"boolean"},"pgDealManageRoles":{"type":"boolean"},"pgDealNoteAdd":{"type":"boolean"},"pgDealNoteDelete":{"type":"boolean"},"pgDealNoteEdit":{"type":"boolean"},"pgInboxManageAvailability":{"type":"boolean"},"pgInboxManageOwnAvailability":{"type":"boolean"},"pgInboxView":{"type":"boolean"},"pgInboxViewAvailability":{"type":"boolean"},"pgLandingPagesAccess":{"type":"boolean"},"pgReportsDeal":{"type":"boolean"},"pgReportsSalesEngagement":{"type":"boolean"},"pgSmsCampaignManage":{"type":"boolean"},"pgSmsCampaignSend":{"type":"boolean"},"pgSmsCampaignView":{"type":"boolean"},"pgSmsKeywordManage":{"type":"boolean"},"pgSmsKeywordView":{"type":"boolean"},"pgSmsRegistration":{"type":"boolean"},"pgSmsReporting":{"type":"boolean"},"pgSmsSendingOptions":{"type":"boolean"},"pgTagManage":{"type":"boolean"},"pgWhatsappCreateFlows":{"type":"boolean"},"pgWhatsappCreateTemplates":{"type":"boolean"},"pgWhatsappDeleteFlows":{"type":"boolean"},"pgWhatsappDeleteTemplates":{"type":"boolean"},"pgWhatsappUpdateFlows":{"type":"boolean"},"pgWhatsappUpdateSettings":{"type":"boolean"},"pgWhatsappUseInbox":{"type":"boolean"},"pgWhatsappViewAllConversations":{"type":"boolean"},"pgWhatsappViewFlows":{"type":"boolean"},"pgWhatsappViewReports":{"type":"boolean"},"pg_web_personalization_manage":{"type":"boolean"}},"required":[],"type":"object"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"group":{"title":"TEST TITLE","descript":"Description Text","pgListAdd":1,"pgListEdit":1,"pgListDelete":1,"pgListHeaders":1,"pgListEmailaccount":1,"pgListBounce":1,"pgMessageAdd":1,"pgMessageEdit":1,"pgMessageDelete":1,"pgMessageSend":1,"pgContactAdd":1,"pgContactEdit":1,"pgContactDelete":1,"pgContactMerge":1,"pgContactImport":1,"pgContactApprove":1,"pgContactExport":1,"pgContactSync":1,"pgContactFilters":1,"pgContactActions":1,"pgContactFields":1,"pgGroupAdd":1,"pgGroupEdit":1,"pgGroupDelete":1,"pgTemplateAdd":1,"pgTemplateEdit":1,"pgTemplateDelete":1,"pgPersonalizationAdd":1,"pgPersonalizationEdit":1,"pgPersonalizationDelete":1,"pgAutomationManage":1,"pgFormEdit":1,"pgReportsCampaign":1,"pgReportsList":1,"pgReportsUser":1,"pgReportsTrend":1,"pgStartupReports":1,"pgStartupGettingstarted":1,"pgDeal":1,"pgDealDelete":1,"pgDealReassign":1,"pgDealGroupAdd":1,"pgDealGroupEdit":1,"pgDealGroupDelete":1,"pgSavedResponsesManage":1,"reqApproval":1,"reqApproval1st":1,"reqApprovalNotify":"johndoe@example.com","socialdata":0}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"group\": {\n        \"title\": \"My Groups Title\",\n        \"p_admin\": 1,\n        \"links\": {\n            \"userGroups\": \"https://:account.api-us1.com/api/:version/groups/7/userGroups\",\n            \"groupLimit\": \"https://:account.api-us1.com/api/:version/groups/7/groupLimit\",\n            \"dealGroupGroups\": \"https://:account.api-us1.com/api/:version/groups/7/dealGroupGroups\",\n            \"listGroups\": \"https://:account.api-us1.com/api/:version/groups/7/listGroups\",\n            \"addressGroups\": \"https://:account.api-us1.com/api/:version/groups/7/addressGroups\",\n            \"automationGroups\": \"https://:account.api-us1.com/api/:version/groups/7/automationGroups\"\n        },\n        \"id\": \"7\"\n    }\n}"}},"schema":{"type":"object","properties":{"group":{"type":"object","properties":{"title":{"type":"string","example":"My Groups Title"},"p_admin":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"userGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/userGroups"},"groupLimit":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/groupLimit"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/dealGroupGroups"},"listGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/listGroups"},"addressGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/addressGroups"},"automationGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/7/automationGroups"}}},"id":{"type":"string","example":"7"}}}}}},"text/plain":{"examples":{"Result":{"value":"{\n    \"group\": {\n        \"title\": \"TEST TITLE\",\n        \"descript\": \"Description Text\",\n        \"unsubscribelink\": \"0\",\n        \"optinconfirm\": \"0\",\n        \"p_admin\": \"1\",\n        \"pgListAdd\": 1,\n        \"pgListEdit\": 1,\n        \"pgListDelete\": 1,\n        \"pgListHeaders\": 1,\n        \"pgListEmailaccount\": 1,\n        \"pgListBounce\": 1,\n        \"pgMessageAdd\": 1,\n        \"pgMessageEdit\": 1,\n        \"pgMessageDelete\": 1,\n        \"pgMessageSend\": 1,\n        \"pgContactAdd\": 1,\n        \"pgContactEdit\": 1,\n        \"pgContactDelete\": 1,\n        \"pgContactMerge\": 1,\n        \"pgContactImport\": 1,\n        \"pgContactApprove\": 1,\n        \"pgContactExport\": 1,\n        \"pgContactSync\": 1,\n        \"pgContactFilters\": 1,\n        \"pgContactActions\": 1,\n        \"pgContactFields\": 1,\n        \"pg_user_add\": \"0\",\n        \"pg_user_edit\": \"0\",\n        \"pg_user_delete\": \"0\",\n        \"pgGroupAdd\": 1,\n        \"pgGroupEdit\": 1,\n        \"pgGroupDelete\": 1,\n        \"pgTemplateAdd\": 1,\n        \"pgTemplateEdit\": 1,\n        \"pgTemplateDelete\": 1,\n        \"pgPersonalizationAdd\": 1,\n        \"pgPersonalizationEdit\": 1,\n        \"pgPersonalizationDelete\": 1,\n        \"pgAutomationManage\": 1,\n        \"pgFormEdit\": 1,\n        \"pgReportsCampaign\": 1,\n        \"pgReportsList\": 1,\n        \"pgReportsUser\": 1,\n        \"pgReportsTrend\": 1,\n        \"pgStartupReports\": 1,\n        \"pgStartupGettingstarted\": 1,\n        \"pgDeal\": 1,\n        \"pgDealDelete\": 1,\n        \"pgDealReassign\": 1,\n        \"pgDealGroupAdd\": 1,\n        \"pgDealGroupEdit\": 1,\n        \"pgDealGroupDelete\": 1,\n        \"pgSavedResponsesManage\": 1,\n        \"sdate\": \"2018-09-29T22:08:36-05:00\",\n        \"reqApproval\": 1,\n        \"reqApproval1st\": 1,\n        \"reqApprovalNotify\": \"johndoe@example.com\",\n        \"socialdata\": \"0\",\n        \"links\": {\n            \"userGroups\": \"https://:account.api-us1.com/api/:version/groups/5/userGroups\",\n            \"groupLimit\": \"https://:account.api-us1.com/api/:version/groups/5/groupLimit\",\n            \"dealGroupGroups\": \"https://:account.api-us1.com/api/:version/groups/5/dealGroupGroups\",\n            \"listGroups\": \"https://:account.api-us1.com/api/:version/groups/5/listGroups\",\n            \"addressGroups\": \"https://:account.api-us1.com/api/:version/groups/5/addressGroups\",\n            \"automationGroups\": \"https://:account.api-us1.com/api/:version/groups/5/automationGroups\"\n        },\n        \"id\": \"5\"\n    }\n}"}},"schema":{"type":"object","properties":{"group":{"type":"object","properties":{"title":{"type":"string","example":"TEST TITLE"},"descript":{"type":"string","example":"Description Text"},"unsubscribelink":{"type":"string","example":"0"},"optinconfirm":{"type":"string","example":"0"},"p_admin":{"type":"string","example":"1"},"pgListAdd":{"type":"integer","example":1,"default":0},"pgListEdit":{"type":"integer","example":1,"default":0},"pgListDelete":{"type":"integer","example":1,"default":0},"pgListHeaders":{"type":"integer","example":1,"default":0},"pgListEmailaccount":{"type":"integer","example":1,"default":0},"pgListBounce":{"type":"integer","example":1,"default":0},"pgMessageAdd":{"type":"integer","example":1,"default":0},"pgMessageEdit":{"type":"integer","example":1,"default":0},"pgMessageDelete":{"type":"integer","example":1,"default":0},"pgMessageSend":{"type":"integer","example":1,"default":0},"pgContactAdd":{"type":"integer","example":1,"default":0},"pgContactEdit":{"type":"integer","example":1,"default":0},"pgContactDelete":{"type":"integer","example":1,"default":0},"pgContactMerge":{"type":"integer","example":1,"default":0},"pgContactImport":{"type":"integer","example":1,"default":0},"pgContactApprove":{"type":"integer","example":1,"default":0},"pgContactExport":{"type":"integer","example":1,"default":0},"pgContactSync":{"type":"integer","example":1,"default":0},"pgContactFilters":{"type":"integer","example":1,"default":0},"pgContactActions":{"type":"integer","example":1,"default":0},"pgContactFields":{"type":"integer","example":1,"default":0},"pg_user_add":{"type":"string","example":"0"},"pg_user_edit":{"type":"string","example":"0"},"pg_user_delete":{"type":"string","example":"0"},"pgGroupAdd":{"type":"integer","example":1,"default":0},"pgGroupEdit":{"type":"integer","example":1,"default":0},"pgGroupDelete":{"type":"integer","example":1,"default":0},"pgTemplateAdd":{"type":"integer","example":1,"default":0},"pgTemplateEdit":{"type":"integer","example":1,"default":0},"pgTemplateDelete":{"type":"integer","example":1,"default":0},"pgPersonalizationAdd":{"type":"integer","example":1,"default":0},"pgPersonalizationEdit":{"type":"integer","example":1,"default":0},"pgPersonalizationDelete":{"type":"integer","example":1,"default":0},"pgAutomationManage":{"type":"integer","example":1,"default":0},"pgFormEdit":{"type":"integer","example":1,"default":0},"pgReportsCampaign":{"type":"integer","example":1,"default":0},"pgReportsList":{"type":"integer","example":1,"default":0},"pgReportsUser":{"type":"integer","example":1,"default":0},"pgReportsTrend":{"type":"integer","example":1,"default":0},"pgStartupReports":{"type":"integer","example":1,"default":0},"pgStartupGettingstarted":{"type":"integer","example":1,"default":0},"pgDeal":{"type":"integer","example":1,"default":0},"pgDealDelete":{"type":"integer","example":1,"default":0},"pgDealReassign":{"type":"integer","example":1,"default":0},"pgDealGroupAdd":{"type":"integer","example":1,"default":0},"pgDealGroupEdit":{"type":"integer","example":1,"default":0},"pgDealGroupDelete":{"type":"integer","example":1,"default":0},"pgSavedResponsesManage":{"type":"integer","example":1,"default":0},"sdate":{"type":"string","example":"2018-09-29T22:08:36-05:00"},"reqApproval":{"type":"integer","example":1,"default":0},"reqApproval1st":{"type":"integer","example":1,"default":0},"reqApprovalNotify":{"type":"string","example":"johndoe@example.com"},"socialdata":{"type":"string","example":"0"},"links":{"type":"object","properties":{"userGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/userGroups"},"groupLimit":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/groupLimit"},"dealGroupGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/dealGroupGroups"},"listGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/listGroups"},"addressGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/addressGroups"},"automationGroups":{"type":"string","example":"https://:account.api-us1.com/api/:version/groups/5/automationGroups"}}},"id":{"type":"string","example":"5"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Group with id 8\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Group with id 8"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a group","description":"","operationId":"delete-a-group-1","x-canonical-resource":"groups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the group to be deleted","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/ideas":{"get":{"summary":"List the account's ideas","description":"Every idea shared from the account, from the Ideas service, with the signed-in user's relationship to each: whether they shared it, whether they follow it, and which team member they are. Internal: backs the Ideas page in Settings.\n\nThe Ideas service stores each person's name as it was when they shared or followed; Hosted replaces it with their current name, adds the Gravatar hash of their login email, and adds the number of users on the account.\n\nOnly for an account that may use Ideas: anywhere else (a reseller account, or one that shows neither ActiveCampaign branding nor the support widget) every Ideas route answers 404 before the body is read. A 4xx the Ideas service answers, other than 401, is passed on with its status and message as `error`; anything else that goes wrong reaching it is a 502.","operationId":"list-all-ideas","responses":{"200":{"description":"The account's ideas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasListResponse"}}}},"404":{"description":"The account may not use Ideas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"Not found"}}}},"502":{"description":"The Ideas service failed, could not be reached, is not configured, or refused Hosted's signature. The message asks the user to try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"We couldn't save that right now. Your text is still here, so try again in a moment."}}}}},"x-canonical-resource":"product_idea","x-internal":true},"post":{"summary":"Share an idea","description":"Records an idea, or a problem, that the signed-in user wants ActiveCampaign to know about, in the Ideas service. Internal: backs the Share an idea dialog of the app.\n\nHosted adds who is sharing from the session (the account ID, name and plan tier; the user ID, email, name and whether they are an admin), the page area when page capture is on, and the Hosted version, the browser user agent, the viewport and the frontend build, then sends the idea to the Ideas service and passes its reply on. Each user may share at most 8 ideas a minute.\n\nOnly for an account that may use Ideas: anywhere else (a reseller account, or one that shows neither ActiveCampaign branding nor the support widget) every Ideas route answers 404 before the body is read. A 4xx the Ideas service answers, other than 401, is passed on with its status and message as `error`; anything else that goes wrong reaching it is a 502.","operationId":"create-an-idea","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasCreateRequest"},"example":{"kind":"IDEA","description":"Change a field on 200 contacts at once.","pagePath":"/app/contacts/12345","viewport":"1440x900","frontendBuild":null}}}},"responses":{"201":{"description":"The idea was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasCreatedResponse"},"example":{"id":"idea_1","status":"NEW","statusLabel":"Received","createdAt":"2026-09-08T15:00:00.000Z"}}}},"400":{"description":"The body is empty or not a JSON object (an errors array), or the Ideas service refused the idea with a 400 (an error message).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/IdeasMalformedBodyResponse"},{"$ref":"#/components/schemas/IdeasErrorResponse"}]},"examples":{"malformed":{"summary":"The body is not JSON","value":{"errors":[{"status":"400","detail":"Could not decode request body."}]}},"refused":{"summary":"The Ideas service refused the idea","value":{"error":"title: too short"}}}}}},"404":{"description":"The account may not use Ideas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"Not found"}}}},"422":{"description":"kind is not IDEA or PROBLEM, description is blank or longer than 20000 characters, title is outside 3 to 140 characters, pagePath, viewport or frontendBuild is too long, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Tell us a little more","source":{"pointer":"/data/attributes/description"}}]}}}},"429":{"description":"The user has shared 8 ideas in the last minute. Nothing was sent to the Ideas service.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"You are sharing ideas faster than we can take them in. Try again in a minute."}}}},"502":{"description":"The Ideas service failed, could not be reached, is not configured, or refused Hosted's signature. The message asks the user to try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"We couldn't save that right now. Your text is still here, so try again in a moment."}}}}},"x-canonical-resource":"product_idea","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/ideas/{ideaId}":{"delete":{"summary":"Delete an idea","description":"Withdraws an idea the signed-in user shared, through the Ideas service, which refuses anyone but the person who shared it. Takes no request body. Internal: backs the Ideas page in Settings.\n\nOnly for an account that may use Ideas: anywhere else (a reseller account, or one that shows neither ActiveCampaign branding nor the support widget) every Ideas route answers 404 before the body is read. A 4xx the Ideas service answers, other than 401, is passed on with its status and message as `error`; anything else that goes wrong reaching it is a 502.","operationId":"delete-an-idea","parameters":[{"name":"ideaId","in":"path","description":"ID of the idea: the id of an entry in List the account's ideas.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9_-]+)$"}}],"responses":{"200":{"description":"The idea was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasDeletedResponse"},"example":{"id":"idea_1","deletedAt":"2026-09-08T16:00:00.000Z"}}}},"404":{"description":"The account may not use Ideas, or the Ideas service answered 404 for this idea.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"Not found"}}}},"502":{"description":"The Ideas service failed, could not be reached, is not configured, or refused Hosted's signature. The message asks the user to try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"We couldn't save that right now. Your text is still here, so try again in a moment."}}}}},"x-canonical-resource":"product_idea","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/ideas/{ideaId}/followers":{"post":{"summary":"Follow an idea","description":"Adds the signed-in user to the followers of an idea, the \"I want this too\" action, through the Ideas service. Internal: backs the Ideas page in Settings.\n\nOnly for an account that may use Ideas: anywhere else (a reseller account, or one that shows neither ActiveCampaign branding nor the support widget) every Ideas route answers 404 before the body is read. A 4xx the Ideas service answers, other than 401, is passed on with its status and message as `error`; anything else that goes wrong reaching it is a 502.","operationId":"follow-an-idea","parameters":[{"name":"ideaId","in":"path","description":"ID of the idea: the id of an entry in List the account's ideas.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9_-]+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasFollowRequest"},"example":{"consentEmail":true}}}},"responses":{"200":{"description":"The user follows the idea.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasFollowResponse"},"example":{"followerCount":2,"isFollowing":true,"team":[{"userId":7,"name":"Pat Lee","isYou":true,"avatarHash":"2f2d6b1e6a3b3a5c4a4d1e7f9c0b8a21"}]}}}},"400":{"description":"The body is empty or not a JSON object. Send {} to follow with the defaults.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasMalformedBodyResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"404":{"description":"The account may not use Ideas, or the Ideas service answered 404 for this idea.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"Not found"}}}},"422":{"description":"consentEmail is not a JSON boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasValidationErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Unexpected type","source":{"pointer":"/data/attributes/consentEmail"}}]}}}},"502":{"description":"The Ideas service failed, could not be reached, is not configured, or refused Hosted's signature. The message asks the user to try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"We couldn't save that right now. Your text is still here, so try again in a moment."}}}}},"x-canonical-resource":"product_idea","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Stop following an idea","description":"Removes the signed-in user from the followers of an idea, through the Ideas service. Takes no request body. Internal: backs the Ideas page in Settings.\n\nOnly for an account that may use Ideas: anywhere else (a reseller account, or one that shows neither ActiveCampaign branding nor the support widget) every Ideas route answers 404 before the body is read. A 4xx the Ideas service answers, other than 401, is passed on with its status and message as `error`; anything else that goes wrong reaching it is a 502.","operationId":"unfollow-an-idea","parameters":[{"name":"ideaId","in":"path","description":"ID of the idea: the id of an entry in List the account's ideas.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9_-]+)$"}}],"responses":{"200":{"description":"The user no longer follows the idea.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasFollowResponse"},"example":{"followerCount":1,"isFollowing":false,"team":[{"userId":9,"name":"Jo Park","isYou":false,"avatarHash":"c3d4a1b2e5f60718293a4b5c6d7e8f90"}]}}}},"404":{"description":"The account may not use Ideas, or the Ideas service answered 404 for this idea.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"Not found"}}}},"502":{"description":"The Ideas service failed, could not be reached, is not configured, or refused Hosted's signature. The message asks the user to try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeasErrorResponse"},"example":{"error":"We couldn't save that right now. Your text is still here, so try again in a moment."}}}}},"x-canonical-resource":"product_idea","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/import/ai/mapping":{"post":{"summary":"Analyse an uploaded import file with AI","description":"Reads the uploaded file of pending import settings and fills the settings in with AI: the field each column maps to, suggested lists and tags, and the platform the file was exported from. The settings must be `pending`; they are `analyzing` while the call runs and `analyzed` when it answers, or back to `pending` when it fails. When the model cannot map the columns, fuzzy matching maps them instead. Internal: Hosted dispatches this to itself after an upload that uses AI analysis.","operationId":"analyze-import-file","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportMappingRequest"}}}},"responses":{"200":{"description":"The settings are analysed; read them with GET /importsettings/{id}. The body is an empty array.","content":{"application/json":{"schema":{"type":"array","items":{},"maxItems":0},"example":[]}}},"404":{"description":"No import settings have this ID.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Import settings not found\".","type":"string","example":"Import settings not found"}},"type":"object"}}}},"409":{"description":"The settings are not `pending`: they are being analysed or have been analysed already.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Import settings cannot be analyzed in the current state\".","type":"string","example":"Import settings cannot be analyzed in the current state"}},"type":"object"}}}},"422":{"description":"`importSettingsId` is missing or blank. The body lists each refused field.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the field.","type":"string","example":"This value should not be blank."},"source":{"description":"Where the refused field is.","properties":{"pointer":{"description":"The name of the field, after `/data/attributes/`.","type":"string","example":"/data/attributes/importSettingsId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The file could not be read or analysed. The settings are back to `pending`.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Failed to analyze CSV\".","type":"string","example":"Failed to analyze CSV"}},"type":"object"}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/import/ai/sample/{id}":{"get":{"summary":"Preview one row of an import","description":"Applies the import settings to one row of the uploaded file, so the user can check the mappings before starting the import: of the first 20 data rows, the one with the most values, with each mapped value formatted, plus the tags and lists the contact would get. Nothing is imported or saved. Internal: backs the contact import UI.","operationId":"retrieve-import-sample-row","parameters":[{"name":"id","in":"path","description":"ID of the import settings, as the upload returned it in `fileMetadata.importSettingsId`.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The previewed row.","content":{"application/json":{"schema":{"required":["sample"],"properties":{"sample":{"$ref":"#/components/schemas/ImportSample","description":"The row as the import would apply it."}},"type":"object"},"example":{"sample":{"fields":[{"id":"email","name":"Email","value":"john.doe@example.com","category":"standard","type":"text","exists":true}],"tags":[{"id":null,"tag":"VIP","aiMapped":false,"exists":false}],"lists":[{"id":123,"name":"Newsletter Subscribers","aiMapped":true,"exists":true}]}}}}},"404":{"description":"No import settings have this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the settings that were not found.","type":"string","example":"ImportSettings not found for id: 550e8400-e29b-41d4-a716-446655440000"}},"type":"object"}}}}},"x-canonical-resource":"import","x-internal":true}},"/import/ai/upload":{"post":{"summary":"Start a contact import from a file in S3","description":"Copies a CSV or Excel file an AI agent stored in S3 into the account's import storage, converts it to CSV, creates the import settings for it and starts analysing its columns with AI after the call answers: poll GET /importsettings/{id} until `state.process` is `analyzed`. The same as POST /import/upload except for where the file comes from; it always uses AI analysis and takes no list IDs. Needs the permission to import contacts. Internal: the AI agents call it with a file a user gave them.","operationId":"upload-import-file-from-s3","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportAIUploadRequest"}}}},"responses":{"200":{"description":"The file is stored and its import settings are created.","content":{"application/json":{"schema":{"required":["success","fileMetadata"],"properties":{"success":{"description":"Always true.","type":"boolean","example":true},"fileMetadata":{"description":"The stored file and the settings created for it.","required":["importSettingsId","filename","totalRows","fileSizeInBytes"],"properties":{"importSettingsId":{"description":"ID of the import settings created for the file. Pass it to GET /importsettings/{id}.","type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"filename":{"description":"The `filename` sent.","type":"string","example":"contacts-2024-01-15.xlsx"},"totalRows":{"description":"Number of data rows in the file, not counting the header row.","type":"integer","example":1250},"fileSizeInBytes":{"description":"Size of the file after conversion to CSV, in bytes.","type":"integer","example":524288}},"type":"object"}},"type":"object"}}}},"400":{"description":"The file was refused: larger than 100 MB, not a CSV or Excel file, an Excel sheet too large to convert, no data row, or first two rows with different column counts.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Why the file was refused.","type":"string","example":"Invalid file type. Only CSV and Excel files (.csv, .xlsx, .xls, .xlsm) are allowed."}},"type":"object"}}}},"403":{"description":"The user may not import contacts.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Always \"Permission denied.\".","type":"string","example":"Permission denied."}},"type":"object"}}}},"422":{"description":"`bucket`, `key` or `filename` is missing or blank. The body lists each refused field.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the field.","type":"string","example":"Filename cannot be empty"},"source":{"description":"Where the refused field is.","properties":{"pointer":{"description":"The name of the field, after `/data/attributes/`.","type":"string","example":"/data/attributes/filename"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The file could not be read from S3, stored, converted or queued for analysis.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Always \"Failed to process uploaded file\".","type":"string","example":"Failed to process uploaded file"}},"type":"object"}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/import/bulk_import":{"post":{"summary":"Bulk import contacts","description":"Import up to 250 contacts in one request. Asynchronous: the response returns a batchId and a successful response only means the import was accepted, not finished — poll GET /import/info with the batchId to confirm it completed before relying on the results. Contacts are matched by email (or by email_hash): existing contacts are updated and new ones are created, so an import is safe when some of the contacts already exist. Lists and tags are set per contact: use each contact's subscribe array to add it to lists, and its tags array to tag it (tags that do not exist are created). There is no request-level list id; one sent outside a contact is ignored. Contacts added to a list this way get list status active. A list that does not exist is skipped quietly. If the contact is already on the list as unconfirmed, previously bounced, previously unsubscribed, or is on the exclusion list, the subscription is skipped and the row is recorded as a partial success: the contact itself is still created or updated, GET /import/info lists it under success, and a callback with detailed_results reports it as a failure with code 104, 116 or 130. Check list membership if it matters. Sending the exact same request body again while the first import of it is still running (or for up to 24 hours if it never finishes) is rejected with 400: the message starts with \"Failed to persist the JSON payload\" and failureReasons[0] starts with \"Duplicate request detected\". Change the body or wait rather than retrying an accepted request unchanged. The status endpoints report failed rows by email only; to receive the reason a row failed, register a callback with detailed_results. Requires the contact import permission. It is the preferred way to create or update many contacts at once, with or without lists and tags.","operationId":"bulk-import-contacts","x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"Content-Type","in":"header","schema":{"type":"string","default":"application/json"},"description":"The body is read as JSON whatever this header says."},{"name":"Api-Token","in":"header","schema":{"type":"string"},"description":"Your API key. Its user needs the contact import permission."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["contacts"],"properties":{"contacts":{"type":"array","description":"The contacts to import: at least 1 and at most 250 per request. A request with more than 250 is rejected with 400 and nothing is queued. Each contact needs an email, or an email_hash of an existing contact, or a phone when enable_contacts_without_email is true. For fewer than about 10 contacts, POST /contact/sync per contact is simpler.","items":{"properties":{"email":{"type":"string","description":"The contact's email address. Used to find an existing contact to update; otherwise a new contact is created. Must be a valid address. Required unless email_hash is given, or phone is given and enable_contacts_without_email is true."},"email_hash":{"type":"string","description":"The hash of an existing contact, as returned in the hash field of GET /contacts. Use it instead of email to update a contact whose email you do not have, or do not want to change; the stored email is kept. A contact must have email or email_hash (or phone with enable_contacts_without_email)."},"first_name":{"type":"string","description":"The contact's first name."},"last_name":{"type":"string","description":"The contact's last name."},"phone":{"type":"string","description":"The contact's phone number, as a string. With enable_contacts_without_email set to true, a contact may be identified by phone alone."},"customer_acct_name":{"type":"string","description":"The name of the account (organization) to link the contact to. Created if it does not exist, and the contact is linked to it."},"tags":{"type":"array","description":"Tag names to apply to the contact. Tags that do not exist yet are created. Tag names cannot contain commas.","default":[],"items":{"type":"string"}},"fields":{"type":"array","description":"Custom field values to set on the contact. Each entry needs the custom field's numeric id and a value. Field ids come from GET /fields. A non-integer id or a missing value fails validation for the whole request (400).","items":{"properties":{"id":{"type":"integer","description":"The ID of the custom field. Custom fields must be referenced by the ID that ActiveCampaign assigns to them. You can retrieve the ID number for a custom field by using the \"List all custom fields\" API call.","format":"int32"},"value":{"type":"string","description":"The value to store. For multi-value fields, separate values with the double-pipe delimiter, for example ||foo||bar||. Values for dropdown, list box, radio and checkbox fields that do not match an existing option are added as new options unless exclude_new_field_options is true."}},"required":["id","value"],"type":"object"}},"subscribe":{"type":"array","description":"Lists to add the contact to, one object per list. This is the only way to put imported contacts on a list; a list id outside a contact is ignored. The contact is added with status active. A list that does not exist is skipped quietly. If the contact is already on the list as unconfirmed, previously bounced, previously unsubscribed, or is on the exclusion list, the row is recorded as a partial success (codes 104 bounced, 116 unsubscribed or unconfirmed, 130 exclusion list) and, for bounced, unsubscribed and excluded contacts, every subscribe entry on that contact is skipped. The contact is still created or updated. GET /import/info counts these rows as success; a callback with detailed_results counts them as failures.","items":{"properties":{"listid":{"type":"string","description":"The id of the list. Find list ids with GET /lists."}},"type":"object"}},"unsubscribe":{"type":"array","description":"Lists to remove the contact from, one object per list.","items":{"properties":{"listid":{"type":"string","description":"The id of the list. Find list ids with GET /lists."}},"type":"object"}},"ip":{"type":"string","description":"The IPv4 address to record as the contact's subscribe and last-seen IP. Optional."},"job_title":{"type":"string","description":"The contact's job title on its account (organization). Only applied on accounts with the accounts feature. Optional."},"open_tracking_optout":{"type":["boolean","integer","string"],"description":"Whether the contact has opted out of pixel-based email open tracking, recorded separately from their consent to receive marketing email. Accepts 1/0, true/false or yes/no, as a JSON boolean, a JSON number or a string; strings are trimmed and case-insensitive. Omitting the field, or sending it blank, leaves the stored value unchanged. The server records the time of the change itself and does not accept a timestamp as input; a repeated value that changes nothing does not move it. Any other value rejects that contact's row with failure code 85 and leaves the rest of the import running. Inert unless the open-tracking opt-out feature is enabled for the account. Optional."},"ua":{"type":"string"}},"type":"object","description":"One contact. Must have email, or email_hash, or phone together with the request-level enable_contacts_without_email option."}},"exclude_automations":{"type":"boolean","default":false,"description":"Set to true so the import does not start automations for the imported contacts. Must be a JSON boolean; any other type is rejected with 422."},"send_webhooks":{"type":"boolean","description":"Set to false to suppress webhooks for the imported contacts. When omitted, contact, custom field and tag webhooks are sent but list subscription webhooks are not; set to true to send list webhooks as well. Must be a JSON boolean; any other type is rejected with 422."},"enable_contacts_without_email":{"type":"boolean","default":false,"description":"Set to true to allow contacts that have a phone number but no email. Each such contact is identified by its phone. Must be a JSON boolean; any other type is rejected with 422."},"exclude_new_field_options":{"type":"boolean","default":false,"description":"Set to true so custom field values that do not match an existing option of a dropdown, list box, radio or checkbox field are not added as new options."},"delete_after":{"type":"string","description":"A date and time after which the import's per-contact status records may be removed. Any format PHP's strtotime understands, for example 2026-12-31 or +30 days. An unparseable value is rejected with 422."},"callback":{"type":"object","description":"Optional. A request the importer makes to your endpoint when the import finishes. This is the only way to receive per-row failure reasons for an API import.","required":["url","requestType"],"properties":{"url":{"type":"string","description":"The URL the importer calls once the import has completed."},"requestType":{"type":"string","description":"GET or POST. Required. Any other value fails validation (400).","default":"POST"},"detailed_results":{"type":"string","description":"Include this key (any value, for example \"true\") to have the callback body carry the results: success and failures counts, an always-present failure_reasons array (empty), and, only when there were failures, a failure_results array with the email, code and message of every row that was not fully imported. Rows that imported but had a list subscription skipped (codes 104, 116, 130) are counted as failures here even though GET /import/info lists them as success. Only meaningful with requestType POST. Presence is what turns it on; the value itself is ignored."},"params":{"type":"array","description":"A list of parameters to include in the callback request. Add each parameter in the form of a key-value pair. For a GET request, each parameter will be appended to the end of the URL in a query string. For a POST request, parameters will be included in the body of the request.","items":{"properties":{"key":{"type":"string","description":"Name of the parameter. Required: an entry without key fails validation."},"value":{"type":"string","description":"Value of the parameter. Required: an entry without value fails validation."}},"type":"object","required":["key","value"],"additionalProperties":false}},"headers":{"type":"array","description":"A list of headers to include in the callback request. Add each header in the form of a key-value pair.","items":{"properties":{"key":{"type":"string","description":"Name of the header. Required: an entry without key fails validation."},"value":{"type":"string","description":"Value of the header. Required: an entry without value fails validation."}},"type":"object","required":["key","value"],"additionalProperties":false}}},"additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"contacts":[{"email":"sam@example.com","first_name":"Sam","last_name":"Example","phone":"555-555-5555","customer_acct_name":"Example Inc","tags":["newsletter","trade show 2026"],"fields":[{"id":1,"value":"foo"},{"id":2,"value":"||foo||bar||baz||"}],"subscribe":[{"listid":1},{"listid":2}],"unsubscribe":[{"listid":3}]}],"exclude_automations":false,"callback":{"url":"https://www.example.com/import-finished","requestType":"POST","detailed_results":"true","params":[{"key":"source","value":"nightly-sync"}],"headers":[{"key":"X-Auth","value":"token"}]}}}}}}},"responses":{"200":{"description":"Accepted and queued. The import has not run yet; poll GET /import/info with the batchId.","content":{"application/json":{"examples":{"Result":{"value":"{\n   \"success\":1,\n   \"queued_contacts\":1,\n   \"batchId\":\"0641fbdd-f62f-4c2c-ba02-3a83d5d11ac9\",\n   \"message\":\"Contact import queued\"\n}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":1,"default":0,"description":"1 when the import was queued."},"queued_contacts":{"type":"integer","example":1,"default":0,"description":"How many contacts were in the request."},"batchId":{"type":"string","example":"0641fbdd-f62f-4c2c-ba02-3a83d5d11ac9","description":"Use this with GET /import/info to check the import's progress and results."},"message":{"type":"string","example":"Contact import queued","description":"Always \"Contact import queued\" on success."}}}}}},"400":{"description":"The request was not queued. Either the body failed validation (message starts with \"JSON payload did not pass validation\"; failureReasons lists each problem: missing or invalid contacts array, more than 250 contacts, a contact without email, a bad email, a bad fields or callback entry), or the exact same body was submitted while an earlier import of it is still running (message starts with \"Failed to persist the JSON payload\" and failureReasons[0] starts with \"Duplicate request detected\").","content":{"application/json":{"examples":{"Validation failed":{"value":"{\"success\":0,\"message\":\"JSON payload did not pass validation. Please fix failureReasons and retry. The import was not queued for processing.\",\"failureReasons\":[{\"contact\":2,\"failureReason\":\"Field 'email' incorrect format\"}]}"},"Duplicate request":{"value":"{\"success\":0,\"message\":\"Failed to persist the JSON payload. Please check failureReason for more information. The import was not queued for processing.\",\"failureReasons\":[\"Duplicate request detected. Please allow the previous import with this information to finish before queueing another.\"]}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0 on an error."},"message":{"type":"string","description":"What went wrong, in one sentence."},"failureReasons":{"type":"array","description":"One entry per problem. A string for request-level problems. For a problem in one contact, an object with contact (1-based position in the contacts array) and failureReason. For a problem in a callback params or headers entry, an object with param or header (0-based position) and failureReason.","items":{}}}}}}},"403":{"description":"The API user does not have the contact import permission.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"This account does not have permission to access this endpoint.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0."},"message":{"type":"string","description":"Why the request was refused."}}}}}},"413":{"description":"The request body is 400,000 bytes or larger. Send fewer contacts per request.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"JSON payload size too big: 412345. The import was not queued for processing.\",\"failureReasons\":[\"Payload size for batches must be less than 400000 bytes. Try sending fewer contacts.\"]}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0 on an error."},"message":{"type":"string","description":"What went wrong, in one sentence."},"failureReasons":{"type":"array","description":"One entry per problem. A string for request-level problems. For a problem in one contact, an object with contact (1-based position in the contacts array) and failureReason. For a problem in a callback params or headers entry, an object with param or header (0-based position) and failureReason.","items":{}}}}}}},"422":{"description":"A request-level option has the wrong type: exclude_automations, send_webhooks or enable_contacts_without_email is not a boolean, or delete_after is not a date.","content":{"application/json":{"examples":{"Result":{"value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid Input Parameter\",\"detail\":\"exclude_automations is not an acceptable value\"}]}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"description":"HTTP status code."},"title":{"type":"string","example":"Invalid Input Parameter","description":"Short name of the error."},"detail":{"type":"string","description":"What went wrong."}}},"description":"One entry per problem."}}}}}},"429":{"description":"Too many import requests this minute for this account. Requests with a single contact are counted against their own, separate limit. Batch contacts into fewer, larger requests or retry after a minute.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"Rate limit exceeded.\",\"failureReasons\":[\"Up to 100 imports may be requested per minute. Please batch contacts into larger requests, or retry this request in a minute.\"]}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0 on an error."},"message":{"type":"string","description":"What went wrong, in one sentence."},"failureReasons":{"type":"array","description":"One entry per problem. A string for request-level problems. For a problem in one contact, an object with contact (1-based position in the contacts array) and failureReason. For a problem in a callback params or headers entry, an object with param or header (0-based position) and failureReason.","items":{}}}}}}},"503":{"description":"The import could not be created. Retry the request.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"Failed to create import. Please retry request.\",\"failureReasons\":[\"Unable to create import process\"]}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0 on an error."},"message":{"type":"string","description":"What went wrong, in one sentence."},"failureReasons":{"type":"array","description":"One entry per problem. A string for request-level problems. For a problem in one contact, an object with contact (1-based position in the contacts array) and failureReason. For a problem in a callback params or headers entry, an object with param or header (0-based position) and failureReason.","items":{}}}}}}}},"deprecated":false},"get":{"summary":"Summarize recent API bulk imports by day","description":"Summarize this account's API bulk imports from the last 7 days: for each day, how many batches and contacts are still outstanding and how many completed. Only imports submitted through POST /import/bulk_import are counted; imports started from the app's import tool or by integrations never appear here (use GET /import/history for those). There is no per-batch or per-contact detail and no error information, so this cannot explain why an import failed; for one batch use GET /import/info with its batchId. Both arrays are empty when nothing was imported through the API in the last 7 days. A batch that stalled and has a failed chunk is left out of outstanding.","operationId":"bulk-import-status-list","x-canonical-resource":"import","responses":{"200":{"description":"Per-day totals for the last 7 days.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"outstanding\":[\n    {\"forDate\":\"2021-06-01\",\"batches\":\"333\",\"contacts\":\"83250\"}\n  ],\n  \"recentlyCompleted\":[\n    {\"forDate\":\"2021-06-01\",\"batches\":\"17\",\"contacts\":\"4250\"},\n    {\"forDate\":\"2021-06-02\",\"batches\":\"50\",\"contacts\":\"12500\"}\n  ]\n}"}},"schema":{"type":"object","properties":{"outstanding":{"type":"array","description":"Days (by submission date) with imports that have not finished, with the number of batches and the number of contacts still to process.","items":{"type":"object","properties":{"forDate":{"type":"string","example":"2026-09-01","description":"Calendar day, YYYY-MM-DD."},"batches":{"type":"string","example":"333","description":"Number of import requests that day, as a string."},"contacts":{"type":"string","example":"83250","description":"Number of contacts, as a string."}}}},"recentlyCompleted":{"type":"array","description":"Days (by completion date) with finished imports, with the number of batches and the number of contacts processed.","items":{"type":"object","properties":{"forDate":{"type":"string","example":"2026-09-01","description":"Calendar day, YYYY-MM-DD."},"batches":{"type":"string","example":"333","description":"Number of import requests that day, as a string."},"contacts":{"type":"string","example":"83250","description":"Number of contacts, as a string."}}}}}}}}}},"deprecated":false}},"/import/execute":{"post":{"summary":"Start a contact import","description":"Starts importing the uploaded file with the settings sent and answers as soon as the import is queued; contacts are imported in the background, so follow the import with GET /import/status/{processId}. The settings sent are validated, used for the import and stored over the saved settings. They must be in the `analyzed` state: the call moves them to `submitting` and then `submitted`, so a second call for the same settings answers 409, and a failure before the import is queued moves them back to `analyzed`. Lists and custom fields the settings name without an ID are created, and tags without an ID are added as the contacts are imported; each needs the matching permission. Internal: backs the contact import UI.","operationId":"execute-import","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportExecutionRequest"}}}},"responses":{"200":{"description":"The import is queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportExecutionResponse"},"example":{"success":true,"message":"The import process has been initiated.","processId":12345,"filename":"contacts-2024-01-15.xlsx","totalContacts":1250}}}},"400":{"description":"The mappings cannot be imported: there are none, a column is mapped twice or not at all, a column index is outside the file, a field is mapped twice, or neither email nor (where phone-only contacts are on) phone is mapped. Nothing was imported.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Why the mappings were refused.","type":"string","example":"A column must be mapped to the email field."}},"type":"object"}}}},"403":{"description":"The settings create a tag, a custom field or a list and the user may not manage tags, manage custom fields or add lists, or they create a list and the account has no access to lists.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Which permission is missing.","type":"string","example":"You do not have permission to execute this import. Tag management permission is required."}},"type":"object"}}}},"404":{"description":"Something the import refers to does not exist, such as the stored settings.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Always \"The requested import resource was not found\".","type":"string","example":"The requested import resource was not found"}},"type":"object"}}}},"409":{"description":"The settings are not in the `analyzed` state: analysis has not finished, or the import has been started already.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Why the import cannot start.","type":"string","example":"Import cannot be executed. Import must be in 'analyzed' state."}},"type":"object"}}}},"422":{"description":"The settings are missing, or one of their keys is missing or has the wrong type. The body lists each refused field.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the field; \"Unexpected type\" when it could not be read as the type it needs.","type":"string","example":"This value should not be blank."},"source":{"description":"Where the refused field is.","properties":{"pointer":{"description":"The path of the field, after `/data/attributes/`.","type":"string","example":"/data/attributes/settings.displayFilename"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The import could not be started, for example because of a database error.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Always \"Import execution failed due to database error\" or \"An unexpected error occurred during import execution\".","type":"string","example":"An unexpected error occurred during import execution"}},"type":"object"}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/import/file/{filename}":{"get":{"summary":"Download a file from import storage","description":"Streams a file from the account's import storage as an attachment, by the name it is stored under: the uploaded file, `{id}-original.csv` (the settings' `savedFilename`), or the formatted copy the import writes, `{id}-formatted.csv`. The content type follows the extension: `text/csv` for `.csv`, `application/json` for `.json`, `application/octet-stream` otherwise. Internal: backs the contact import UI.","operationId":"download-import-file","parameters":[{"name":"filename","in":"path","description":"Name the file is stored under in the account's import storage.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The file, with `Content-Disposition: attachment` naming it.","headers":{"Content-Disposition":{"description":"`attachment` with the file name.","schema":{"type":"string"}},"Content-Length":{"description":"Size of the file in bytes.","schema":{"type":"integer"}}},"content":{"text/csv":{"schema":{"description":"A `.csv` file.","type":"string","format":"binary"}},"application/json":{"schema":{"description":"A `.json` file, sent as stored.","type":"string","format":"binary"}},"application/octet-stream":{"schema":{"description":"Any other file.","type":"string","format":"binary"}}}},"404":{"description":"No file has this name in the account's import storage.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"File not found\".","type":"string","example":"File not found"}},"type":"object"}}}},"500":{"description":"The file could not be read.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Error retrieving file\".","type":"string","example":"Error retrieving file"}},"type":"object"}}}}},"x-canonical-resource":"import","x-internal":true}},"/import/history":{"get":{"summary":"List contact imports made from the app or by integrations","description":"List this account's contact imports that were started from the app's import tool (CSV or file uploads) or by an integration, newest first, with how many rows imported, partly imported, or failed. Use it to answer questions about an import a user ran in the app, then use GET /import/history/{importId}/{type} to get the rows that failed and why. Imports submitted through POST /import/bulk_import do not appear here; check those with GET /import/info. Users outside the main user group only see imports from their own group. Paginated with limit (1 to 100, default 20) and offset; meta.total is the number of imports visible to the caller. Requires the contact import permission.","operationId":"list-import-history","x-canonical-resource":"import","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":100},"description":"Number of imports to return. Defaults to 20; the maximum is 100. Values outside 1 to 100 are rejected with 422."},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0},"description":"Number of imports to skip. Use with limit to page through the history."}],"responses":{"200":{"description":"One page of imports, newest first, with paging metadata.","content":{"application/json":{"examples":{"Result":{"value":"{\"importHistory\":[{\"id\":\"12\",\"processid\":\"3401\",\"name\":\"contacts.csv\",\"created\":\"2026-09-01 14:03:12\",\"total\":\"500\",\"percent\":100,\"success\":\"480\",\"partial\":\"15\",\"failed\":\"5\",\"status\":\"finished\",\"username\":\"admin\"}],\"meta\":{\"total\":1,\"page_input\":{\"limit\":20,\"offset\":0}}}"}},"schema":{"type":"object","properties":{"importHistory":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"12","description":"The import id. Use it with GET /import/history/{importId}/{type}."},"processid":{"type":"string","example":"3401","description":"Internal process id. 0 for imports made by an integration."},"name":{"type":"string","example":"contacts.csv","description":"The uploaded file name, or the integration's label."},"created":{"type":"string","example":"2026-09-01 14:03:12","description":"When the import was started, in the calling user's timezone."},"total":{"type":"string","example":"500","description":"Rows in the import."},"percent":{"type":"integer","example":100,"description":"How far the import has run, as a whole number from 0 to 100. 100 when status is finished."},"success":{"type":"string","example":"480","description":"Rows imported fully."},"partial":{"type":"string","example":"15","description":"Rows imported, but a list subscription was skipped (bounced, unsubscribed, unknown list, or on the exclusion list)."},"failed":{"type":"string","example":"5","description":"Rows not imported at all."},"status":{"type":"string","example":"finished","description":"waiting (not started), processing, or finished. If the import's process record has since been removed, status shows waiting while percent is 100; treat percent 100 as finished."},"username":{"type":"string","example":"admin","description":"The user who started the import. null for integration imports."}}},"description":"The imports, newest first, one entry per import."},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"description":"Total imports visible to the caller."},"page_input":{"type":"object","properties":{"limit":{"type":"integer","example":20,"description":"The limit used for this page."},"offset":{"type":"integer","example":0,"description":"The offset used for this page."}},"description":"The limit and offset used for this page."}},"description":"Paging information."}}}}}},"403":{"description":"The API user does not have the contact import permission.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"This account does not have permission to access this endpoint.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0."},"message":{"type":"string","description":"Why the request was refused."}}}}}},"422":{"description":"limit or offset is out of range.","content":{"application/json":{"examples":{"Result":{"value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid attribute\",\"detail\":\"This value should be between 1 and 100.\",\"source\":{\"pointer\":\"/data/attributes/limit\"}}]}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"description":"HTTP status code."},"title":{"type":"string","example":"Invalid attribute","description":"Short name of the error."},"detail":{"type":"string","description":"What went wrong."},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/limit","description":"Which query parameter was rejected."}},"description":"Which request field the problem is in, as a pointer."}}},"description":"One entry per problem."}}}}}}},"deprecated":false}},"/import/history/{importId}/{type}":{"get":{"summary":"List the rows of an app or integration import that failed or were only partly imported, with reasons","description":"For one import from GET /import/history, list the rows that did not import (type failure) or that imported but had a list subscription skipped (type partial), each with its email and the reason. This is the endpoint to use when a user asks why their import had errors. It covers imports started from the app or by an integration only; imports submitted through POST /import/bulk_import are not in the history and their reasons are only available through the import callback. Returns at most 500 rows, oldest first, and there is no paging beyond that. For partial rows the reason starts with \"Imported under ID: <contact id>\", followed by the skipped reason in parentheses. Integration imports have no per-row log and return an empty list. An import id that does not exist, or that the caller is not allowed to see, is a 404. Requires the contact import permission.","operationId":"list-import-failed-rows","x-canonical-resource":"import","parameters":[{"name":"importId","in":"path","required":true,"schema":{"type":"integer"},"description":"The import id, from the id field of GET /import/history."},{"name":"type","in":"path","required":true,"schema":{"type":"string","enum":["failure","partial"]},"description":"failure for rows that were not imported; partial for rows that were imported but had a list subscription skipped. Contacts on the exclusion list appear under failure for imports run by the older import path and under partial for current ones, so check both when looking for excluded contacts. Anything else is a 422."}],"responses":{"200":{"description":"The matching rows with their reasons, at most 500.","content":{"application/json":{"examples":{"Failure rows":{"value":"{\"failedRows\":[{\"email\":\"\",\"reason\":\"Empty row - No Email Address.\"},{\"email\":\"sam@example.com\",\"reason\":\"Row skipped - It is on exclusion list.\"},{\"email\":\"pat@example.com\",\"reason\":\"Contact Limit Exceeded.\"}]}"},"Partial rows":{"value":"{\"failedRows\":[{\"email\":\"sam@example.com\",\"reason\":\"Imported under ID: 123 (This contact has unsubscribed from a list in the past and so will not be imported into lists, but their data will be updated if applicable)\"}]}"}},"schema":{"type":"object","properties":{"failedRows":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"The row's email address."},"reason":{"type":"string","description":"Why the row failed or was only partly imported, in plain text."}}},"description":"The rows of this import that failed (type failure) or were only partly imported (type partial). At most 500 rows are returned."}}}}}},"403":{"description":"The API user does not have the contact import permission.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"This account does not have permission to access this endpoint.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0."},"message":{"type":"string","description":"Why the request was refused."}}}}}},"404":{"description":"No import with that id is visible to the caller.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"Import id 12 not found.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0."},"message":{"type":"string","description":"Why the request was refused."}}}}}},"422":{"description":"type is not failure or partial.","content":{"application/json":{"examples":{"Result":{"value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid Input Parameter\",\"detail\":\"Type must be 'failure' or 'partial'.\"}]}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"description":"HTTP status code."},"title":{"type":"string","description":"Short name of the error."},"detail":{"type":"string","description":"What went wrong."}}},"description":"One entry per problem."}}}}}}},"deprecated":false}},"/import/info":{"get":{"summary":"Bulk import status info","description":"Check the status of one API bulk import using the batchId returned by POST /import/bulk_import. Imports run in the background, so call this after submitting one to confirm it completed: an import is only finished when status is completed, and a successful response to the import request alone does not mean the contacts were created. If the import has not finished yet, wait and poll again rather than resubmitting the same contacts. success lists the ids of the contacts that were created or updated; failure lists the email of each row that was not imported, with no reason. To get failure reasons, register a callback with detailed_results when submitting the import. This endpoint knows nothing about imports started from the app or by integrations; use GET /import/history for those. Requires the contact import permission.","operationId":"bulk-import-status-info","x-canonical-resource":"import","parameters":[{"name":"batchId","in":"query","schema":{"type":"string"},"required":true,"description":"The batch id returned when the import was submitted. Required. An unknown batch id returns status false with empty lists rather than an error."}],"responses":{"200":{"description":"The batch's status and per-contact outcome so far.","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"status\":\"completed\",\n  \"success\":[\"123\",\"124\",\"125\",\"126\"],\n  \"failure\":[\n    \"invalid.email@invalidDomain\", \n    \"invalid'character@example.com\"\n  ]\n}"}},"schema":{"type":"object","properties":{"status":{"type":["string","boolean"],"example":"completed","description":"waiting (accepted, not started), claimed or active (running), completed, failed, or interrupted (stopped before every contact was processed; the counts below are partial). false when the batch has not been picked up yet, which is normal for a few seconds after submitting."},"success":{"type":"array","items":{"type":"string","example":"123"},"description":"Ids of the contacts created or updated so far, as strings. Includes contacts whose list subscription was skipped (partial success). Empty until the import starts."},"failure":{"type":"array","items":{"type":"string","example":"invalid.email@invalidDomain"},"description":"Emails of the rows that were not imported. Only the email is given, not the reason."}}}}}},"400":{"description":"batchId was not given.","content":{"application/json":{"examples":{"Bad Request":{"value":"{\"success\":0,\"message\":\"'batchId' is a required field.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"default":0,"description":"Always 0."},"message":{"type":"string","example":"'batchId' is a required field.","description":"Why the request was refused."}}}}}},"403":{"description":"The API user does not have the contact import permission.","content":{"application/json":{"examples":{"Result":{"value":"{\"success\":0,\"message\":\"This account does not have permission to access this endpoint.\"}"}},"schema":{"type":"object","properties":{"success":{"type":"integer","example":0,"description":"Always 0."},"message":{"type":"string","description":"Why the request was refused."}}}}}}},"deprecated":false}},"/import/status/{processId}":{"get":{"summary":"Retrieve the progress of an import","description":"How far an import started by POST /import/execute has got, read from its process record. Any background process of the account is answered, not only imports. Internal: backs the contact import UI.","operationId":"retrieve-import-status","parameters":[{"name":"processId","in":"path","description":"ID of the import process, as POST /import/execute returned it.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The progress.","content":{"application/json":{"schema":{"required":["import"],"properties":{"import":{"$ref":"#/components/schemas/ImportStatusResponse","description":"The progress of the process."}},"type":"object"},"example":{"import":{"id":12345,"status":"processing","totalRows":1250,"processedRows":750,"created":"2024-01-15 10:30:00"}}}}},"404":{"description":"No process has this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the process that was not found.","type":"string","example":"No Result found for Process with id 12345"}},"type":"object"}}}}},"x-canonical-resource":"import","x-internal":true}},"/import/upload":{"post":{"summary":"Upload a file to import contacts from","description":"Stores a CSV or Excel file sent as `multipart/form-data`, converts it to CSV, creates the import settings for it and starts analysing its columns. With `useAiAnalysis=true`, the default, the analysis runs with AI after the call answers: poll GET /importsettings/{id} until `state.process` is `analyzed`. With `useAiAnalysis=false` the columns are mapped by fuzzy matching before the call answers, and no lists or tags are suggested. Internal: backs the contact import UI.","operationId":"upload-import-file","parameters":[{"name":"useAiAnalysis","in":"query","description":"`true` analyses the file with AI after the upload answers: poll GET /importsettings/{id} until `state.process` is `analyzed`. `false` maps the columns by fuzzy matching before the upload answers, with no list or tag suggestions.","schema":{"type":"string","default":"true","enum":["true","false"]},"example":"false"},{"name":"listIds[]","in":"query","description":"IDs of existing lists chosen for the import, one `listIds[]` per list; each must be a positive integer. Stored as the settings' `listIds`. With AI analysis, `lists` is filled with these lists instead of suggestions; with `useAiAnalysis=false`, `lists` starts empty either way.","schema":{"type":"array","items":{"type":"string"}},"example":["3","17"]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"required":["file"],"properties":{"file":{"description":"The file: `.csv`, `.xlsx`, `.xls` or `.xlsm`, at most 100 MB, with a header row and at least one data row.","type":"string","format":"binary"}},"type":"object"}}}},"responses":{"200":{"description":"The file is stored and its import settings are created.","content":{"application/json":{"schema":{"required":["success","fileMetadata"],"properties":{"success":{"description":"Always true.","type":"boolean","example":true},"fileMetadata":{"description":"The stored file and the settings created for it.","required":["importSettingsId","filename","totalRows","fileSizeInBytes"],"properties":{"importSettingsId":{"description":"ID of the import settings created for the file. Pass it to GET /importsettings/{id}.","type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"filename":{"description":"Name of the file as the user uploaded it.","type":"string","example":"contacts-2024-01-15.xlsx"},"totalRows":{"description":"Number of data rows in the file, not counting the header row.","type":"integer","example":1250},"fileSizeInBytes":{"description":"Size of the file after conversion to CSV, in bytes.","type":"integer","example":524288}},"type":"object"}},"type":"object"}}}},"400":{"description":"No file was sent, or the file was refused: larger than 100 MB, not a CSV or Excel file, an Excel sheet too large to convert, no data row, or first two rows with different column counts.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Why the file was refused; \"No files were uploaded.\" when there is no `file` part.","type":"string","example":"CSV cannot be processed: file must contain at least a header row and one data row."}},"type":"object"}}}},"422":{"description":"`useAiAnalysis` is not `true` or `false`, or a `listIds[]` value is not a positive integer. The body lists each refused parameter.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused parameter.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the parameter.","type":"string","example":"useAiAnalysis must be true or false."},"source":{"description":"Where the refused parameter is.","properties":{"pointer":{"description":"The name of the parameter, after `/data/attributes/`.","type":"string","example":"/data/attributes/useAiAnalysis"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The file could not be stored, converted or analysed.","content":{"application/json":{"schema":{"properties":{"success":{"description":"Always false.","type":"boolean","example":false},"message":{"description":"Always \"Failed to process uploaded file\".","type":"string","example":"Failed to process uploaded file"}},"type":"object"}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/importsettings/{id}":{"get":{"summary":"Retrieve the settings of an import","description":"The stored settings of an import being prepared: the file, its column mappings, the lists and tags, the options and the lifecycle state. Poll it after an upload that uses AI analysis until `state.process` is `analyzed`. Only the user who uploaded the file can read them. Internal: backs the contact import UI.","operationId":"retrieve-import-settings","parameters":[{"name":"id","in":"path","description":"ID of the import settings, as the upload returned it in `fileMetadata.importSettingsId`.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The settings.","content":{"application/json":{"schema":{"required":["settings"],"properties":{"settings":{"$ref":"#/components/schemas/ImportSettings","description":"The stored settings."}},"type":"object"}}}},"404":{"description":"No import settings have this ID (the body is `{\"message\": \"ImportSettings not found for id: …\"}`), or another user uploaded the file (the body is an `errors` array with one 404 entry).","content":{"application/json":{"schema":{"oneOf":[{"properties":{"message":{"description":"Names the settings that were not found.","type":"string","example":"ImportSettings not found for id: 550e8400-e29b-41d4-a716-446655440000"}},"type":"object"},{"properties":{"errors":{"description":"One entry.","type":"array","items":{"properties":{"status":{"description":"Always 404.","type":"integer","example":404},"title":{"description":"The translated name of the status.","type":"string","example":"Not Found"}},"type":"object"}}},"type":"object"}]}}}}},"x-canonical-resource":"import","x-internal":true},"put":{"summary":"Update the settings of an import","description":"Replaces the stored settings of an import being prepared with the settings sent, typically the ones GET /importsettings/{id} returned with the user's changes to mappings, lists, tags, options or `state.currentPage`. `id`, `savedFilename`, `sessionId`, `totalRows`, `source`, `account`, `url`, `processId`, `userId` and `generatedBy` keep their stored values; every other key is replaced, `state.process` included, so send back the value you read. Only the user who uploaded the file can update them. Internal: backs the contact import UI.","operationId":"update-import-settings","parameters":[{"name":"id","in":"path","description":"ID of the import settings, as the upload returned it in `fileMetadata.importSettingsId`.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSettingsUpdateRequest"}}}},"responses":{"200":{"description":"The settings as stored.","content":{"application/json":{"schema":{"required":["settings"],"properties":{"settings":{"$ref":"#/components/schemas/ImportSettings","description":"The stored settings."}},"type":"object"}}}},"404":{"description":"No import settings have this ID (the body is `{\"message\": \"ImportSettings not found for id: …\"}`), or another user uploaded the file (the body is an `errors` array with one 404 entry).","content":{"application/json":{"schema":{"oneOf":[{"properties":{"message":{"description":"Names the settings that were not found.","type":"string","example":"ImportSettings not found for id: 550e8400-e29b-41d4-a716-446655440000"}},"type":"object"},{"properties":{"errors":{"description":"One entry.","type":"array","items":{"properties":{"status":{"description":"Always 404.","type":"integer","example":404},"title":{"description":"The translated name of the status.","type":"string","example":"Not Found"}},"type":"object"}}},"type":"object"}]}}}},"422":{"description":"The settings are missing, or one of their keys is missing or has the wrong type. The body lists each refused field.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the field; \"Unexpected type\" when it could not be read as the type it needs.","type":"string","example":"This value should not be blank."},"source":{"description":"Where the refused field is.","properties":{"pointer":{"description":"The path of the field, after `/data/attributes/`.","type":"string","example":"/data/attributes/settings.mappings[0].column"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/industryOpenTrends":{"get":{"summary":"Retrieve campaign open benchmarks for the account's industry","description":"Open counts across the industry the account named during onboarding, by day of the month, day of the week and hour of the day, read from per-industry benchmark files kept in file storage. An account with no industry on record gets the benchmarks of the \"other\" category. Lines of a file with no opens, or labelled 0, are left out, so a list can be shorter than its period. Internal: backs the recommended send times on the campaign calendar.","operationId":"retrieve-industry-open-trends","responses":{"200":{"description":"The three benchmark series. A list is empty when its file has no usable lines.","content":{"application/json":{"schema":{"required":["monthly","weekly","hourly"],"properties":{"monthly":{"description":"Opens by day of the month, in the order of the file.","type":"array","items":{"required":["label","hits"],"properties":{"label":{"description":"The bucket, as written in the first column of the benchmark file: the day of the month.","type":"string","example":"1"},"hits":{"description":"Opens recorded for this bucket across the industry, from the second column of the benchmark file. Always above 0: lines with no opens are left out, as are lines labelled 0.","type":"integer","example":749}},"type":"object"}},"weekly":{"description":"Opens by day of the week, in the order of the file.","type":"array","items":{"required":["label","hits"],"properties":{"label":{"description":"The bucket, as written in the first column of the benchmark file: the day of the week, such as monday.","type":"string","example":"monday"},"hits":{"description":"Opens recorded for this bucket across the industry, from the second column of the benchmark file. Always above 0: lines with no opens are left out, as are lines labelled 0.","type":"integer","example":3120}},"type":"object"}},"hourly":{"description":"Opens by hour of the day, in the order of the file.","type":"array","items":{"required":["label","hits"],"properties":{"label":{"description":"The bucket, as written in the first column of the benchmark file: the hour of the day.","type":"string","example":"9"},"hits":{"description":"Opens recorded for this bucket across the industry, from the second column of the benchmark file. Always above 0: lines with no opens are left out, as are lines labelled 0.","type":"integer","example":1410}},"type":"object"}}},"type":"object"},"example":{"monthly":[{"label":"1","hits":749},{"label":"2","hits":750}],"weekly":[{"label":"monday","hits":3120},{"label":"tuesday","hits":3480}],"hourly":[{"label":"9","hits":1410},{"label":"10","hits":1655}]}}}},"500":{"description":"A benchmark file for the industry could not be opened.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Something went wrong on our end. Please try again later\".","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-internal":true}},"/init":{"get":{"summary":"Retrieve the request context for app start-up","description":"The cell, account ID, environment and traffic source the platform routed this request with, and whether it came from an internal network address. The front ends call it first at start-up, for example to decide whether to start error reporting. Every value comes from request headers and the client address; nothing is read from the account. The traffic source is repeated in an `X-Traffic-Source` response header. Internal: backs the app start-up.","operationId":"retrieve-init-context","parameters":[{"name":"X-Hosted-Cell","in":"header","description":"Name of the cell serving the request. Normally set by the platform edge gateway in front of Hosted; read as received.","required":false,"schema":{"type":"string"},"example":"product-aws-use1-p-1"},{"name":"X-Hosted-Account-Id","in":"header","description":"ID of the account the request is for. Normally set by the platform edge gateway in front of Hosted; read as received.","required":false,"schema":{"type":"string"},"example":"12345"},{"name":"X-Traffic-Source","in":"header","description":"Where the request entered the platform, such as `external` or `internal`. Normally set by the platform edge gateway in front of Hosted; read as received. Defaults to `unknown`.","required":false,"schema":{"type":"string"},"example":"external"}],"responses":{"200":{"description":"The request context","headers":{"X-Traffic-Source":{"description":"The `trafficSource` value of the body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitData"},"example":{"environment":"production","cell":"product-aws-use1-p-1","accountId":"12345","trafficSource":"external","isInternalIp":false}}}},"500":{"description":"Building the context failed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always `An exception occurred.`","type":"string","example":"An exception occurred."}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/initiatives":{"post":{"tags":["Business Goals"],"summary":"Create a business goal","description":"Creates a business goal and links the conversion given in conversionId to it, with the goalType and goalValue target when they are given. Answers 201 with the goal. If the goal is created but the conversion cannot be linked, the goal is kept and the answer is 207 with the goal and a conversionError message. A name that already belongs to a goal or folder (a label in the API) is answered with 500 and an error message, not 409.","operationId":"create-a-business-goal","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInitiativeRequest"}}}},"responses":{"201":{"description":"The business goal was created.","content":{"application/json":{"schema":{"required":["initiative"],"properties":{"initiative":{"$ref":"#/components/schemas/InitiativeResource","description":"The business goal that was created."}},"type":"object"}}}},"207":{"description":"The business goal was created but the conversion could not be linked to it.","content":{"application/json":{"schema":{"required":["initiative","conversionError"],"properties":{"initiative":{"$ref":"#/components/schemas/InitiativeResource","description":"The business goal that was created."},"conversionError":{"description":"Why the conversion could not be linked.","type":"string","example":"Conversion not found"}},"type":"object"}}}},"422":{"description":"A field is invalid: label or color is missing or blank, conversionId is missing or does not match a conversion, targetEndDate is blank, useTargetEndDate is not numeric, or goalType is not 1 or 2."},"500":{"description":"The business goal could not be created, for example because the name is already used.","content":{"application/json":{"schema":{"required":["error"],"properties":{"error":{"description":"What went wrong.","type":"string","example":"Initiative or label with name \"Grow the newsletter list\" already exists"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":false,"x-bulk-operation":false},"get":{"tags":["Business Goals"],"summary":"List all business goals","description":"Returns the account's business goals, active by default or archived with `isArchived=1`, newest first unless `orders` says otherwise. Results are paginated with `limit` and `page`. `meta` carries the account's total number of active goals and of archived goals. Optional flags add each goal's association counts and linked conversions. Query parameter names are accepted in camelCase or snake_case (`isArchived` or `is_archived`).","operationId":"list-all-business-goals","parameters":[{"name":"limit","in":"query","description":"Number of business goals per page, 1 to 100.","required":false,"schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"page","in":"query","description":"Page to return, starting at 1.","required":false,"schema":{"type":"integer","default":1}},{"name":"isArchived","in":"query","description":"1 to list archived business goals, 0 to list active ones.","required":false,"schema":{"type":"integer","default":0,"enum":[0,1]}},{"name":"search","in":"query","description":"Only business goals whose name contains this text.","required":false,"schema":{"type":"string"}},{"name":"includeAssociationCounts","in":"query","description":"When true, each business goal carries the number of automations, campaigns, forms and SMS broadcasts in its folder (labeled with it in the API) (automationLabelCount, campaignLabelCount, formLabelCount, smsLabelCount). Accepts true or 1 for yes, false or 0 for no.","required":false,"schema":{"type":"string","default":"false"}},{"name":"includeConversionLabels","in":"query","description":"When true, each business goal carries its linked conversions in conversionLabels (conversion folders in the UI). Accepts true or 1 for yes, false or 0 for no.","required":false,"schema":{"type":"string","default":"false"}},{"name":"includeAssets","in":"query","description":"Accepted for compatibility with `GET /businessGoals/data`, but has no effect on this endpoint.","required":false,"schema":{"type":"string","default":"false","enum":["true","false"]}},{"name":"useOverviewConfig","in":"query","description":"When true, results are limited to and ordered by the account's Overview goals configuration, falling back to favorited goals, instead of the normal listing. Accepts true or 1 for yes, false or 0 for no.","required":false,"schema":{"type":"string","default":"false"}},{"name":"orders","in":"query","description":"A single column-to-direction mapping, such as `orders[created_timestamp]=DESC`. Only the first key is used. The column must be one of `folder`, `updated_timestamp` or `created_timestamp`; the direction is `ASC` or `DESC`, case-insensitive. Any other column or direction is rejected with 422.","style":"deepObject","explode":true,"schema":{"maxProperties":1,"minProperties":1,"properties":{"folder":{"type":"string","enum":["ASC","DESC"]},"updated_timestamp":{"type":"string","enum":["ASC","DESC"]},"created_timestamp":{"type":"string","enum":["ASC","DESC"]}},"type":"object","default":{"created_timestamp":"DESC"},"additionalProperties":false}},{"name":"filters","in":"query","description":"Equality filters keyed by field, such as `filters[source]=1`. `goal_type`, `goal_value` and `conversion_target_status` match against the goal's linked conversion; every other key matches the business goal itself. Empty and null values are ignored. A key outside the list is rejected with 422.","style":"deepObject","explode":true,"schema":{"properties":{"id":{"type":"integer"},"groupid":{"type":"integer"},"folder":{"type":"string"},"color":{"type":"string"},"created_timestamp":{"type":"string"},"updated_timestamp":{"type":"string"},"created_by":{"type":"integer"},"updated_by":{"type":"integer"},"description":{"type":"string"},"is_initiative":{"type":"integer","enum":[0,1]},"is_archived":{"type":"integer","enum":[0,1]},"archived_date":{"type":"string"},"use_target_end_date":{"type":"integer","enum":[0,1]},"target_end_date":{"type":"string"},"source":{"type":"integer","enum":[0,1,2,3,4]},"template":{"type":"string"},"goal_type":{"type":"integer"},"goal_value":{"type":"number"},"conversion_target_status":{"type":"string"}},"type":"object","default":{},"additionalProperties":false}}],"responses":{"200":{"description":"The requested page of business goals and the account totals.","content":{"application/json":{"schema":{"required":["initiatives","meta"],"properties":{"initiatives":{"description":"The business goals on this page.","type":"array","items":{"$ref":"#/components/schemas/InitiativeResource"}},"meta":{"description":"Totals for the whole account.","required":["total","totalArchived"],"properties":{"total":{"description":"Number of business goals matching this request, or of active goals when archived goals were requested.","type":["integer","string"],"example":3},"totalArchived":{"description":"Number of business goals matching this request when archived goals were requested, otherwise of archived goals.","type":["integer","string"],"example":1}},"type":"object"}},"type":"object"}}}},"422":{"description":"A query parameter is invalid: `limit` is not 1 to 100, `isArchived` is not 0 or 1, or `orders` or `filters` use an unsupported key."}},"deprecated":false,"x-canonical-resource":"business_goal"}},"/initiatives/buildbusinessgoal":{"post":{"summary":"Build a business goal from a schema","description":"Creates a business goal (and its associated segment/conversion tracking) from a structured schema, typically LLM-generated. The internal shape of the schema parameter is not fully reverse-engineered -- known: schema.businessGoal.name must be present.","operationId":"build-a-business-goal","requestBody":{"content":{"application/json":{"schema":{"required":["schema"],"properties":{"schema":{"description":"A JSON-encoded string (double-encoded, not a nested object) describing the business goal to build. Confirmed shape fragment: {\"businessGoal\": {\"name\": string, ...}, ...}. Full schema not yet documented.","type":"string"}},"type":"object"}}}},"responses":{"201":{"description":"201","content":{"application/json":{"schema":{"properties":{"success":{"description":"True when the business goal was built.","type":"boolean","example":true},"message":{"description":"Confirms the business goal was built.","type":"string","example":"Business goal initiative built successfully"},"data":{"description":"Initiative build details; shape not fully confirmed.","type":"object"}},"type":"object"}}}},"500":{"description":"500","content":{"application/json":{"schema":{"properties":{"success":{"description":"False when the business goal could not be built.","type":"boolean","example":false},"error":{"description":"Known cases: contains 'already exists' when a goal with that name exists; contains 'Failed to generate segment from AI service' when the associated segment couldn't be created.","type":"string"}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"business_goal","x-destructive":false,"x-bulk-operation":false}},"/initiatives/bulkArchive":{"put":{"tags":["Business Goals"],"summary":"Archive multiple business goals","description":"Archives each business goal in ids, one at a time. A failure for one id does not stop the others and is not reported individually: the answer is 200 even when some or all ids fail, so compare failed_count with total_processed. An id counts as failed when no business goal has it or archiving it errors; a goal that is already archived counts as archived. An empty or missing ids is answered with 422 and nothing is archived.","operationId":"archive-multiple-business-goals","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ids"],"properties":{"ids":{"description":"Ids of the business goals to archive. Must contain at least one id.","type":"array","items":{"type":"integer"},"minItems":1,"example":[12,13,14]}},"type":"object"}}}},"responses":{"200":{"description":"Every id was attempted. Check failed_count for ids that could not be archived.","content":{"application/json":{"schema":{"required":["message","archived_count","failed_count","total_processed"],"properties":{"message":{"description":"Summary naming how many goals were archived.","type":"string","example":"Bulk archive completed. 2 business goals archived successfully."},"archived_count":{"description":"Number of ids now archived, including goals that were already archived.","type":"integer","example":2},"failed_count":{"description":"Number of ids that could not be archived, for example because no goal has that id.","type":"integer","example":1},"total_processed":{"description":"Number of ids in the request, which is archived_count plus failed_count.","type":"integer","example":3}},"type":"object"}}}},"422":{"description":"ids is missing or empty."}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true}},"/initiatives/bulkDelete":{"delete":{"tags":["Business Goals"],"summary":"Delete multiple business goals (QA cleanup)","description":"QA test-cleanup tooling, not a customer API. Permanently deletes each business goal in ids, together with its links to automations, campaigns, forms and conversions. Business goals are normally archived, never deleted, so the call is refused with 403 unless source is qa. Ids that match no business goal are skipped without error, and the answer is the same 200 whether or not anything was deleted. An empty or missing ids is answered with 422. The request is a DELETE with a JSON body.","operationId":"delete-multiple-business-goals","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["source","ids"],"properties":{"source":{"description":"Must be qa. Any other value, or none, is refused with 403.","type":"string","enum":["qa"],"example":"qa"},"ids":{"description":"Ids of the business goals to delete. Must contain at least one id.","type":"array","items":{"type":"integer"},"minItems":1,"example":[12,13]}},"type":"object"}}}},"responses":{"200":{"description":"Every id was processed. Ids that matched no business goal were skipped.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Confirmation message.","type":"string","example":"Initiatives deleted successfully"}},"type":"object"}}}},"403":{"description":"source is not qa. Business goals can not be deleted, only archived."},"422":{"description":"ids is missing or empty."}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/initiatives/import":{"post":{"tags":["Business Goals"],"summary":"Import a business goal from a recipe","description":"Creates a business goal from the personalized recipe whose hash is given in template, together with the conversion, segment and conversion trigger the recipe describes, and links the conversion to the goal. A goal whose name is already taken is created with a number after it, such as Name(1). With source prepopulated, a recipe that already has a goal is not imported again: the call answers 200 with a message instead, and a new goal is also made a favorite on the Overview page. The recipe's personalization must be done; a recipe that is not is answered with 500, and an unknown hash with 404. Meant for the Goals page and the account's own automatic setup, and expected to move to a recipe-specific endpoint.","operationId":"import-a-business-goal-from-a-recipe","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportInitiativeRequest"}}}},"responses":{"200":{"description":"Only with source prepopulated: a goal already exists for this recipe, so nothing was imported.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Says a goal already exists for the recipe hash.","type":"string","example":"Initiative already exists for recipe hash 3KP9Mla"}},"type":"object"}}}},"201":{"description":"The business goal was created from the recipe.","content":{"application/json":{"schema":{"required":["initiative"],"properties":{"initiative":{"$ref":"#/components/schemas/InitiativeResource","description":"The business goal that was created."}},"type":"object"}}}},"404":{"description":"No recipe has this template hash."},"409":{"description":"The goal already exists, for a source other than prepopulated. Name clashes are renamed instead, so this is not normally returned.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Why the import was refused.","type":"string"}},"type":"object"}}}},"422":{"description":"template is blank, or source is not one of the listed values."},"500":{"description":"The import failed, for example because the recipe is not personalized yet. The message is the raw error text.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"The error message of the failure.","type":"string","example":"Recipe has not completed personalization for hash 3KP9Mla"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/initiatives/{initiativeId}":{"put":{"summary":"Update a business goal","operationId":"update-a-business-goal","parameters":[{"name":"initiativeId","in":"path","description":"The business goal's id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"All fields optional; only supplied fields are updated. Fields are flat on the request body -- not wrapped in an `initiative` key.","properties":{"label":{"description":"Business goal name.","type":"string"},"description":{"description":"Description of the business goal.","type":"string"},"targetEndDate":{"description":"Required if useTargetEndDate is set to 1.","type":"string","format":"date"},"useTargetEndDate":{"description":"Sent as 0/1, not a JSON boolean.","type":"integer","enum":[0,1]}},"type":"object"}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"initiative":{"$ref":"#/components/schemas/InitiativeResource","description":"The business goal after the update."}},"type":"object"}}}},"403":{"description":"403 -- for example the business goal is archived"},"404":{"description":"404"},"409":{"description":"409 -- conflict"}},"deprecated":false,"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false},"get":{"summary":"Retrieve a business goal","description":"Retrieves a business goal (internally an Initiative / Folder row).","operationId":"retrieve-a-business-goal","parameters":[{"name":"initiativeId","in":"path","description":"The business goal's id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"includeAssociationCounts","in":"query","description":"When true, the business goal carries the number of automations, campaigns, forms and SMS broadcasts in its folder (labeled with it in the API) (automationLabelCount, campaignLabelCount, formLabelCount, smsLabelCount). Accepts true or 1 for yes, false or 0 for no.","schema":{"type":"string","default":"false"}},{"name":"includeConversionLabels","in":"query","description":"When true, the business goal carries its linked conversions in conversionLabels (conversion folders in the UI). Accepts true or 1 for yes, false or 0 for no.","schema":{"type":"string","default":"false"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"required":["initiative"],"properties":{"initiative":{"$ref":"#/components/schemas/InitiativeResource","description":"The business goal."}},"type":"object"}}}},"404":{"description":"404","content":{"application/json":{"schema":{"properties":{"error":{"description":"Says the business goal was not found.","type":"string","example":"Initiative not found"}},"type":"object"}}}}},"deprecated":false,"x-canonical-resource":"business_goal"}},"/initiatives/{initiativeId}/archive":{"put":{"tags":["Business Goals"],"summary":"Archive a business goal","description":"Archives the business goal. Business goals cannot be deleted, only archived, and an archived goal can no longer be updated. Archiving a goal that is already archived changes nothing and still answers 200. The request has no body.","operationId":"archive-a-business-goal","parameters":[{"name":"initiativeId","in":"path","description":"Id of the business goal to archive.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"},"example":12}],"responses":{"200":{"description":"The business goal is archived.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Confirmation naming the archived goal.","type":"string","example":"Initiative with id 12 archived successfully"}},"type":"object"}}}},"404":{"description":"No business goal has this id.","content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"Names the id that was not found.","type":"string","example":"Initiative not found for id: 12"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false}},"/kafka/deferred":{"post":{"summary":"Re-publish a deferred Kafka write","description":"Internal: the relay target for Kafka writes Hosted could not make when it first tried, not a customer API. When Hosted defers a write to the Kafka REST proxy, it queues the proxy request body for the queue relay (QHS), which later POSTs it here as the account; Hosted then publishes each record to the topic through the account's current Kafka client. Used for Avro-encoded messages, such as the automation block processing log.\n\nDuring an account maintenance window nothing is published and the answer is 503, so the relay tries again later. A record the proxy rejects is not reported back: once the records have been handed to the client the answer is 200.","operationId":"publish-deferred-kafka-records","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KafkaDeferralRequest"},"example":{"key_schema_id":null,"value_schema_id":null,"records":[{"key":"12345","value":"AAAAAAEGZm9v"}],"topic":"automation.fact.block-processing-log.1"}}}},"responses":{"200":{"description":"The records were handed to the Kafka client. The body is a fixed sentence.","content":{"text/html":{"schema":{"type":"string","example":"Kafka deferred request handled"}}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"HTTP status code as a string, \"400\".","type":"string","example":"400"},"detail":{"description":"Why the body was refused: \"Request body is empty.\", \"Could not decode request body.\" or that it did not decode to an object.","type":"string","example":"Request body is empty."}},"type":"object"}}},"type":"object"}}}},"422":{"description":"topic is missing, empty or not a string; records is missing or empty; or a record has no value, a value or key that is not a string, or a field other than key and value.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"One error per failed check.","type":"array","items":{"required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed, for example \"This value should not be blank.\", \"topic must be a string.\", \"This field is missing.\" or \"This field was not expected.\".","type":"string","example":"This value should not be blank."},"source":{"description":"The field that failed the check.","properties":{"pointer":{"description":"The field, as /data/attributes/<field>; a record field is named like records[0][value].","type":"string","example":"/data/attributes/topic"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"503":{"description":"The account is in a maintenance window. Nothing was published; the relay retries later.","content":{"text/html":{"schema":{"type":"string","example":"Deferring Kafka request due to maintenance window"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/kafka/increment-deferred":{"post":{"summary":"Re-publish a deferred Kafka increment write","description":"Internal: the relay target for increment intents Hosted could not publish when it first tried, not a customer API. When a direct publish of increment intents to the Kafka REST proxy fails in a way worth retrying, Hosted queues the proxy request body on a dedicated queue; the queue relay (QHS) later POSTs it here as the account, and Hosted publishes each record to the topic as JSON. The JSON counterpart of Re-publish a deferred Kafka write, which takes Avro-encoded records.\n\nUnlike that endpoint, a record the proxy rejects is reported: the answer is then 503, so the relay retries the whole request and, after repeated failures, moves it to its dead-letter queue. Records that were already published are published again on the retry; the consumer drops them by their event_id.","operationId":"publish-deferred-kafka-increment-records","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KafkaIncrementDeferralRequest"},"example":{"records":[{"key":"12345-42","value":{"event_id":"6f1c2b0e-8a4d-4f3e-9b7a-2d5c1e0f9a11","account_id":12345,"table":"em_series","row_id":42,"column":"entered","delta":1,"write_path":"aggregated"}}],"topic":"hosted.fact.increment.series.0"}}}},"responses":{"200":{"description":"Every record was published. The body is a fixed sentence.","content":{"text/html":{"schema":{"type":"string","example":"Increment deferred request handled"}}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"required":["status","detail"],"properties":{"status":{"description":"HTTP status code as a string, \"400\".","type":"string","example":"400"},"detail":{"description":"Why the body was refused: \"Request body is empty.\", \"Could not decode request body.\" or that it did not decode to an object.","type":"string","example":"Request body is empty."}},"type":"object"}}},"type":"object"}}}},"422":{"description":"topic is missing, empty or not a string; records is missing or empty; or a record has no value, a value that is not an object, a key that is not a string, or a field other than key and value.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"description":"One error per failed check.","type":"array","items":{"required":["status","title"],"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"Which check failed, for example \"This value should not be blank.\", \"topic must be a string.\", \"This field is missing.\" or \"This field was not expected.\".","type":"string","example":"This value should not be blank."},"source":{"description":"The field that failed the check.","properties":{"pointer":{"description":"The field, as /data/attributes/<field>; a record field is named like records[0][value].","type":"string","example":"/data/attributes/topic"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"503":{"description":"Nothing was published because the account is in a maintenance window (\"Deferring increment Kafka request due to maintenance window\"), or at least one record was rejected by the proxy (\"Increment deferred re-publish failed\"). The relay retries later.","content":{"text/html":{"schema":{"type":"string","example":"Increment deferred re-publish failed"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/labels":{"get":{"summary":"List labels","description":"Internal. Lists the labels of the account. When neither orders nor order is given, they are sorted by name; when orders is given but has no key that is used, they come back in no set order. Initiatives are left out by default: they are listed only when orders[is_initiative] has a non-empty value. Each label carries its links; the association counts are added with include_association_counts=1.","operationId":"list-labels","x-canonical-resource":"label","parameters":[{"name":"ids","in":"query","description":"Comma-separated IDs of the labels to return. Returns only those labels and sets the limit to their number, in place of limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of labels to return. Default 20, maximum 100; a larger number returns 100, and the string null returns up to 1000. A number of 0 or less returns every match, and offset is then not applied.","schema":{"type":["integer","string"],"default":20}},{"name":"offset","in":"query","description":"Number of labels to skip, for paging.","schema":{"type":"integer","default":0}},{"name":"all","in":"query","description":"When present, with any value, for example 1, returns every match: limit and offset are not applied.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Returns only labels whose name contains this text. Case is not considered. The text is not escaped: % matches any text and _ matches any single character. search=0 or an empty value applies no filter.","schema":{"type":"string"}},{"name":"orders","in":"query","style":"deepObject","explode":true,"description":"Sort order, as orders[key]=asc or orders[key]=desc; any value other than desc sorts ascending. Keys: folder (the name), created_timestamp, is_initiative, and with include_association_counts=1 also campaign_label_count, form_label_count, automation_label_count and sms_label_count (only when the account has SMS). Other keys are not used, and when no key is used the labels come back in no set order instead of by name. Giving orders[is_initiative] a non-empty value also lists initiatives, leaving out archived ones unless is_archived is 1. orders[selected_ids][]=ID, repeated, puts the labels with those IDs first and the rest after, each group by name; it replaces the other sort keys.","schema":{"type":"object","additionalProperties":{"type":["string","array"]}}},{"name":"is_archived","in":"query","description":"Read only together with orders[is_initiative]. When 1, archived initiatives are listed too.","schema":{"type":"integer","enum":[0,1]}},{"name":"include_association_counts","in":"query","description":"When 1, adds campaignLabelCount, formLabelCount and automationLabelCount to each label, and smsLabelCount when the account has SMS.","schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"The labels on this page, and the total that match","content":{"application/json":{"schema":{"type":"object","properties":{"labels":{"type":"array","description":"The labels on this page","items":{"$ref":"#/components/schemas/Label"}},"meta":{"type":"object","description":"Paging information","properties":{"total":{"type":"string","description":"Number of labels that match, across all pages, as a numeric string","example":"1"}}}}},"example":{"labels":[{"groupid":"3","label":"Spring launch","color":"edf0f7","createdTimestamp":"2026-10-15T10:52:26-05:00","updatedTimestamp":"2026-10-15T10:52:26-05:00","created_by":"1","updated_by":"1","description":"","isInitiative":"0","isArchived":"0","archivedDate":null,"useTargetEndDate":"0","targetEndDate":null,"source":"0","template":"","links":{"formLabels":"https://:account.api-us1.com/api/:version/labels/3/formLabels","automationLabels":"https://:account.api-us1.com/api/:version/labels/3/automationLabels","campaignFolders":"https://:account.api-us1.com/api/:version/labels/3/campaignFolders","conversionFolders":"https://:account.api-us1.com/api/:version/labels/3/conversionFolders"},"id":"3"}],"meta":{"total":"1"}}}}}},"x-internal":true},"post":{"summary":"Create a label","description":"Internal. Creates a label. The name is required and must not be used by any other label or initiative; case and accents are not considered. Before the check, HTML entities in label and color are decoded, HTML tags are removed and spaces are trimmed. When color is missing or empty, it is set to edf0f7. description is optional and is cleaned the same way; it must be 500 characters or fewer. The response holds only the values that were saved: label, color, description when sent, the timestamps, groupid, created_by, updated_by, links and id.","operationId":"create-a-label","x-canonical-resource":"label","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["label"],"properties":{"label":{"$ref":"#/components/schemas/LabelInput"}}},"example":{"label":{"label":"Spring launch","color":"f85e4e"}}}}},"responses":{"201":{"description":"The label was created","content":{"application/json":{"schema":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/Label"}}},"example":{"label":{"label":"Spring launch","color":"f85e4e","createdTimestamp":"2026-10-15T10:52:26-05:00","updatedTimestamp":"2026-10-15T10:52:26-05:00","groupid":"3","created_by":"1","updated_by":"1","links":{"formLabels":"https://:account.api-us1.com/api/:version/labels/3/formLabels","automationLabels":"https://:account.api-us1.com/api/:version/labels/3/automationLabels","campaignFolders":"https://:account.api-us1.com/api/:version/labels/3/campaignFolders","conversionFolders":"https://:account.api-us1.com/api/:version/labels/3/conversionFolders"},"id":"3"}}}}},"400":{"$ref":"#/components/responses/LabelBadBody"},"422":{"$ref":"#/components/responses/LabelInvalid"}},"x-internal":true}},"/labels/bulkDelete":{"delete":{"summary":"Delete labels in bulk","description":"Deletes the labels with the given IDs, one at a time. Initiatives and archived labels are deleted too. An ID with no label is skipped, and the request still answers 200. For each label it also deletes the label's campaign, automation, form and conversion associations, and asks the SMS service to drop the label from its broadcasts. For an initiative it also removes it from favorites, deletes its recommendations (unless it was made from a recipe), its conversion performance summaries and its automation relations.","operationId":"bulk-delete-labels","parameters":[{"name":"ids","in":"query","description":"Comma-separated IDs of the labels to delete. Each part is read as a whole number. It can also be sent as a form-encoded body field; the query string wins when both are sent. A JSON body is not read. Without it, or with 0, nothing is deleted.","schema":{"type":"string"},"example":"3,4"}],"responses":{"200":{"description":"The labels were deleted, or there was nothing to delete","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"N Labels deleted successfully\", where N is the number of IDs that had a label. \"Nothing to delete\" when no ID had a label.","type":"string","example":"2 Labels deleted successfully"},"meta":{"properties":{"success":{"description":"Always true","type":"boolean","example":true}},"type":"object"}},"type":"object"},"example":{"message":"2 Labels deleted successfully","meta":{"success":true}}}}}},"x-canonical-resource":"label","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/labels/filters":{"get":{"summary":"List the labels used by one asset type","description":"Lists the labels that at least one asset of the chosen type has, one row per label, for filtering assets by label. Archived labels are left out. Initiatives are left out unless include_initiatives is 1. Rows are sorted by label name; with include_initiatives=1, labels come first and initiatives after. For reltype sms the label links come from the SMS service; when it cannot be reached, labels is empty.","operationId":"list-label-filters","parameters":[{"name":"reltype","in":"query","description":"Asset type whose labels are listed. Any other value returns an empty list, or 422 when relid is also sent.","schema":{"type":"string","default":"automations","enum":["automations","campaigns","forms","sms"]}},{"name":"relid","in":"query","description":"ID of one asset of that type. When sent and not 0, only the labels of that asset are listed.","schema":{"type":"integer","default":0},"example":12},{"name":"all","in":"query","description":"When 1, returns every row: page and limit are not applied.","schema":{"type":"integer","default":0,"enum":[0,1]}},{"name":"page","in":"query","description":"Page number, starting at 1. Rows skipped are (page - 1) times limit.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","description":"Rows per page. There is no maximum. 0 returns every row.","schema":{"type":"integer","default":20,"minimum":0}},{"name":"include_initiatives","in":"query","description":"When 1, initiatives are listed too, after the labels.","schema":{"type":"integer","default":0,"enum":[0,1]}}],"responses":{"200":{"description":"The labels on this page","content":{"application/json":{"schema":{"properties":{"labels":{"description":"The labels on this page","type":"array","items":{"description":"One label and one of its associations of the chosen type","properties":{"id":{"description":"ID of one of the label's associations, as a numeric string. It is not the label ID.","type":"string"},"seriesid":{"description":"ID of one automation with this label, as a numeric string. For reltype automations.","type":"string"},"campaignid":{"description":"ID of one campaign with this label, as a numeric string. For reltype campaigns.","type":"string"},"formid":{"description":"ID of one form with this label, as a numeric string. For reltype forms.","type":"string"},"broadcastid":{"description":"ID of one SMS broadcast with this label, as a numeric string. For reltype sms.","type":"string"},"folderid":{"description":"ID of the label, as a numeric string","type":"string"},"created_timestamp":{"description":"When the association was made (Y-m-d H:i:s). Not sent for reltype sms.","type":"string"},"updated_timestamp":{"description":"When the association last changed (Y-m-d H:i:s). Not sent for reltype sms.","type":"string"},"created_by":{"description":"ID of the user who made the association, as a numeric string. Not sent for reltype sms.","type":["string","null"]},"updated_by":{"description":"ID of the user who last changed the association, as a numeric string. Not sent for reltype sms.","type":["string","null"]},"label_count":{"description":"Always \"0\". Sent only for reltype sms.","type":"string"},"title":{"description":"Name of the label","type":"string"},"color":{"description":"Color of the label, as a hex code without #","type":"string"},"relCount":{"description":"Number of associations of the chosen type that the label has, as a numeric string. With relid, only those of that asset.","type":"string"},"isInitiative":{"description":"\"1\" when the label is an initiative, else \"0\"","type":"string","enum":["0","1"]},"isArchived":{"description":"Always \"0\": archived labels are left out","type":"string","enum":["0"]}},"type":"object"}}},"type":"object"},"example":{"labels":[{"id":"41","seriesid":"12","folderid":"3","created_timestamp":"2026-10-15 10:52:26","updated_timestamp":"2026-10-15 10:52:26","created_by":"1","updated_by":"1","title":"Spring launch","color":"edf0f7","relCount":"2","isInitiative":"0","isArchived":"0"}]}}}},"422":{"description":"relid was sent with a reltype that is not supported","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"description":"The HTTP status, as a string","type":"string","example":"422"},"detail":{"description":"Always \"Invalid relType\"","type":"string","example":"Invalid relType"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"422","detail":"Invalid relType"}]}}}}},"x-canonical-resource":"label","x-internal":true}},"/labels/{id}":{"get":{"summary":"Retrieve a label","description":"Internal. Returns one label. An initiative is not returned: its ID answers 404.","operationId":"retrieve-a-label","x-canonical-resource":"label","parameters":[{"$ref":"#/components/parameters/LabelId"}],"responses":{"200":{"description":"The label","content":{"application/json":{"schema":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/Label"}}},"example":{"label":{"groupid":"3","label":"Spring launch","color":"edf0f7","createdTimestamp":"2026-10-15T10:52:26-05:00","updatedTimestamp":"2026-10-15T10:52:26-05:00","created_by":"1","updated_by":"1","description":"","isInitiative":"0","isArchived":"0","archivedDate":null,"useTargetEndDate":"0","targetEndDate":null,"source":"0","template":"","links":{"formLabels":"https://:account.api-us1.com/api/:version/labels/3/formLabels","automationLabels":"https://:account.api-us1.com/api/:version/labels/3/automationLabels","campaignFolders":"https://:account.api-us1.com/api/:version/labels/3/campaignFolders","conversionFolders":"https://:account.api-us1.com/api/:version/labels/3/conversionFolders"},"id":"3"}}}}},"404":{"description":"No label has this ID, or the ID is an initiative. The two bodies differ.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Names the record that was not found. Sent when no label has this ID.","example":"No Result found for Folder with id 3"},"error":{"type":"string","description":"Always \"Label not found\". Sent when the ID is an initiative.","example":"Label not found"}}},"example":{"error":"Label not found"}}}}},"x-internal":true},"put":{"summary":"Update a label","description":"Internal. Changes the name, color or description of a label. PATCH does the same. Only label, color and description can be changed; fields left out keep their value. An empty description clears it. The description must be 500 characters or fewer. An initiative can be changed this way too. The new name must not be used by any other label or initiative; case and accents are not considered. Before the check, HTML entities in label, color and description are decoded, HTML tags are removed and spaces are trimmed. An empty color is set to edf0f7. A body without a label object changes only updatedTimestamp and updated_by. The response is the stored label with the changes.","operationId":"update-a-label","x-canonical-resource":"label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/LabelId"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/LabelInput"}}},"example":{"label":{"label":"Spring launch","color":"f85e4e"}}}}},"responses":{"200":{"description":"The label after the change","content":{"application/json":{"schema":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/Label"}}},"example":{"label":{"groupid":"3","label":"Spring launch","color":"f85e4e","createdTimestamp":"2026-10-15T10:52:26-05:00","updatedTimestamp":"2026-10-16T09:12:40-05:00","created_by":"1","updated_by":"1","description":"","isInitiative":"0","isArchived":"0","archivedDate":null,"useTargetEndDate":"0","targetEndDate":null,"source":"0","template":"","links":{"formLabels":"https://:account.api-us1.com/api/:version/labels/3/formLabels","automationLabels":"https://:account.api-us1.com/api/:version/labels/3/automationLabels","campaignFolders":"https://:account.api-us1.com/api/:version/labels/3/campaignFolders","conversionFolders":"https://:account.api-us1.com/api/:version/labels/3/conversionFolders"},"id":"3"}}}}},"400":{"$ref":"#/components/responses/LabelBadBody"},"403":{"description":"The request has no current user.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string","example":"403"},"detail":{"type":"string","description":"Always Forbidden","example":"Forbidden"}}}}}},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"$ref":"#/components/responses/LabelNotFound"},"422":{"$ref":"#/components/responses/LabelInvalid"}},"x-internal":true},"delete":{"summary":"Delete a label","description":"Internal. Deletes a label. Its links to forms, automations, campaigns and conversions are deleted too, and the SMS service is asked to remove it from SMS broadcasts. When the SMS service request fails, the label is still deleted. Each linked conversion's stored performance summary is cleared. The forms, automations, campaigns, conversions and broadcasts themselves are not deleted. Initiatives cannot be deleted this way.","operationId":"delete-a-label","x-canonical-resource":"label","x-destructive":true,"x-bulk-operation":false,"parameters":[{"$ref":"#/components/parameters/LabelId"}],"responses":{"200":{"description":"The label was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object","description":"Empty object"},"example":{}}}},"403":{"description":"The database delete failed. The body is a plain-text message, not JSON, even though the Content-Type is application/json.","content":{"application/json":{"schema":{"type":"string","description":"Message saying the label could not be deleted"}}}},"404":{"$ref":"#/components/responses/LabelNotFound"}},"x-internal":true}},"/labels/{labelId}/upgrade":{"put":{"summary":"Upgrade a label to an initiative","description":"Makes the label an initiative: isInitiative becomes 1. The label keeps its ID and its campaign, automation and form links. Archived labels can be upgraded too. On upgrade, created_by and createdTimestamp are reset to the current user and time, updated_by and updatedTimestamp are set, and an empty color becomes edf0f7. label, color, description, targetEndDate and useTargetEndDate are saved only on upgrade, and only when sent and not empty. label and color are saved without the cleaning that PUT /labels/{id} applies; description is saved as sent. If the label is already an initiative, it is not changed and the answer is still 200. In both cases, when conversionId is sent, that conversion is linked to the initiative. If the link fails, the upgrade is kept and the answer is 207 with conversionError.","operationId":"upgrade-a-label","parameters":[{"name":"labelId","in":"path","description":"ID of the label to upgrade","required":true,"schema":{"type":"integer"},"example":3}],"requestBody":{"description":"Read as JSON. A body that is not JSON is the same as no body.","required":false,"content":{"application/json":{"schema":{"properties":{"label":{"description":"New name. Must not be the name of another label or initiative; case is not considered.","type":"string","example":"Spring launch"},"color":{"description":"New color, as a 6-character hex code without #","type":"string","example":"f85e4e"},"description":{"description":"Description of the initiative, up to 500 characters","type":"string","example":"Grow sign-ups before the spring launch"},"targetEndDate":{"description":"Target end date, as a date or date and time with an optional offset. It is stored without an offset, in the server time zone.","type":"string","example":"2026-12-31"},"useTargetEndDate":{"description":"1 to use targetEndDate, 0 not to","type":"integer","enum":[0,1],"example":1},"conversionId":{"description":"ID of a visible conversion to link to the initiative, as a number or numeric string","type":["integer","string"],"example":"9"},"goalType":{"description":"Goal for the conversion: 1 for total count, 2 for total revenue. Read only with conversionId. Any other value links the conversion without a goal. For 2, the goal currency is the conversion's currency.","type":["integer","string"],"example":"1"},"goalValue":{"description":"Target for the goal. Read only with conversionId and a goalType of 1 or 2. Left out or empty, it is 0.","type":["integer","string"],"example":"100"}},"type":"object"},"example":{"conversionId":"9","goalType":"1","goalValue":"100","useTargetEndDate":1,"targetEndDate":"2026-12-31"}}}},"responses":{"200":{"description":"The label was upgraded, or was already an initiative. When conversionId was sent, it was linked.","content":{"application/json":{"schema":{"properties":{"message":{"description":"\"Folder with id N has been upgraded to an initiative\", or \"Folder with id N is already an initiative\"","type":"string"}},"type":"object"},"example":{"message":"Folder with id 3 has been upgraded to an initiative"}}}},"207":{"description":"Same as 200, but the conversion could not be linked","content":{"application/json":{"schema":{"properties":{"message":{"description":"Same message as for 200","type":"string"},"conversionError":{"description":"Why the link failed: no visible conversion has this ID (\"No Result found for Conversion with id N\"), the conversion is already linked to this initiative, or the link could not be saved.","type":"string"}},"type":"object"},"example":{"message":"Folder with id 3 has been upgraded to an initiative","conversionError":"No Result found for Conversion with id 9"}}}},"404":{"description":"No label has this ID","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the record that was not found","type":"string"}},"type":"object"},"example":{"message":"No Result found for Folder with id 3"}}}},"422":{"description":"On upgrade, label is the name of another label or initiative","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Could not process request\"","type":"string"},"error":{"description":"The database error","type":"string"}},"type":"object"},"example":{"message":"Could not process request","error":"Duplicate entry '1-Spring launch' for key 'em_folder.groupfolder'"}}}}},"x-canonical-resource":"label","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/landingPages/accountinfo":{"get":{"summary":"Retrieve an account's record from the platform accounts table","description":"Internal: account data the landing pages service reads from Hosted, not a customer API. Returns one row of the platform-wide ActiveCampaign accounts table (`_account.accounts`), read from the replica and looked up by the `accountId` given. The lookup is not limited to the account the request is authenticated to. The row is returned as stored, every column included, wrapped under `account`. When no account has this ID the answer is still 200 and the body is the JSON literal `null`.","operationId":"retrieve-landing-pages-account-info","x-canonical-resource":"activecampaign_account","parameters":[{"name":"accountId","in":"query","description":"ID of the ActiveCampaign account. Not enforced: without it the body is `null`.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The account's row, or `null` when no account has this ID","content":{"application/json":{"schema":{"type":["object","null"],"properties":{"account":{"$ref":"#/components/schemas/LandingPagesAccountRecord"}}}}}}},"deprecated":false,"x-internal":true}},"/landingPages/bulkaccountinfo":{"post":{"summary":"Retrieve the status of several ActiveCampaign accounts","description":"Internal: account data the landing pages service reads from Hosted, not a customer API. A read sent as POST so that it can carry a list of IDs; it changes nothing. Looks each ID up in the platform-wide ActiveCampaign accounts table (`_account.accounts`, read replica), not limited to the account the request is authenticated to, and returns the name, expiry date and status of every account it finds, keyed by account ID. IDs with no account are left out. When none is found the body is an empty JSON array `[]`, not an object.","operationId":"list-landing-pages-account-info","x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountIds"],"properties":{"accountIds":{"type":"array","description":"IDs of the ActiveCampaign accounts to look up. Must not be empty.","items":{"type":"integer"},"minItems":1}}},"example":{"accountIds":[2000099,2033669]}}}},"responses":{"200":{"description":"The accounts found, keyed by account ID","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"One entry per account found; the key is the account ID.","additionalProperties":{"$ref":"#/components/schemas/LandingPagesAccountSummary"}},{"type":"array","description":"No account was found for any of the IDs.","maxItems":0}]}}}},"422":{"description":"`accountIds` is missing or empty, or the body is not JSON. The body is empty."}},"deprecated":false,"x-internal":true}},"/landingPages/metadata":{"get":{"summary":"Retrieve landing pages metadata","description":"Internal: what the landing pages service loads from Hosted for its editor, not a customer API. Bundles three things in one call: the user named by `pagesUserId`, the Pendo analytics configuration and the account's admin branding. `pendoConfig` describes the user the request is authenticated as, not `pagesUserId`, and is cached per user for six hours.","operationId":"retrieve-landing-pages-metadata","x-canonical-resource":"account_user","parameters":[{"name":"pagesUserId","in":"query","description":"ID of the user whose record is returned under `user`.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The landing pages metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandingPagesMetadata"}}}},"404":{"description":"No user with this ID, or `pagesUserId` is missing","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Which user was not found."}}}}}}},"deprecated":false,"x-internal":true}},"/legacyEngage/oauth/finish":{"get":{"summary":"Finish connecting a messaging channel","description":"The provider redirects the browser here once the user has authorised, or refused, the connect started by GET /legacyEngage/oauth/start or /reconnect/{connectionId}. Hosted forwards the provider's answer and the confirm cookie to engage-api, which decides whether the connect is accepted, and renders the HTML page engage-api describes with its status, such as 200 when the channel is connected. A missing or mismatched confirm cookie is engage-api's to refuse as a connect not started in this browser. Internal: backs the Engage channel connect flow.","operationId":"finish-legacy-engage-channel-connect","parameters":[{"name":"state","in":"query","description":"The signed state engage-api gave the provider when the connect started.","required":false,"schema":{"type":"string"}},{"name":"code","in":"query","description":"The authorisation code, when the user authorised the connect.","required":false,"schema":{"type":"string"}},{"name":"error","in":"query","description":"The provider's error code, when the user refused or the provider failed.","required":false,"schema":{"type":"string"}},{"name":"error_reason","in":"query","description":"The provider's reason for the error.","required":false,"schema":{"type":"string"}},{"name":"error_description","in":"query","description":"The provider's description of the error.","required":false,"schema":{"type":"string"}},{"name":"legacy_engage_oauth_confirm","in":"cookie","description":"The confirm secret the start or reconnect leg set in this browser.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"engage-api accepted the connect. An HTML page with its heading and message, such as \"Instagram connected\".","content":{"text/html":{"schema":{"description":"An HTML page with engage-api's heading, message and request reference.","type":"string"}}}},"502":{"description":"engage-api could not be reached or gave no outcome. A generic \"We couldn't connect this channel\" HTML page.","content":{"text/html":{"schema":{"description":"An HTML page with a heading and a message.","type":"string"}}}},"default":{"description":"engage-api refused the connect, for example 422 when the user denied access at the provider. An HTML page with its heading, message and reference, sent with the status engage-api answered with.","content":{"text/html":{"schema":{"description":"An HTML page with a heading, a message and, when engage-api gave one, a request reference.","type":"string"}}}}},"x-canonical-resource":"channel_connection","x-internal":true}},"/legacyEngage/oauth/reconnect/{connectionId}":{"get":{"summary":"Start reconnecting a messaging channel","description":"The first browser leg of reconnecting a messaging channel account already connected to Engage. It works as GET /legacyEngage/oauth/start does, naming the connection instead of a channel: when engage-api starts the reconnect, the browser is redirected to the provider with a confirm cookie; otherwise the answer is an HTML page with engage-api's heading, message and status, such as 404 when the connection no longer exists. Internal: backs the Engage channel connect flow.","operationId":"start-legacy-engage-channel-reconnect","parameters":[{"name":"connectionId","in":"path","description":"ID of the channel connection in engage-api, a UUID.","required":true,"schema":{"type":"string"},"example":"0b5e4f1c-8d7a-4a37-9d1e-2f5c7e1a9b01"}],"responses":{"302":{"description":"engage-api started the reconnect. The browser goes to the provider's authorisation page.","headers":{"Location":{"description":"The provider's authorisation URL, as engage-api returned it.","schema":{"type":"string","format":"uri"}},"Set-Cookie":{"description":"The `legacy_engage_oauth_confirm` cookie: the confirm secret engage-api returned, HttpOnly, SameSite=Lax, Secure over HTTPS, path `/api/3/legacyEngage/oauth/finish`, for 10 minutes.","schema":{"type":"string"}}}},"502":{"description":"engage-api could not be reached or gave no outcome. A generic \"We couldn't connect this channel\" HTML page.","content":{"text/html":{"schema":{"description":"An HTML page with a heading and a message.","type":"string"}}}},"default":{"description":"engage-api answered without starting the reconnect, for example 404 when the connection no longer exists. An HTML page with its heading, message and reference, sent with the status engage-api answered with.","content":{"text/html":{"schema":{"description":"An HTML page with a heading, a message and, when engage-api gave one, a request reference.","type":"string"}}}}},"x-canonical-resource":"channel_connection","x-internal":true}},"/legacyEngage/oauth/start":{"get":{"summary":"Start connecting a messaging channel","description":"The first browser leg of connecting a messaging channel account, such as Instagram, to Engage. Hosted serves it because a legacy account's host has no route to engage-api; every account can use it. Hosted asks engage-api to start the connect for the acting user, sending the channel, the host the request arrived on and whether this is a log-in-as-customer session, and makes no connect decision of its own. When engage-api starts it, the browser is redirected to the provider with a confirm cookie scoped to GET /legacyEngage/oauth/finish; otherwise the answer is an HTML page with engage-api's heading, message and status. Open it as a top-level navigation, in the popup the connect runs in. Internal: backs the Engage channel connect flow.","operationId":"start-legacy-engage-channel-connect","parameters":[{"name":"channel","in":"query","description":"The channel to connect, as engage-api names it, for example `instagram`. Passed on unchecked; engage-api refuses one it does not know.","required":false,"schema":{"type":"string"},"example":"instagram"}],"responses":{"302":{"description":"engage-api started the connect. The browser goes to the provider's authorisation page.","headers":{"Location":{"description":"The provider's authorisation URL, as engage-api returned it.","schema":{"type":"string","format":"uri"}},"Set-Cookie":{"description":"The `legacy_engage_oauth_confirm` cookie: the confirm secret engage-api returned, HttpOnly, SameSite=Lax, Secure over HTTPS, path `/api/3/legacyEngage/oauth/finish`, for 10 minutes.","schema":{"type":"string"}}}},"502":{"description":"engage-api could not be reached or gave no outcome. A generic \"We couldn't connect this channel\" HTML page.","content":{"text/html":{"schema":{"description":"An HTML page with a heading and a message.","type":"string"}}}},"default":{"description":"engage-api answered without starting the connect. An HTML page with its heading, message and reference, sent with the status engage-api answered with.","content":{"text/html":{"schema":{"description":"An HTML page with a heading, a message and, when engage-api gave one, a request reference.","type":"string"}}}}},"x-canonical-resource":"channel_connection","x-internal":true}},"/listGroups":{"post":{"summary":"Create a list group permission","description":"","operationId":"create-a-list-group-permission","x-canonical-resource":"listGroups","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"listGroup":{"properties":{"listid":{"type":"integer","description":"ID of the list","format":"int32"},"groupid":{"type":"integer","description":"ID of the group that list should be associated with","format":"int32"},"list":{"type":"integer"},"group":{"type":"integer"}},"required":["listid","groupid"],"type":"object"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"listGroup":{"listid":19,"groupid":1}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"listGroup\": {\n        \"list\": 19,\n        \"group\": 1,\n        \"links\": {\n            \"list\": \"https://account.api-us1.com/api/3/listGroups/55/list\",\n            \"group\": \"https://account.api-us1.com/api/3/listGroups/55/group\"\n        },\n        \"id\": \"55\"\n    }\n}"}},"schema":{"type":"object","properties":{"listGroup":{"type":"object","properties":{"list":{"type":"integer","example":19,"default":0},"group":{"type":"integer","example":1,"default":0},"links":{"type":"object","properties":{"list":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/list"},"group":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/group"}}},"id":{"type":"string","example":"55"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden"}}}}}}},"deprecated":false},"get":{"summary":"List all list group permissions","description":"Each record grants one user group access to one list.","operationId":"list-all-list-group-permissions","x-canonical-resource":"listGroups","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","format":"int32","default":20},"description":"Maximum number of list group permissions to return"},{"name":"offset","in":"query","schema":{"type":"integer","format":"int32","default":0},"description":"Number of list group permissions to skip, for paging"}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"listGroups\": [\n        {\n            \"list\": \"19\",\n            \"group\": \"1\",\n            \"p_list_add\": \"0\",\n            \"p_list_edit\": \"0\",\n            \"p_list_delete\": \"0\",\n            \"p_list_sync\": \"0\",\n            \"p_list_filter\": \"0\",\n            \"p_message_add\": \"0\",\n            \"p_message_edit\": \"0\",\n            \"p_message_delete\": \"0\",\n            \"p_message_send\": \"0\",\n            \"p_subscriber_add\": \"0\",\n            \"p_subscriber_edit\": \"0\",\n            \"p_subscriber_delete\": \"0\",\n            \"p_subscriber_import\": \"0\",\n            \"p_subscriber_approve\": \"0\",\n            \"links\": {\n                \"list\": \"https://account.api-us1.com/api/3/listGroups/55/list\",\n                \"group\": \"https://account.api-us1.com/api/3/listGroups/55/group\"\n            },\n            \"id\": \"55\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 1\n    }\n}"}},"schema":{"type":"object","properties":{"listGroups":{"type":"array","items":{"type":"object","properties":{"list":{"type":"string","example":"19","description":"ID of the list the user group is granted access to"},"group":{"type":"string","example":"1","description":"ID of the user group that has access to the list"},"p_list_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add lists, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_sync":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may sync the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_list_filter":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may manage the list's segments, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may create campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_send":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may send campaigns to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add contacts to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete contacts from the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_import":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may import contacts into the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_approve":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may approve contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"links":{"type":"object","properties":{"list":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/list","description":"URL of the related list"},"group":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/group","description":"URL of the related user group"}},"description":"URLs of the related list and user group"},"id":{"type":"string","example":"55","description":"ID of the list group permission"}}},"description":"List group permissions, one per list and user group pair"},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"description":"Total number of list group permissions, ignoring limit and offset"}},"description":"Paging metadata"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden","description":"The API user does not have access to this list group permission"}}}}}}},"deprecated":false}},"/listGroups/bulkUpdate":{"post":{"summary":"Change which lists a user group can access","description":"Internal. Adds and removes the list group records of one user group in one request. Each record gives the group access to one list.\n\nFor each id in `listIdsToAdd`, a record is created unless the group already has one for that list. A new record has every permission flag \"0\". For each id in `listIdsToDelete`, the group's record for that list is deleted, if there is one. Adds run first, then deletes, in one transaction: if a list id cannot be saved, nothing is changed. The group and the lists are not checked to exist.\n\nAfter the change, the list permissions of every user are rebuilt from the list group records of their groups. This rebuild also deletes every list group record whose list does not exist, so an id of a missing list leaves no record. The rebuild also replaces the account's user permission table, and removes user group and deal group total records of deleted users or deal groups.\n\nThe fields are top-level keys of the JSON body, not wrapped in `listGroup`. Only POST is accepted. Other methods also reach this script, but get 405.","operationId":"bulk-update-list-group-permissions","x-canonical-resource":"listGroups","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["group"],"properties":{"group":{"type":["string","integer"],"description":"ID of the user group. Must not be empty or 0."},"listIdsToAdd":{"type":"array","items":{"type":["string","integer"]},"description":"IDs of the lists the group gets access to. Send both keys; use an empty array for the one you do not need."},"listIdsToDelete":{"type":"array","items":{"type":["string","integer"]},"description":"IDs of the lists the group loses access to. Send both keys; use an empty array for the one you do not need."}},"description":"At least one of `listIdsToAdd` and `listIdsToDelete` must be a non-empty array."},"example":{"group":"4","listIdsToAdd":[1],"listIdsToDelete":[3]}}}},"responses":{"202":{"description":"The change was saved. The body holds every list group record of the group after the change, not paged, and their number in `meta.total`.","content":{"application/json":{"schema":{"type":"object","properties":{"listGroups":{"type":"array","items":{"$ref":"#/components/schemas/ListGroupBulkUpdateRecord"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Number of records in `listGroups`"}}}}},"example":{"listGroups":[{"list":"1","group":"4","p_list_add":"0","p_list_edit":"0","p_list_delete":"0","p_list_sync":"0","p_list_filter":"0","p_message_add":"0","p_message_edit":"0","p_message_delete":"0","p_message_send":"0","p_subscriber_add":"0","p_subscriber_edit":"0","p_subscriber_delete":"0","p_subscriber_import":"0","p_subscriber_approve":"0","links":{"list":"https://account.api-us1.com/api/3/listGroups/55/list","group":"https://account.api-us1.com/api/3/listGroups/55/group"},"id":"55"}],"meta":{"total":1}}}}},"403":{"description":"The request is not authenticated or not allowed. The body is empty."},"405":{"description":"A method other than POST. The Allow header says POST.","headers":{"Allow":{"description":"The accepted method","schema":{"type":"string","example":"POST"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListGroupBulkUpdateErrors"},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}},"422":{"description":"Nothing was changed. Either `group` is missing, empty or 0, or both `listIdsToAdd` and `listIdsToDelete` are missing or empty: one error with `status`, `title` and `detail`, both translated texts. Or an id in `listIdsToAdd` is null, empty or only spaces: the ids are saved one at a time, so the first such id stops the request and the whole change is rolled back. The body then holds one error, for that first id, with `title`, `detail`, `code`, `error` and `source`, and no `status`. Its `source.pointer` is `/data/attributes/list` and does not say which id failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListGroupBulkUpdateErrors"},"example":{"errors":[{"title":"The listGroup list was not provided.","detail":"","code":"field_missing","error":"listGroup_list_was_not_provided","source":{"pointer":"/data/attributes/list"}}]}}}}},"deprecated":false,"x-internal":true}},"/listGroups/{id}":{"get":{"summary":"Retrieve a list group permission","description":"","operationId":"retrieve-a-list-group-permission","x-canonical-resource":"listGroups","parameters":[{"name":"id","in":"path","description":"ID of the list group permission","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"listGroup\": {\n        \"list\": \"19\",\n        \"group\": \"1\",\n        \"p_list_add\": \"0\",\n        \"p_list_edit\": \"0\",\n        \"p_list_delete\": \"0\",\n        \"p_list_sync\": \"0\",\n        \"p_list_filter\": \"0\",\n        \"p_message_add\": \"0\",\n        \"p_message_edit\": \"0\",\n        \"p_message_delete\": \"0\",\n        \"p_message_send\": \"0\",\n        \"p_subscriber_add\": \"0\",\n        \"p_subscriber_edit\": \"0\",\n        \"p_subscriber_delete\": \"0\",\n        \"p_subscriber_import\": \"0\",\n        \"p_subscriber_approve\": \"0\",\n        \"links\": {\n            \"list\": \"https://account.api-us1.com/api/3/listGroups/55/list\",\n            \"group\": \"https://account.api-us1.com/api/3/listGroups/55/group\"\n        },\n        \"id\": \"55\"\n    }\n}"}},"schema":{"type":"object","properties":{"listGroup":{"type":"object","properties":{"list":{"type":"string","example":"19","description":"ID of the list the user group is granted access to"},"group":{"type":"string","example":"1","description":"ID of the user group that has access to the list"},"p_list_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add lists, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_sync":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may sync the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_list_filter":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may manage the list's segments, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may create campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_send":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may send campaigns to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add contacts to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete contacts from the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_import":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may import contacts into the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_approve":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may approve contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"links":{"type":"object","properties":{"list":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/list","description":"URL of the related list"},"group":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/group","description":"URL of the related user group"}},"description":"URLs of the related list and user group"},"id":{"type":"string","example":"55","description":"ID of the list group permission"}},"description":"The list group permission"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden","description":"The API user does not have access to this list group permission"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for ListGroup with id 55\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for ListGroup with id 55","description":"No list group permission has this ID"}}}}}}},"deprecated":false},"put":{"summary":"Update a list group permission","description":"Points an existing permission at another list or user group. Unlike create and delete, this does not rebuild the users' list permissions.","operationId":"update-a-list-group-permission","x-canonical-resource":"listGroups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the list group permission","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"listGroup":{"type":"object","properties":{"list":{"type":"integer","description":"ID of the list","format":"int32"},"group":{"type":"integer","description":"ID of the user group","format":"int32"}},"description":"Fields to change on the list group permission"}},"additionalProperties":false},"examples":{"Request Example":{"value":{"listGroup":{"list":19,"group":2}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"listGroup\": {\n        \"list\": 19,\n        \"group\": 1,\n        \"p_list_add\": \"0\",\n        \"p_list_edit\": \"0\",\n        \"p_list_delete\": \"0\",\n        \"p_list_sync\": \"0\",\n        \"p_list_filter\": \"0\",\n        \"p_message_add\": \"0\",\n        \"p_message_edit\": \"0\",\n        \"p_message_delete\": \"0\",\n        \"p_message_send\": \"0\",\n        \"p_subscriber_add\": \"0\",\n        \"p_subscriber_edit\": \"0\",\n        \"p_subscriber_delete\": \"0\",\n        \"p_subscriber_import\": \"0\",\n        \"p_subscriber_approve\": \"0\",\n        \"links\": {\n            \"list\": \"https://account.api-us1.com/api/3/listGroups/55/list\",\n            \"group\": \"https://account.api-us1.com/api/3/listGroups/55/group\"\n        },\n        \"id\": \"55\"\n    }\n}"}},"schema":{"type":"object","properties":{"listGroup":{"type":"object","properties":{"list":{"type":"integer","example":19,"default":0,"description":"ID of the list the user group is granted access to. Returned in the type the request sent it, so a JSON number when sent as one; later reads return a numeric string"},"group":{"type":"integer","example":1,"default":0,"description":"ID of the user group that has access to the list. Returned in the type the request sent it, so a JSON number when sent as one; later reads return a numeric string"},"p_list_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add lists, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete the list, otherwise \"0\". Legacy: Hosted no longer sets this flag when it creates list group records, so it is \"0\" unless older code set it. Read-only through this endpoint."},"p_list_sync":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may sync the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_list_filter":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may manage the list's segments, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may create campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete campaigns for the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_message_send":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may send campaigns to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_add":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may add contacts to the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_edit":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may edit contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_delete":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may delete contacts from the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_import":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may import contacts into the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"p_subscriber_approve":{"type":"string","example":"0","enum":["0","1"],"description":"\"1\" if users in the user group may approve contacts on the list, otherwise \"0\". Copied into each group member's list permissions when they are rebuilt. Read-only through this endpoint."},"links":{"type":"object","properties":{"list":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/list","description":"URL of the related list"},"group":{"type":"string","example":"https://account.api-us1.com/api/3/listGroups/55/group","description":"URL of the related user group"}},"description":"URLs of the related list and user group"},"id":{"type":"string","example":"55","description":"ID of the list group permission"}},"description":"The list group permission"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden","description":"The API user does not have access to this list group permission"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for ListGroup with id 55\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for ListGroup with id 55","description":"No list group permission has this ID"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a list group permission","description":"Removes the user group's access to the list, then rebuilds the list permissions of every user in the account.","operationId":"delete-a-list-group-permission","x-canonical-resource":"listGroups","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the list group permission","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Forbidden","description":"The API user does not have access to this list group permission"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for ListGroup with id 55\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for ListGroup with id 55","description":"No list group permission has this ID"}}}}}}},"deprecated":false}},"/lists":{"get":{"summary":"Retrieve all lists","description":"Retrieve the account's contact lists, 20 per request by default and at most 100; page with offset. Each list in this collection carries two counters: active_subscribers, the contacts with an active subscription to the list, and non_deleted_subscribers, every contact still on the list in any status. The difference between them is the contacts on the list who are unconfirmed, unsubscribed or bounced; the list object does not break that remainder down by status. To count the contacts on one list in one status, use GET /contacts with listid, status and meta=only. Filter by name with filters[name]. Only email lists are returned unless filters[channel] is sms or all. The exclusion list is not a contact list; see GET /lists/exclusions.","operationId":"retrieve-all-lists","x-canonical-resource":"lists","parameters":[{"name":"filters[name]","in":"query","description":"Filter by the name of the list","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of lists to return per request. Defaults to 20; the maximum is 100, and asking for more is capped at 100.","schema":{"type":"integer","default":20,"maximum":100}},{"name":"filters[name][<operator>]","in":"query","description":"Filters lists by list name according to the operator specified. (See supported operators below)","schema":{"type":"string"}},{"name":"orders[name]","in":"query","description":"Orders filtered results by weight, ascending order, or descending order. If weight is used, exact matches are returned first, followed by matches starting with what was filtered by, followed by the rest of the results.","schema":{"type":"string"}},{"name":"offset","in":"query","description":"Number of lists to skip before returning results. Use with limit to page through the lists.","schema":{"type":"integer","default":0}},{"name":"filters[channel]","in":"query","description":"Which channel's lists to return: email (the default), sms, or all. SMS lists are left out unless this is sms or all.","schema":{"type":"string","enum":["email","sms","all"],"default":"email"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"lists\": [\n        {\n            \"stringid\": \"email-subscription\",\n            \"userid\": \"1\",\n            \"name\": \"Email Subscription\",\n            \"cdate\": \"2018-08-06T16:30:41-05:00\",\n            \"p_use_tracking\": \"1\",\n            \"p_use_analytics_read\": \"0\",\n            \"p_use_analytics_link\": \"0\",\n            \"p_use_twitter\": \"0\",\n            \"p_use_facebook\": \"0\",\n            \"p_embed_image\": \"1\",\n            \"p_use_captcha\": \"1\",\n            \"send_last_broadcast\": \"0\",\n            \"private\": \"0\",\n            \"analytics_domains\": null,\n            \"analytics_source\": \"\",\n            \"analytics_ua\": \"\",\n            \"twitter_token\": \"\",\n            \"twitter_token_secret\": \"\",\n            \"facebook_session\": null,\n            \"carboncopy\": null,\n            \"subscription_notify\": null,\n            \"unsubscription_notify\": null,\n            \"require_name\": \"0\",\n            \"get_unsubscribe_reason\": \"0\",\n            \"to_name\": \"Subscriber\",\n            \"optinoptout\": \"1\",\n            \"sender_name\": \"\",\n            \"sender_addr1\": \"\",\n            \"sender_addr2\": \"\",\n            \"sender_city\": \"\",\n            \"sender_state\": \"\",\n            \"sender_zip\": \"\",\n            \"sender_country\": \"\",\n            \"sender_phone\": \"\",\n            \"sender_url\": \"https://www.example.com\",\n            \"sender_reminder\": \"You signed up for my mailing list.\",\n            \"fulladdress\": \"\",\n            \"optinmessageid\": \"0\",\n            \"optoutconf\": \"0\",\n            \"deletestamp\": null,\n            \"udate\": null,\n            \"links\": {\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/1/contactGoalLists\",\n                \"user\": \"https://:account.api-us1.com/api/3/lists/1/user\",\n                \"addressLists\": \"https://:account.api-us1.com/api/3/lists/1/addressLists\"\n            },\n            \"id\": \"1\",\n            \"user\": \"1\"\n        },\n        {\n            \"stringid\": \"robert-list\",\n            \"userid\": \"1\",\n            \"name\": \"Robert List\",\n            \"cdate\": \"2018-09-07T08:56:49-05:00\",\n            \"p_use_tracking\": \"1\",\n            \"p_use_analytics_read\": \"0\",\n            \"p_use_analytics_link\": \"0\",\n            \"p_use_twitter\": \"0\",\n            \"p_use_facebook\": \"0\",\n            \"p_embed_image\": \"1\",\n            \"p_use_captcha\": \"1\",\n            \"send_last_broadcast\": \"0\",\n            \"private\": \"0\",\n            \"analytics_domains\": null,\n            \"analytics_source\": \"\",\n            \"analytics_ua\": \"\",\n            \"twitter_token\": \"\",\n            \"twitter_token_secret\": \"\",\n            \"facebook_session\": null,\n            \"carboncopy\": null,\n            \"subscription_notify\": null,\n            \"unsubscription_notify\": null,\n            \"require_name\": \"0\",\n            \"get_unsubscribe_reason\": \"0\",\n            \"to_name\": \"Subscriber\",\n            \"optinoptout\": \"1\",\n            \"sender_name\": \"\",\n            \"sender_addr1\": \"\",\n            \"sender_addr2\": \"\",\n            \"sender_city\": \"\",\n            \"sender_state\": \"\",\n            \"sender_zip\": \"\",\n            \"sender_country\": \"\",\n            \"sender_phone\": \"\",\n            \"sender_url\": \"http://www.activecampaign.com\",\n            \"sender_reminder\": \"Test\",\n            \"fulladdress\": \"\",\n            \"optinmessageid\": \"0\",\n            \"optoutconf\": \"0\",\n            \"deletestamp\": null,\n            \"udate\": null,\n            \"links\": {\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/2/contactGoalLists\",\n                \"user\": \"https://:account.api-us1.com/api/3/lists/2/user\",\n                \"addressLists\": \"https://:account.api-us1.com/api/3/lists/2/addressLists\"\n            },\n            \"id\": \"2\",\n            \"user\": \"1\"\n        },\n        {\n            \"stringid\": \"mark-list\",\n            \"userid\": \"1\",\n            \"name\": \"Mark List\",\n            \"cdate\": \"2018-09-14T08:53:28-05:00\",\n            \"p_use_tracking\": \"1\",\n            \"p_use_analytics_read\": \"0\",\n            \"p_use_analytics_link\": \"0\",\n            \"p_use_twitter\": \"0\",\n            \"p_use_facebook\": \"0\",\n            \"p_embed_image\": \"1\",\n            \"p_use_captcha\": \"1\",\n            \"send_last_broadcast\": \"0\",\n            \"private\": \"0\",\n            \"analytics_domains\": null,\n            \"analytics_source\": \"\",\n            \"analytics_ua\": \"\",\n            \"twitter_token\": \"\",\n            \"twitter_token_secret\": \"\",\n            \"facebook_session\": null,\n            \"carboncopy\": null,\n            \"subscription_notify\": null,\n            \"unsubscription_notify\": null,\n            \"require_name\": \"0\",\n            \"get_unsubscribe_reason\": \"0\",\n            \"to_name\": \"Subscriber\",\n            \"optinoptout\": \"1\",\n            \"sender_name\": \"\",\n            \"sender_addr1\": \"\",\n            \"sender_addr2\": \"\",\n            \"sender_city\": \"\",\n            \"sender_state\": \"\",\n            \"sender_zip\": \"\",\n            \"sender_country\": \"\",\n            \"sender_phone\": \"\",\n            \"sender_url\": \"http://www.activecampaign.com\",\n            \"sender_reminder\": \"testing.\",\n            \"fulladdress\": \"\",\n            \"optinmessageid\": \"0\",\n            \"optoutconf\": \"0\",\n            \"deletestamp\": null,\n            \"udate\": null,\n            \"links\": {\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/3/contactGoalLists\",\n                \"user\": \"https://:account.api-us1.com/api/3/lists/3/user\",\n                \"addressLists\": \"https://:account.api-us1.com/api/3/lists/3/addressLists\"\n            },\n            \"id\": \"3\",\n            \"user\": \"1\"\n        },\n        {\n            \"stringid\": \"\",\n            \"userid\": \"0\",\n            \"name\": \"\",\n            \"cdate\": \"2018-09-25T15:24:37-05:00\",\n            \"p_use_tracking\": \"1\",\n            \"p_use_analytics_read\": \"0\",\n            \"p_use_analytics_link\": \"0\",\n            \"p_use_twitter\": \"0\",\n            \"p_use_facebook\": \"0\",\n            \"p_embed_image\": \"1\",\n            \"p_use_captcha\": \"1\",\n            \"send_last_broadcast\": \"0\",\n            \"private\": \"0\",\n            \"analytics_domains\": null,\n            \"analytics_source\": \"\",\n            \"analytics_ua\": \"\",\n            \"twitter_token\": \"\",\n            \"twitter_token_secret\": \"\",\n            \"facebook_session\": null,\n            \"carboncopy\": null,\n            \"subscription_notify\": null,\n            \"unsubscription_notify\": null,\n            \"require_name\": \"0\",\n            \"get_unsubscribe_reason\": \"0\",\n            \"to_name\": \"Subscriber\",\n            \"optinoptout\": \"1\",\n            \"sender_name\": \"\",\n            \"sender_addr1\": \"\",\n            \"sender_addr2\": \"\",\n            \"sender_city\": \"\",\n            \"sender_state\": \"\",\n            \"sender_zip\": \"\",\n            \"sender_country\": \"\",\n            \"sender_phone\": \"\",\n            \"sender_url\": null,\n            \"sender_reminder\": null,\n            \"fulladdress\": null,\n            \"optinmessageid\": \"0\",\n            \"optoutconf\": \"0\",\n            \"deletestamp\": null,\n            \"udate\": \"2018-09-25T15:24:37-05:00\",\n            \"links\": {\n                \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/4/contactGoalLists\",\n                \"user\": \"https://:account.api-us1.com/api/3/lists/4/user\",\n                \"addressLists\": \"https://:account.api-us1.com/api/3/lists/4/addressLists\"\n            },\n            \"id\": \"4\",\n            \"user\": null\n        }\n    ],\n    \"meta\": {\n        \"total\": \"4\"\n    }\n}"}},"schema":{"type":"object","properties":{"lists":{"type":"array","items":{"type":"object","properties":{"stringid":{"type":"string","example":"email-subscription"},"userid":{"type":"string","example":"1"},"name":{"type":"string","example":"Email Subscription"},"cdate":{"type":"string","example":"2018-08-06T16:30:41-05:00"},"p_use_tracking":{"type":"string","example":"1"},"p_use_analytics_read":{"type":"string","example":"0"},"p_use_analytics_link":{"type":"string","example":"0"},"p_use_twitter":{"type":"string","example":"0"},"p_use_facebook":{"type":"string","example":"0"},"p_embed_image":{"type":"string","example":"1"},"p_use_captcha":{"type":"string","example":"1"},"send_last_broadcast":{"type":"string","example":"0"},"private":{"type":"string","example":"0"},"analytics_domains":{},"analytics_source":{"type":"string","example":""},"analytics_ua":{"type":"string","example":""},"twitter_token":{"type":"string","example":""},"twitter_token_secret":{"type":"string","example":""},"facebook_session":{},"carboncopy":{},"subscription_notify":{},"unsubscription_notify":{},"require_name":{"type":"string","example":"0"},"get_unsubscribe_reason":{"type":"string","example":"0"},"to_name":{"type":"string","example":"Subscriber"},"optinoptout":{"type":"string","example":"1"},"sender_name":{"type":"string","example":""},"sender_addr1":{"type":"string","example":""},"sender_addr2":{"type":"string","example":""},"sender_city":{"type":"string","example":""},"sender_state":{"type":"string","example":""},"sender_zip":{"type":"string","example":""},"sender_country":{"type":"string","example":""},"sender_phone":{"type":"string","example":""},"sender_url":{"type":"string","example":"https://www.example.com"},"sender_reminder":{"type":"string","example":"You signed up for my mailing list."},"fulladdress":{"type":"string","example":""},"optinmessageid":{"type":"string","example":"0"},"optoutconf":{"type":"string","example":"0"},"deletestamp":{},"udate":{},"channel":{"type":"string","example":"email","description":"The channel the list is for: email or sms."},"description":{"type":["string","null"],"example":null,"description":"The list's description, or null when none was set."},"created_timestamp":{"type":"string","example":"2019-11-13 13:45:15"},"updated_timestamp":{"type":"string","example":"2021-02-11 12:40:12"},"created_by":{"type":["string","null"],"example":null},"updated_by":{"type":["string","null"],"example":null},"non_deleted_subscribers":{"type":"string","example":"17210","description":"Every contact still on this list in any status (active, unconfirmed, unsubscribed or bounced), as a string. Subtract active_subscribers to get the contacts on the list who are not active."},"active_subscribers":{"type":"string","example":"5147","description":"Contacts with an active subscription to this list, as a string."},"links":{"type":"object","properties":{"contactGoalLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/contactGoalLists"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/user"},"addressLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/addressLists"}}},"id":{"type":"string","example":"1"},"user":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"170","description":"Number of lists that match, as a string."}}}}}}}},"403":{"description":"403","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to view lists.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"default":0},"title":{"type":"string","example":"Forbidden"},"detail":{"type":"string","example":"You do not have permission to view lists."}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete lists in bulk","description":"Deletes several lists in one request, either the lists named in ids or, with all, every list the user can see. Each list is deleted during the request, one after another. A deleted list loses its contacts: by default a contact that is on no other list is deleted, and a contact that is also on another list is kept on that list. With keepContacts every contact is kept and only taken off the list. Custom fields used by no other list are deleted with the list. A list that does not exist is skipped. Other failures on a single list are skipped too, except the permission and limit checks described under 403. A list that fails partway may already have lost some of its contacts, because they are removed before the list itself. Skipped lists do not change the response. Needs the admin permission. The delete-list permission (pg_list_delete) is also checked for each list it deletes.","operationId":"bulk-delete-lists","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ids"],"properties":{"ids":{"description":"IDs of the lists to delete. Must be present even when all is true, and may then be empty. When all is true, the lists to delete come from all and filter instead.","type":"array","items":{"type":"integer"}},"filter":{"description":"ID of one of the caller's saved list filters. Used only when all is true: then only the lists that match it are deleted. If it does not match one of the caller's saved list filters, the request fails and nothing is deleted. Defaults to 0, no filter.","type":"integer"},"all":{"description":"When true, deletes every list the user can see, or every list that matches filter, instead of the lists in ids. Defaults to false.","type":"boolean"},"keepContacts":{"description":"When true, every contact is kept and only taken off the deleted lists. When false, the default, contacts that are on no other list are deleted.","type":"boolean"}},"type":"object"},"example":{"ids":[12,13],"keepContacts":true}}}},"responses":{"200":{"description":"The lists were processed.","content":{"application/json":{"schema":{"required":["success"],"properties":{"success":{"description":"Always true here.","type":"boolean","example":true}},"type":"object"},"example":{"success":true}}}},"400":{"description":"ids is missing, or the body is empty or not JSON. Nothing is deleted. Body: success false and message \"Invalid request\".","content":{"application/json":{"schema":{"required":["success","message"],"properties":{"success":{"type":"boolean","example":false},"message":{"type":"string","example":"Invalid request"}},"type":"object"}}}},"403":{"description":"Refused, in one of two ways. When the user does not have the admin permission, nothing is deleted and the body is JSON: success false and message \"Action not allowed\". When the user lacks the delete-list permission (pg_list_delete), or the account has reached its contact-delete limit, the request stops at the list being deleted. The body is then a plain-text sentence, not JSON, though the Content-Type header still says application/json. A missing permission stops the request at the first list that exists, before anything is deleted. When the limit is reached, lists already deleted in the same request stay deleted.","content":{"application/json":{"schema":{"required":["success","message"],"properties":{"success":{"type":"boolean","example":false},"message":{"type":"string","example":"Action not allowed"}},"type":"object"}}}}},"x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":true},"post":{"summary":"Create a list","description":"Creates a list. Only name is validated: stringid is generated from the name when left out, and the sender fields are not checked. Sending the private key makes the list private whatever its value.","operationId":"create-new-list","requestBody":{"content":{"application/json":{"schema":{"properties":{"list":{"description":"The list to create.","required":["name"],"properties":{"name":{"description":"Name of the list to create","type":"string"},"stringid":{"description":"URL-safe list name. Example: 'list-name-sample'","type":"string"},"sender_url":{"description":"The website URL this list is for.","type":"string"},"sender_reminder":{"description":"A reminder for your contacts as to why they are on this list and you are messaging them.","type":"string"},"send_last_broadcast":{"description":"Boolean value indicating whether or not to send the last sent campaign to this list to a new subscriber upon subscribing. 1 = yes, 0 = no","type":"boolean","default":false},"carboncopy":{"description":"Comma-separated list of email addresses to send a copy of all mailings to upon send","type":"string"},"subscription_notify":{"description":"Comma-separated list of email addresses to notify when a new subscriber joins this list.","type":"string"},"unsubscription_notify":{"description":"Comma-separated list of email addresses to notify when a subscriber unsubscribes from this list.","type":"string"},"channel":{"description":"Type of channel for the list. Possible values are `email` or `sms`.","type":"string","default":"email"},"userid":{"description":"User id of the list owner. Applied only for main-group admins.","type":"integer"},"private":{"description":"Whether the list is private. Only the presence of this key is read: any value, including false, makes the list private. Leave the key out for a list that is not private.","type":"boolean"},"sender_name":{"description":"Name of the sender, printed in the footer of mailings sent to this list.","type":"string"},"sender_addr1":{"description":"First line of the sender's postal address.","type":"string"},"sender_addr2":{"description":"Second line of the sender's postal address.","type":"string"},"sender_city":{"description":"City of the sender's postal address.","type":"string"},"sender_zip":{"description":"Postal code of the sender's address.","type":"string"},"sender_state":{"description":"State or region of the sender's address.","type":"string"},"sender_country":{"description":"Country of the sender's address.","type":"string"},"sender_phone":{"description":"Phone number of the sender.","type":"string"},"description":{"description":"Description of the list.","type":"string"}},"type":"object","additionalProperties":false}},"type":"object"},"example":{"list":{"name":"Name of List","stringid":"Name-of-list","sender_url":"http://activecampaign.com","sender_reminder":"You are receiving this email as you subscribed to a newsletter when making an order on our site.","send_last_broadcast":0,"carboncopy":"","subscription_notify":"","unsubscription_notify":"","userid":1}}}}},"responses":{"201":{"description":"The list was created.","content":{"application/json":{"schema":{"properties":{"list":{"description":"The list as saved.","properties":{"id":{"description":"ID of the list.","type":"string"},"name":{"description":"Name of the list.","type":"string"},"channel":{"description":"Channel of the list: email or sms.","type":"string"},"stringid":{"description":"URL-safe list name.","type":"string"},"sender_url":{"description":"The website URL this list is for.","type":"string"},"sender_reminder":{"description":"The reminder shown to contacts about why they are on this list.","type":"string"},"description":{"description":"Description of the list.","type":"string"},"send_last_broadcast":{"description":"1 when the last sent campaign is sent to a new subscriber upon subscribing, 0 when not.","type":"integer"},"carboncopy":{"description":"Comma-separated email addresses that receive a copy of every mailing.","type":"string"},"subscription_notify":{"description":"Comma-separated email addresses notified when a subscriber joins the list.","type":"string"},"unsubscription_notify":{"description":"Comma-separated email addresses notified when a subscriber unsubscribes.","type":"string"},"userid":{"description":"ID of the user who owns the list.","type":"integer"},"user":{"description":"ID of the user who owns the list, repeated from userid as the list's user relationship.","type":"string"},"cdate":{"description":"Date and time the list was created.","type":"string"},"udate":{"description":"Date and time the list was last updated.","type":"string"},"links":{"description":"URLs of the list's related resources.","properties":{"contactGoalLists":{"description":"URL of the list's contactGoalLists.","type":"string"},"user":{"description":"URL of the list's owner.","type":"string"},"addressLists":{"description":"URL of the list's addressLists.","type":"string"}},"type":"object"}},"type":"object"}},"type":"object"},"example":{"list":{"id":"6","name":"Name of List","channel":"email","stringid":"Name-of-list","sender_url":"http://activecampaign.com","sender_reminder":"You are receiving this email as you subscribed to a newsletter when making an order on our site.","description":"","send_last_broadcast":0,"carboncopy":"","subscription_notify":"","unsubscription_notify":"","userid":1,"user":"1","cdate":"2019-02-27T19:06:23-05:00","udate":"2019-02-27T19:06:23-05:00","links":{"contactGoalLists":"https://:account.api-us1.com/api/:version/lists/6/contactGoalLists","user":"https://:account.api-us1.com/api/:version/lists/6/user","addressLists":"https://:account.api-us1.com/api/:version/lists/6/addressLists"}}}}}},"403":{"description":"The user may not create lists, or the account has reached its list limit.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"integer"},"title":{"description":"Short name of the error.","type":"string"},"detail":{"description":"What went wrong.","type":"string"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create lists."}]}}}},"422":{"description":"The list was not created: name is empty or contains HTML, or channel is not email or sms."}},"x-canonical-resource":"lists","x-destructive":false,"x-bulk-operation":false}},"/lists/cleanup":{"post":{"summary":"Clean up contacts on lists","description":"Internal. Used by the list cleanup wizard. Removes contacts from lists in a background job, or, with `preview`, only counts them. A contact that would be left on no list is deleted, not just removed.\n\nSend `listIds`, or `allLists` to use every list the user can see. Pick the contacts with exactly one of `status` and `emails`. `status` picks contacts by their status on the list, and `date` limits them by date. `emails` picks the contacts with those email addresses; addresses that match no contact are skipped.\n\nWith `preview`, nothing changes. Without it, a background job is queued and its ID comes back in `process`. Each call without `preview` queues a new job. The account's count of deleted contacts goes up by `totalDeleting`, except when support staff act in the account. It goes up before the job is saved, so also when saving the job fails.\n\nAn account without the Campaigns feature gets 403 for every method. The fields are top-level keys of a JSON or form body. In a form body, send the arrays as repeated `listIds[]` and `emails[]` keys; repeated bare `listIds` or `emails` keys keep only the last value. The query string is not read. Only POST is accepted.","operationId":"clean-up-list-contacts","x-canonical-resource":"lists","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsCleanupRequest"},"example":{"listIds":[5],"status":2,"date":"2026-10-01T00:00:00+00:00","preview":true,"limit":100}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ListsCleanupRequest"}}}},"responses":{"202":{"description":"The counts, and either the queued job or, with `preview`, the emails of the contacts that would be deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsCleanupResult"},"example":{"totalRemoving":3,"totalDeleting":1,"contactEmails":["sam@example.com"],"success":1}}}},"403":{"description":"Either the request is not authenticated or not allowed, and the body is empty. Or the account does not have the Campaigns feature: the body includes `success` 0 and `message` `Please upgrade your account to enable the Campaign module and access campaigns.`; some callers also get `result_code`, `result_message` and `result_output`. Or a user outside the admin group sent a list ID that is not one of their lists: the body is one error with `detail` `You do not have permissions to edit this list`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ListsHttpErrors"},{"$ref":"#/components/schemas/ListsCleanupUpgrade"}]},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permissions to edit this list"}]}}}},"404":{"description":"A list in `listIds` does not exist. Users outside the admin group get 403 for such a list instead.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"List with id 9 not found."}}}},"405":{"$ref":"#/components/responses/ListsMethodNotAllowed"},"422":{"description":"The body is not valid. The body is usually one error with `title` `Invalid Input Parameter` and a `detail` such as: `listIds` is not an array; a list ID is not a whole number; both or neither of `status` and `emails` were sent; `status` is not one of the values; an email is not valid; `date` is missing or not in the format, for a status other than 0 (with status 0 the date is not checked at all); in a preview, `limit` is not a whole number from 1 to 20000 or `offset` is not a whole number of 0 or more. In some cases the body is plain text instead: `Must filter by either email or list status.` when `emails` or `status` is sent as null and the other is missing, and `Could not process list cleanup request.` when the job cannot be saved.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ListsHttpErrors"},{"type":"string"}]},"example":{"errors":[{"status":422,"title":"Invalid Input Parameter","detail":"The 'listIds' parameter is not a valid array"}]}}}}},"deprecated":false,"x-internal":true}},"/lists/clear_cache":{"post":{"summary":"Clear the cached lists of the user","description":"Internal. Used by the app UI. Clears the cached list IDs of the user's first user group, so they are read again on the next request. For a user outside the admin group, the admin group's cache is cleared too. The cached lists used by automations are also cleared. No lists change. The request body is not read. Only POST is accepted.","operationId":"clear-lists-cache","x-canonical-resource":"lists","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"The cache was cleared. The body is empty."},"403":{"description":"The request is not authenticated or not allowed. The body is empty."},"405":{"$ref":"#/components/responses/ListsMethodNotAllowed"}},"deprecated":false,"x-internal":true}},"/lists/exclusions":{"get":{"summary":"Retrieve exclusions list","description":"The account's exclusion list: suppression rules that stop sends to matching addresses or numbers even when a contact is active on a list. Each rule has a matchPhrase, a matchType that says how the phrase is matched (exact, begin or end), and a channel: all when the rule applies to every list on both channels, allEmail or allSms when it applies to every list on that one channel, or several when it is limited to the lists named in lists. This is not the set of unsubscribed or bounced contacts, and meta.total counts rules, not contacts. To count unsubscribed or bounced contacts, use GET /contacts with status and meta=only.","operationId":"exclusions-retrieve-a-list","x-canonical-resource":"lists","parameters":[{"name":"filters[matchPhrase]","in":"query","description":"Filters by the match phrase, for example `filters[matchPhrase]=.com`","schema":{"type":"string"}},{"name":"filters[lists]","in":"query","description":"Filters by the list ID, for example `filters[lists][]=1`. You can filter by many list IDs","schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"orders[matchPhrase]","in":"query","description":"Sort by the matchPhrase","schema":{"type":"string","enum":["'DESC'","'ASC'"]}},{"name":"orders[lists]","in":"query","description":"Sort by lists IDs","schema":{"type":"string","enum":["'DESC'","'ASC'"]}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"exclusions\": [\n        {\n            \"id\": \"1\",\n            \"matchPhrase\": \"jdoe@example.org\",\n            \"matchType\": \"end\",\n            \"channel\": \"allSms\",\n            \"hidden\": false,\n            \"lists\": []\n        },\n        {\n            \"id\": \"2\",\n            \"matchPhrase\": \"jdoe@example.com\",\n            \"matchType\": \"exact\",\n            \"channel\": \"several\",\n            \"hidden\": false,\n            \"lists\": [\n                \"2\",\n                \"1\"\n            ]\n        }\n    ],\n    \"meta\": {\n        \"total\": 5\n    }\n}"}},"schema":{"type":"object","properties":{"exclusions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"1"},"matchPhrase":{"type":"string","example":"jdoe@example.org"},"matchType":{"type":"string","example":"end"},"channel":{"type":"string","example":"allSms"},"hidden":{"type":"boolean","example":false,"default":true},"lists":{"type":"array"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":5,"default":0}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Validation errors":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"Invalid order direction: \\\"DASC\\\". Allowed values are: \\\"ASC\\\", \\\"DESC\\\"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/orders[matchPhrase]\"\n            }\n        },\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"Invalid filter field: \\\"nonExisting\\\". Allowed fields are: matchPhrase, lists\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/filters[nonExisting]\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid attribute"},"detail":{"type":"string","example":"Invalid order direction: \"DASC\". Allowed values are: \"ASC\", \"DESC\""},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/orders[matchPhrase]"}}}}}}}}}}}},"deprecated":false},"post":{"summary":"Create an exclusion","description":"Adds one rule to the exclusion list and returns it in the same shape as GET /lists/exclusions/{id}. See GET /lists/exclusions for what a rule is and how matchType and channel are read. Only users in the main admin group can create a rule with channel all, allEmail or allSms. This includes the default channel, allEmail. The caller needs permission to edit lists and to delete contacts.","operationId":"create-a-list-exclusion","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["matchPhrase","matchType"],"properties":{"matchPhrase":{"description":"The text the rule matches, such as an email address or a domain. No other rule may use the same text.","type":"string","example":"sam@example.com"},"matchType":{"description":"How matchPhrase is matched","type":"string","enum":["exact","begin","end"],"example":"exact"},"channel":{"description":"Where the rule applies","type":"string","default":"allEmail","enum":["all","allEmail","allSms","several"]},"lists":{"description":"String-quoted IDs of existing lists. Required with channel several, and must be empty or omitted for any other channel.","type":"array","items":{"type":"string"}}},"type":"object"},"example":{"matchPhrase":"sam@example.com","matchType":"exact","channel":"several","lists":["1","2"]}}}},"responses":{"200":{"description":"The new rule","content":{"application/json":{"schema":{"properties":{"id":{"type":"string"},"matchPhrase":{"type":"string"},"matchType":{"type":"string"},"channel":{"type":"string"},"hidden":{"type":"boolean"},"lists":{"description":"List IDs when channel is several, otherwise empty","type":"array","items":{"type":"string"}}},"type":"object"},"example":{"id":"15","matchPhrase":"sam@example.com","matchType":"exact","channel":"several","hidden":false,"lists":["1","2"]}}}},"400":{"description":"The body is empty, is not valid JSON, or is a single JSON value rather than an object. Nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionBadRequest"},"example":{"errors":[{"status":"400","detail":"Could not decode request body."}]}}}},"403":{"description":"The caller may not edit lists or may not delete contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"422":{"description":"A field is missing or invalid, a list does not exist, or another rule already uses matchPhrase. Nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"matchPhrase \"sam@example.com\" is not unique","source":{"pointer":"/data/attributes/matchPhrase"}}]}}}}},"x-canonical-resource":"lists","x-internal":true,"x-destructive":false,"x-bulk-operation":false},"delete":{"summary":"Delete exclusions","description":"Deletes the exclusion rules named in ids[]. With filterId, only the rules in ids[] that match that saved filter are deleted. For a user outside the main admin group, a rule is only taken off the lists that user can access, and it is deleted only when no list is left. A hidden rule is not deleted, but it is still taken off its lists. IDs that match no rule are skipped. The caller needs permission to edit lists and to delete contacts.","operationId":"delete-exclusions","parameters":[{"name":"ids[]","in":"query","description":"IDs of the rules to delete. Repeat it for each ID, for example ids[]=1&ids[]=2.","required":true,"schema":{"type":"array","items":{"type":"string"}}},{"name":"filterId","in":"query","description":"ID of a saved exclusion filter that belongs to the caller","schema":{"type":"string"},"example":"10"}],"responses":{"204":{"description":"The request was processed, even when no rule was deleted. The body is empty."},"403":{"description":"The caller may not edit lists or may not delete contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No saved exclusion filter with filterId belongs to the caller. Nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Filter with provided filterId does not exists [filterId=10, adminId=1]"}]}}}},"422":{"description":"ids[] is missing or holds a value that is not a positive whole number, or filterId is not one. Nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Missing ids","source":{"pointer":"/data/attributes/ids"}}]}}}}},"x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":true}},"/lists/exclusions/export":{"get":{"summary":"Export exclusions","description":"Downloads the exclusion rules as a file. Hidden rules and rules with an empty pattern are left out. In CSV and xls files, the first row names the columns, and each row after it is one rule. The pattern column holds the matchPhrase. A CSV file starts with a UTF-8 byte order mark. In CSV and xls files, a value that starts with =, +, - or @ gets a leading apostrophe. The caller needs permission to edit lists and to delete contacts.","operationId":"export-list-exclusions","parameters":[{"name":"format","in":"query","description":"File format","schema":{"type":"string","default":"csv","enum":["csv","xls","xml"]}},{"name":"fields[]","in":"query","description":"Columns to include, in the order given. matchPhrase is the same as pattern. Repeat it for each column. Without it, the file has id and pattern.","schema":{"type":"array","items":{"type":"string","enum":["id","pattern","matchPhrase"]}}},{"name":"filters[matchPhrase]","in":"query","description":"Only rules whose matchPhrase contains this text","schema":{"type":"string"},"example":"example.com"},{"name":"filters[lists][]","in":"query","description":"Only rules on at least one of these lists. Repeat it for each list ID. Each value is read as a whole number, and values that read as 0 are skipped.","schema":{"type":"array","items":{"type":"string"}}},{"name":"orders[matchPhrase]","in":"query","description":"Sort by matchPhrase. DESC sorts in descending order, in upper or lower case. Any other value sorts in ascending order. Without it, rules are sorted by matchPhrase in ascending order. When the file has no pattern column, they are always sorted that way.","schema":{"type":"string"}},{"name":"offset","in":"query","description":"Number of rules to skip. A negative number counts as 0.","schema":{"type":"integer","default":0}},{"name":"limit","in":"query","description":"Most rules to export. 0 or a negative number exports all of them.","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"The file, sent as an attachment. The Content-Type has charset=utf-8.","headers":{"Content-Disposition":{"description":"attachment; filename=exclusions_export. followed by the format, such as exclusions_export.csv","schema":{"type":"string"}}},"content":{"text/plain":{"schema":{"description":"A CSV file, for format csv. Every value is in double quotes.","type":"string"},"example":"\"id\",\"pattern\"\n\"15\",\"sam@example.com\"\n"},"application/vnd.ms-excel":{"schema":{"description":"An HTML table, for format xls","type":"string"}},"application/xml":{"schema":{"description":"An export element with one row element per rule, for format xml","type":"string"}}}},"400":{"description":"format or a fields[] value is not supported, an orders key other than matchPhrase or lists is sent, or a parameter was sent as a single value where a list is expected, or the other way round","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionBadRequest"},"example":{"errors":[{"status":"400","detail":"Unsupported export format \"pdf\"."}]}}}},"403":{"description":"The caller may not edit lists or may not delete contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListsExclusionErrors"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}}},"x-canonical-resource":"lists","x-internal":true}},"/lists/exclusions/{id}":{"get":{"summary":"Retrieve an exclusion","description":"Retrieve one exclusion rule by id. See GET /lists/exclusions for what a rule is and how matchType and channel are read.","operationId":"exclusions-retrieve-an-exclusion","x-canonical-resource":"lists","parameters":[{"name":"id","in":"path","description":"ID of the exclusion to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"id\": \"2\",\n    \"matchPhrase\": \"pattern\",\n    \"matchType\": \"exact\",\n    \"channel\": \"several\",\n    \"hidden\": false,\n    \"lists\": [\n        \"2\",\n        \"1\"\n    ]\n}"}},"schema":{"type":"object","properties":{"id":{"type":"string","example":"2"},"matchPhrase":{"type":"string","example":"pattern"},"matchType":{"type":"string","example":"exact"},"channel":{"type":"string","example":"several"},"hidden":{"type":"boolean","example":false,"default":true},"lists":{"type":"array","items":{"type":"string","example":"2"}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Exclusion not found [id=422]\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Exclusion not found [id=422]"}}}}}}},"deprecated":false},"put":{"summary":"Update an exclusion","description":"","operationId":"update-an-exclusion","x-canonical-resource":"lists","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The Exclusion's ID","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["all","allSms","allEmail","several"]},"lists":{"type":"array","description":"String-quoted IDs of lists. This field should **only** be provided when `channel = \"several\"`. For all other channel types, it must be either empty or omitted. If included for unsupported channel types, a 422 HTTP error will be returned.","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"id\": \"2\",\n    \"matchPhrase\": \"example@example.com\",\n    \"matchType\": \"exact\",\n    \"channel\": \"email\",\n    \"hidden\": false,\n    \"lists\": [\n    \t\"1\", \"2\"\n    ]\n}"}},"schema":{"type":"object","properties":{"id":{"type":"string","example":"2"},"matchPhrase":{"type":"string","example":"example@example.com"},"matchType":{"type":"string","example":"exact"},"channel":{"type":"string","example":"email"},"hidden":{"type":"boolean","example":false,"default":true},"lists":{"type":"array","items":{"type":"string","example":"1"}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Missing permissions":{"value":"{\n    \"message\": \"You don't have permission to access this resource\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"You don't have permission to access this resource"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Exclusion with id 404\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Exclusion with id 404"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Validation error":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"Lists must be an array of string-quoted integers\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/lists[0]\"\n            }\n        },\n        {\n            \"status\": 422,\n            \"title\": \"Invalid attribute\",\n            \"detail\": \"List IDs must be empty for channel \\\"all\\\"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/lists\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":422,"default":0},"title":{"type":"string","example":"Invalid attribute"},"detail":{"type":"string","example":"Lists must be an array of string-quoted integers"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/lists[0]"}}}}}}}}}}}},"deprecated":false}},"/lists/reassign_multiple":{"post":{"summary":"Move lists to another owner","description":"Internal. Makes `listsOwnerId` the owner of every list owned by one of the users in `userIdsToDelete`. The users themselves are not changed. If they own no lists, nothing changes and the answer is still 200. Neither user ID is checked to exist.\n\nThe fields are read from the query string or a form body; when both have a field, the query string wins. A JSON body is not read, so it gets 422. Only POST is accepted.","operationId":"reassign-lists-to-user","x-canonical-resource":"lists","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["userIdsToDelete[]","listsOwnerId"],"properties":{"userIdsToDelete[]":{"type":"array","items":{"type":"integer"},"description":"IDs of the users whose lists move, as repeated `userIdsToDelete[]` keys. A single `userIdsToDelete` value also works. Each value is read as a whole number, so an empty single value means user 0.","example":[4,5]},"listsOwnerId":{"type":"integer","description":"ID of the user who becomes the owner. Must not be empty or \"0\". Any other value is read as a whole number, so a value that is not a number makes user 0 the owner.","example":3}}}}}},"responses":{"200":{"description":"The lists were moved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true"}}},"example":{"success":true}}}},"403":{"description":"The request is not authenticated or not allowed. The body is empty."},"405":{"$ref":"#/components/responses/ListsMethodNotAllowed"},"422":{"description":"`userIdsToDelete` is missing, or `listsOwnerId` is missing, empty or \"0\". Nothing changes. The body is the plain text `Invalid arguments.`","content":{"text/plain":{"schema":{"type":"string"},"example":"Invalid arguments."}}}},"deprecated":false,"x-internal":true}},"/lists/{id}":{"get":{"summary":"Retrieve a list","description":"Retrieve one contact list by id. The single-list response carries the list's channel, description and timestamps but not the active_subscribers and non_deleted_subscribers counters; read those from GET /lists.","operationId":"retrieve-a-list","x-canonical-resource":"lists","parameters":[{"name":"id","in":"path","description":"ID of the lists to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"list\": {\n        \"stringid\": \"email-subscription\",\n        \"userid\": \"1\",\n        \"name\": \"Email Subscription\",\n        \"cdate\": \"2018-08-06T16:30:41-05:00\",\n        \"p_use_tracking\": \"1\",\n        \"p_use_analytics_read\": \"0\",\n        \"p_use_analytics_link\": \"0\",\n        \"p_use_twitter\": \"0\",\n        \"p_use_facebook\": \"0\",\n        \"p_embed_image\": \"1\",\n        \"p_use_captcha\": \"1\",\n        \"send_last_broadcast\": \"0\",\n        \"private\": \"0\",\n        \"analytics_domains\": null,\n        \"analytics_source\": \"\",\n        \"analytics_ua\": \"\",\n        \"twitter_token\": \"\",\n        \"twitter_token_secret\": \"\",\n        \"facebook_session\": null,\n        \"carboncopy\": null,\n        \"subscription_notify\": null,\n        \"unsubscription_notify\": null,\n        \"require_name\": \"0\",\n        \"get_unsubscribe_reason\": \"0\",\n        \"to_name\": \"Subscriber\",\n        \"optinoptout\": \"1\",\n        \"sender_name\": \"\",\n        \"sender_addr1\": \"\",\n        \"sender_addr2\": \"\",\n        \"sender_city\": \"\",\n        \"sender_state\": \"\",\n        \"sender_zip\": \"\",\n        \"sender_country\": \"\",\n        \"sender_phone\": \"\",\n        \"sender_url\": \"http://www.activecampaign.com\",\n        \"sender_reminder\": \"You signed up for my mailing list.\",\n        \"fulladdress\": \"\",\n        \"optinmessageid\": \"0\",\n        \"optoutconf\": \"0\",\n        \"deletestamp\": null,\n        \"udate\": null,\n        \"links\": {\n            \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/1/contactGoalLists\",\n            \"user\": \"https://:account.api-us1.com/api/3/lists/1/user\",\n            \"addressLists\": \"https://:account.api-us1.com/api/3/lists/1/addressLists\"\n        },\n        \"id\": \"1\",\n        \"user\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"list":{"type":"object","properties":{"stringid":{"type":"string","example":"email-subscription"},"userid":{"type":"string","example":"1"},"name":{"type":"string","example":"Email Subscription"},"cdate":{"type":"string","example":"2018-08-06T16:30:41-05:00"},"p_use_tracking":{"type":"string","example":"1"},"p_use_analytics_read":{"type":"string","example":"0"},"p_use_analytics_link":{"type":"string","example":"0"},"p_use_twitter":{"type":"string","example":"0"},"p_use_facebook":{"type":"string","example":"0"},"p_embed_image":{"type":"string","example":"1"},"p_use_captcha":{"type":"string","example":"1"},"send_last_broadcast":{"type":"string","example":"0"},"private":{"type":"string","example":"0"},"analytics_domains":{},"analytics_source":{"type":"string","example":""},"analytics_ua":{"type":"string","example":""},"twitter_token":{"type":"string","example":""},"twitter_token_secret":{"type":"string","example":""},"facebook_session":{},"carboncopy":{},"subscription_notify":{},"unsubscription_notify":{},"require_name":{"type":"string","example":"0"},"get_unsubscribe_reason":{"type":"string","example":"0"},"to_name":{"type":"string","example":"Subscriber"},"optinoptout":{"type":"string","example":"1"},"sender_name":{"type":"string","example":""},"sender_addr1":{"type":"string","example":""},"sender_addr2":{"type":"string","example":""},"sender_city":{"type":"string","example":""},"sender_state":{"type":"string","example":""},"sender_zip":{"type":"string","example":""},"sender_country":{"type":"string","example":""},"sender_phone":{"type":"string","example":""},"sender_url":{"type":"string","example":"http://www.activecampaign.com"},"sender_reminder":{"type":"string","example":"You signed up for my mailing list."},"fulladdress":{"type":"string","example":""},"optinmessageid":{"type":"string","example":"0"},"optoutconf":{"type":"string","example":"0"},"deletestamp":{},"udate":{},"channel":{"type":"string","example":"email","description":"The channel the list is for: email or sms."},"description":{"type":["string","null"],"example":null,"description":"The list's description, or null when none was set."},"created_timestamp":{"type":"string","example":"2019-11-13 13:45:15"},"updated_timestamp":{"type":"string","example":"2021-02-11 12:40:12"},"created_by":{"type":["string","null"],"example":null},"updated_by":{"type":["string","null"],"example":null},"links":{"type":"object","properties":{"contactGoalLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/contactGoalLists"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/user"},"addressLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/addressLists"}}},"id":{"type":"string","example":"1"},"user":{"type":"string","example":"1"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"status\": 403,\n            \"title\": \"Forbidden\",\n            \"detail\": \"You do not have permission to view lists.\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"integer","example":403,"default":0},"title":{"type":"string","example":"Forbidden"},"detail":{"type":"string","example":"You do not have permission to view lists."}}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for _List with id 7\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for _List with id 7"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a list","description":"","operationId":"delete-a-list","x-canonical-resource":"lists","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the list to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for _List with id 3\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for _List with id 3"}}}}}}},"deprecated":false},"put":{"summary":"Update a list","description":"Update an existing list.\n\nOnly the fields listed below can be changed; any other field sent in the `list` object is ignored. `name` is required on every request, even when it is not changing — omitting it is rejected. Other fields keep their current value when omitted. `name` cannot contain HTML, and for lists on the `email` channel both `sender_url` (a valid URL) and `sender_reminder` must be present after the update. A list's `channel` cannot be changed after creation.\n\n## Sender address and visibility\n\nThe postal sender fields (`sender_name`, `sender_addr1`, `sender_addr2`, `sender_city`, `sender_state`, `sender_zip`, `sender_country`, `sender_phone`) and `private` are updatable, as they are on [`POST /lists`](https://developers.activecampaign.com/reference/create-new-list), so the fields the v1 `list_edit` action wrote can all be written here.\n\nThe sender address may be updated in part: when a request carries any of the postal sender fields, the address shown in the footer of the list's campaigns is rebuilt from the list's stored values with the submitted values applied over them, so the fields the request leaves out keep their stored value. A field submitted as an empty string is removed from the address.","operationId":"update-a-list","x-canonical-resource":"lists","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the list to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"object","properties":{"name":{"type":"string","description":"Name of the list. Cannot contain HTML. Required on every request, even when unchanged."},"stringid":{"type":"string","description":"URL-safe list name. Example: 'list-name-sample'"},"sender_url":{"type":"string","description":"The website URL this list is for. Required, and must be a valid URL, for lists on the `email` channel."},"sender_reminder":{"type":"string","description":"A reminder for your contacts as to why they are on this list and you are messaging them. Required for lists on the `email` channel."},"send_last_broadcast":{"type":"boolean","description":"Whether or not to send the last sent campaign for this list to a new subscriber upon subscribing. 1 = yes, 0 = no","default":false},"carboncopy":{"type":"string","description":"Comma-separated list of email addresses to send a copy of all mailings to upon send"},"subscription_notify":{"type":"string","description":"Comma-separated list of email addresses to notify when a new subscriber joins this list."},"unsubscription_notify":{"type":"string","description":"Comma-separated list of email addresses to notify when a subscriber unsubscribes from this list."},"user":{"type":"integer","format":"int32","description":"User Id of the list owner."},"description":{"type":"string","description":"Description of the list."},"sender_name":{"type":"string","description":"Sender name shown in the postal address block of campaigns sent to this list."},"sender_addr1":{"type":"string","description":"First line of the sender's postal address."},"sender_addr2":{"type":"string","description":"Second line of the sender's postal address."},"sender_city":{"type":"string","description":"City of the sender's postal address."},"sender_state":{"type":"string","description":"State or province of the sender's postal address."},"sender_zip":{"type":"string","description":"Postal code of the sender's postal address."},"sender_country":{"type":"string","description":"Country of the sender's postal address. Accepts a two-letter country code or a country name; it determines how the address block is formatted."},"sender_phone":{"type":"string","description":"Phone number included with the sender's postal address."},"private":{"type":"boolean","description":"Whether the list is private, so that it is not offered on public-facing subscription pages. Unlike on create, where the property is presence-based, the value submitted here is written: `true` makes the list private and `false` makes it public.","example":true}},"required":["name"],"additionalProperties":false}},"required":["list"],"additionalProperties":false},"examples":{"Request Example":{"value":{"list":{"name":"Name of List","stringid":"Name-of-list","sender_url":"http://activecampaign.com","sender_reminder":"You are receiving this email as you subscribed to a newsletter when making an order on our site."}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"list\": {\n        \"stringid\": \"email-subscription\",\n        \"userid\": \"1\",\n        \"name\": \"Email Subscription\",\n        \"cdate\": \"2018-08-06T16:30:41-05:00\",\n        \"p_use_tracking\": \"1\",\n        \"p_use_analytics_read\": \"0\",\n        \"p_use_analytics_link\": \"0\",\n        \"p_use_twitter\": \"0\",\n        \"p_use_facebook\": \"0\",\n        \"p_embed_image\": \"1\",\n        \"p_use_captcha\": \"1\",\n        \"send_last_broadcast\": \"0\",\n        \"private\": \"0\",\n        \"analytics_domains\": null,\n        \"analytics_source\": \"\",\n        \"analytics_ua\": \"\",\n        \"twitter_token\": \"\",\n        \"twitter_token_secret\": \"\",\n        \"facebook_session\": null,\n        \"carboncopy\": null,\n        \"subscription_notify\": null,\n        \"unsubscription_notify\": null,\n        \"require_name\": \"0\",\n        \"get_unsubscribe_reason\": \"0\",\n        \"to_name\": \"Subscriber\",\n        \"optinoptout\": \"1\",\n        \"sender_name\": \"\",\n        \"sender_addr1\": \"\",\n        \"sender_addr2\": \"\",\n        \"sender_city\": \"\",\n        \"sender_state\": \"\",\n        \"sender_zip\": \"\",\n        \"sender_country\": \"\",\n        \"sender_phone\": \"\",\n        \"sender_url\": \"http://www.activecampaign.com\",\n        \"sender_reminder\": \"You signed up for my mailing list.\",\n        \"fulladdress\": \"\",\n        \"optinmessageid\": \"0\",\n        \"optoutconf\": \"0\",\n        \"deletestamp\": null,\n        \"udate\": null,\n        \"links\": {\n            \"contactGoalLists\": \"https://:account.api-us1.com/api/3/lists/1/contactGoalLists\",\n            \"user\": \"https://:account.api-us1.com/api/3/lists/1/user\",\n            \"addressLists\": \"https://:account.api-us1.com/api/3/lists/1/addressLists\"\n        },\n        \"id\": \"1\",\n        \"user\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"list":{"type":"object","properties":{"stringid":{"type":"string","example":"email-subscription"},"userid":{"type":"string","example":"1"},"name":{"type":"string","example":"Email Subscription"},"cdate":{"type":"string","example":"2018-08-06T16:30:41-05:00"},"p_use_tracking":{"type":"string","example":"1"},"p_use_analytics_read":{"type":"string","example":"0"},"p_use_analytics_link":{"type":"string","example":"0"},"p_use_twitter":{"type":"string","example":"0"},"p_use_facebook":{"type":"string","example":"0"},"p_embed_image":{"type":"string","example":"1"},"p_use_captcha":{"type":"string","example":"1"},"send_last_broadcast":{"type":"string","example":"0"},"private":{"type":"string","example":"0"},"analytics_domains":{},"analytics_source":{"type":"string","example":""},"analytics_ua":{"type":"string","example":""},"twitter_token":{"type":"string","example":""},"twitter_token_secret":{"type":"string","example":""},"facebook_session":{},"carboncopy":{},"subscription_notify":{},"unsubscription_notify":{},"require_name":{"type":"string","example":"0"},"get_unsubscribe_reason":{"type":"string","example":"0"},"to_name":{"type":"string","example":"Subscriber"},"optinoptout":{"type":"string","example":"1"},"sender_name":{"type":"string","example":""},"sender_addr1":{"type":"string","example":""},"sender_addr2":{"type":"string","example":""},"sender_city":{"type":"string","example":""},"sender_state":{"type":"string","example":""},"sender_zip":{"type":"string","example":""},"sender_country":{"type":"string","example":""},"sender_phone":{"type":"string","example":""},"sender_url":{"type":"string","example":"http://www.activecampaign.com"},"sender_reminder":{"type":"string","example":"You signed up for my mailing list."},"fulladdress":{"type":"string","example":""},"optinmessageid":{"type":"string","example":"0"},"optoutconf":{"type":"string","example":"0"},"deletestamp":{},"udate":{},"links":{"type":"object","properties":{"contactGoalLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/contactGoalLists"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/user"},"addressLists":{"type":"string","example":"https://:account.api-us1.com/api/3/lists/1/addressLists"}}},"id":{"type":"string","example":"1"},"user":{"type":"string","example":"1"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"You do not have permission to edit lists.\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have permission to edit lists."}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for List with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for List with id 1"}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"This value should not be blank.\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sender_reminder\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"This value should not be blank."},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/sender_reminder"}}}}}}}}}}}},"deprecated":false}},"/lists/{listId}/bulkDelete":{"delete":{"summary":"Delete the contacts that are only on a list","description":"Deletes up to limit contacts that are on this list and on no other list. Contacts are taken lowest contact ID first, whatever their status on the list. Each one is taken off the list and then deleted: its tags, account links and custom object records are removed (the custom object records in the background when a feature flag is on), and a deal whose primary contact it is passes to a secondary contact, stays with its account, or is deleted. Deleted contacts move to the contact archive. Contacts that are also on another list stay on this list. The list itself is not deleted. Call again until deletedContacts is 0 to remove every such contact. The cached list contact counts are cleared after each call that returns 200. Most database errors while deleting do not stop the call, which still returns 200; only some, such as a lost connection, a read-only database or the statement time limit, return 400. A list ID that does not exist, or a list with no such contacts, deletes nothing and returns deletedContacts 0. Works only while the feature flag feature-flags-list-large-delete is on; otherwise the call returns 400 and deletes nothing. DELETE /lists/{listId}/bulk_delete does the same.","operationId":"bulk-delete-list-only-contacts","parameters":[{"name":"listId","in":"path","description":"ID of the list whose contacts are deleted.","required":true,"schema":{"type":"integer"},"example":12},{"name":"limit","in":"query","description":"Most contacts to delete in this call. Must be 1 or more: a missing or empty value, or any value below 1, including fractions such as 0.5, returns 400. A decimal of 1 or more is cut to a whole number, so 2.9 deletes up to 2. There is no upper bound.","required":true,"schema":{"type":"integer","minimum":1},"example":1000}],"responses":{"200":{"description":"The call finished. deletedContacts counts the contacts picked, also when a database error kept some of them from being deleted.","content":{"application/json":{"schema":{"required":["success","deletedContacts"],"properties":{"success":{"description":"Always true here.","type":"boolean","example":true},"deletedContacts":{"description":"How many contacts this call picked for deletion. 0 when none were left.","type":"integer","example":1000}},"type":"object"},"example":{"success":true,"deletedContacts":1000}}}},"400":{"description":"Refused or failed. The feature flag is off: message \"You do not have permission to execute this\", and nothing is deleted. limit is missing or below 1: message \"Invalid request\", and nothing is deleted. An error while deleting, such as a lost connection, a read-only database or the statement time limit: message \"Invalid request\", and contacts taken off the list or deleted before the error stay that way. Most other database errors do not stop the call.","content":{"application/json":{"schema":{"required":["success","message"],"properties":{"success":{"type":"boolean","example":false},"message":{"type":"string","enum":["You do not have permission to execute this","Invalid request"],"example":"Invalid request"}},"type":"object"},"example":{"success":false,"message":"Invalid request"}}}}},"x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":true}},"/lists/{listId}/bulk_delete":{"delete":{"summary":"Delete the contacts that are only on a list (bulk_delete spelling)","description":"Deletes up to limit contacts that are on this list and on no other list. Contacts are taken lowest contact ID first, whatever their status on the list. Each one is taken off the list and then deleted: its tags, account links and custom object records are removed (the custom object records in the background when a feature flag is on), and a deal whose primary contact it is passes to a secondary contact, stays with its account, or is deleted. Deleted contacts move to the contact archive. Contacts that are also on another list stay on this list. The list itself is not deleted. Call again until deletedContacts is 0 to remove every such contact. The cached list contact counts are cleared after each call that returns 200. Most database errors while deleting do not stop the call, which still returns 200; only some, such as a lost connection, a read-only database or the statement time limit, return 400. A list ID that does not exist, or a list with no such contacts, deletes nothing and returns deletedContacts 0. Works only while the feature flag feature-flags-list-large-delete is on; otherwise the call returns 400 and deletes nothing. This is DELETE /lists/{listId}/bulkDelete under another path.","operationId":"bulk-delete-list-only-contacts-alias","parameters":[{"name":"listId","in":"path","description":"ID of the list whose contacts are deleted.","required":true,"schema":{"type":"integer"},"example":12},{"name":"limit","in":"query","description":"Most contacts to delete in this call. Must be 1 or more: a missing or empty value, or any value below 1, including fractions such as 0.5, returns 400. A decimal of 1 or more is cut to a whole number, so 2.9 deletes up to 2. There is no upper bound.","required":true,"schema":{"type":"integer","minimum":1},"example":1000}],"responses":{"200":{"description":"The call finished. deletedContacts counts the contacts picked, also when a database error kept some of them from being deleted.","content":{"application/json":{"schema":{"required":["success","deletedContacts"],"properties":{"success":{"description":"Always true here.","type":"boolean","example":true},"deletedContacts":{"description":"How many contacts this call picked for deletion. 0 when none were left.","type":"integer","example":1000}},"type":"object"},"example":{"success":true,"deletedContacts":1000}}}},"400":{"description":"Refused or failed. The feature flag is off: message \"You do not have permission to execute this\", and nothing is deleted. limit is missing or below 1: message \"Invalid request\", and nothing is deleted. An error while deleting, such as a lost connection, a read-only database or the statement time limit: message \"Invalid request\", and contacts taken off the list or deleted before the error stay that way. Most other database errors do not stop the call.","content":{"application/json":{"schema":{"required":["success","message"],"properties":{"success":{"type":"boolean","example":false},"message":{"type":"string","enum":["You do not have permission to execute this","Invalid request"],"example":"Invalid request"}},"type":"object"},"example":{"success":false,"message":"Invalid request"}}}}},"x-canonical-resource":"lists","x-internal":true,"x-destructive":true,"x-bulk-operation":true}},"/lists/{listId}/latestReportTotals":{"get":{"summary":"Retrieve the report totals of the last campaign sent to a list","description":"The report totals of the last campaign sent to the list. This is the v3 counterpart of calling the v1 campaign_report_totals action with only listid. The last campaign is the completed campaign (status 5) with the highest ID among the campaigns sent to the list. It is not chosen by send date. The totals and the query parameters are the same as for the report totals of that campaign. Totals are lifetime unless both startDate and endDate are sent. Every field is always present; a field the chosen branch does not compute is null. The account must be entitled to campaigns, and the user must be able to see the chosen campaign.","operationId":"retrieve-list-latest-report-totals","parameters":[{"name":"listId","in":"path","description":"ID of the list","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"messageId","in":"query","description":"Restrict the totals to one message of the chosen campaign. This works only when that campaign is a split campaign; for any other campaign the whole campaign is reported. 0, the default, reports the whole campaign.","required":false,"schema":{"type":"integer","default":0,"minimum":0},"example":0},{"name":"startDate","in":"query","description":"Start of the date window, as Y-m-d, Y-m-d H:i:s or Y-m-d\\TH:i:s; a date alone starts at midnight. Send together with endDate.","required":false,"schema":{"type":"string"},"example":"2026-09-01"},{"name":"endDate","in":"query","description":"End of the date window, in the same formats as startDate; may not be earlier than startDate. Send together with startDate.","required":false,"schema":{"type":"string"},"example":"2026-09-30 23:59:59"},{"name":"includeBots","in":"query","description":"true, the default, counts clicks identified as bot clicks; false leaves them out of the click counters. This applies only to lifetime totals: with startDate and endDate, bot clicks are always counted. Only true or false is accepted.","required":false,"schema":{"type":"string","default":"true","enum":["true","false"]},"example":"false"}],"responses":{"200":{"description":"The totals","content":{"application/json":{"schema":{"properties":{"ldate":{"description":"When the campaign was last sent, as stored (Y-m-d H:i:s).","type":["string","null"],"example":"2026-09-28 09:00:00"},"status":{"description":"Status code of the campaign, as on the campaign record (5 is completed).","type":["integer","null"],"example":5},"type":{"description":"Type of the campaign, as on the campaign record (single, split, ...); null in a date window on a single message.","type":["string","null"],"example":"single"},"messageId":{"description":"The message reported on: the messageId sent, or, for the whole campaign, the IDs of all its messages joined with commas.","type":["string","null"],"example":"7"},"totalAmt":{"description":"Number of sends delivered.","type":["integer","null"],"example":1000},"sendAmt":{"description":"Number of sends attempted.","type":["integer","null"],"example":1000},"uniqueOpens":{"description":"Number of contacts who opened at least once.","type":["integer","null"],"example":400},"verifiedUniqueOpens":{"description":"Unique opens confirmed as human.","type":["integer","null"],"example":350},"uniqueLinkClicks":{"description":"Number of distinct links clicked; in a date window, the number of contacts who clicked.","type":["integer","null"],"example":4},"subscriberClicks":{"description":"Number of contacts who clicked at least one link.","type":["integer","null"],"example":120},"unsubscribes":{"description":"Number of contacts who unsubscribed through the campaign.","type":["integer","null"],"example":3},"forwards":{"description":"Total forwards.","type":["integer","null"],"example":5},"uniqueForwards":{"description":"Number of contacts who forwarded at least once.","type":["integer","null"],"example":4},"uniqueReplies":{"description":"Number of contacts who replied at least once. Lifetime totals only.","type":["integer","null"],"example":2},"updates":{"description":"Number of contacts who updated their profile. Lifetime totals only.","type":["integer","null"],"example":1},"totalBounces":{"description":"Hard and soft bounces added together. Lifetime totals only.","type":["integer","null"],"example":6},"socialShares":{"description":"Number of social shares. Lifetime totals only.","type":["integer","null"],"example":0},"replies":{"description":"Reply records counted in the window. Date window only.","type":["integer","null"],"example":1},"bounces":{"description":"Number of contacts who bounced in the window. Date window only.","type":["integer","null"],"example":6},"shares":{"description":"Number of shares in the window. Date window only.","type":["integer","null"],"example":0},"revenue":{"description":"Revenue attributed to the campaign, one item per currency; the whole campaign's revenue even when messageId is sent. Lifetime totals only; null in a date window.","type":["array","null"],"items":{"properties":{"revenue_generator_id":{"description":"ID of the campaign the revenue is attributed to.","type":"string","example":"12"},"currency":{"description":"Currency code, uppercased.","type":"string","example":"USD"},"total_revenue":{"description":"Attributed revenue in the minor unit of the currency (cents for USD).","type":"string","example":"125000"},"revenue_generator_type":{"description":"Always Campaign.","type":"string","example":"Campaign"},"total_revenue_formatted":{"description":"total_revenue formatted for display in the currency.","type":"string","example":"$1,250.00"}},"type":"object"}}},"type":"object"}}}},"400":{"description":"messageId is not one of the messages of the chosen split campaign. Body: errors, a list with one item carrying status \"400\" and detail, the localized reason."},"403":{"description":"The account is not entitled to campaigns (detail \"This account is not entitled to campaigns.\") or the user may not see the chosen campaign (detail \"Forbidden\"). Body: errors, a list with one item carrying status \"403\" and detail."},"404":{"description":"No completed campaign was sent to the list (detail \"No sent campaign found for list {listId}.\"), which is also the answer for a list that does not exist, or no totals were found for the chosen campaign (detail \"No report totals found for campaign {campaignId}.\"). Body: errors, a list with one item carrying status \"404\" and detail."},"422":{"description":"A query parameter is invalid: empty or not a single value, messageId not a whole number of 0 or more, includeBots not true or false, a date in another format, only one of startDate and endDate, or endDate before startDate. Body: errors, a list with one item carrying status \"422\" and detail naming the problem."}},"x-canonical-resource":"campaign","x-internal":true}},"/localevent":{"post":{"summary":"Local Events","description":"Published by TrackCmp. Creates an em_local_event row in production database.","operationId":"local-events","x-canonical-resource":"localevent","x-destructive":false,"x-bulk-operation":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"localEvent":{"type":"object","description":"Data about local event sent by TrackCmp","properties":{"input":{"type":"string","description":"Example: \"{\\\"event\\\":\\\"__pagevisit\\\",\\\"url\\\":\\\"www.url.com\\\"}\"","format":"json"}},"additionalProperties":false},"entries":{"type":"array","items":{"type":"object","properties":{"localEvent":{"type":"object","description":"The event, as in the single-event form.","properties":{"input":{"type":"string","contentMediaType":"application/json","description":"JSON-encoded event object, as in the single-event form."}},"additionalProperties":false}},"additionalProperties":false},"description":"Batch form: several events, each shaped like the single-event body. When present, the root localEvent is ignored; duplicate entries are skipped."}},"additionalProperties":false}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\"message\": \"Email message\"}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Email message"}}}}}}},"deprecated":false,"x-internal":true}},"/looker/acquireCookielessSession":{"post":{"summary":"Acquire a Looker cookieless embed session","description":"Opens a Looker cookieless embed session for the calling user on one explore or LookML dashboard, or attaches another embed to the session the page already holds, and returns the tokens the Looker embed SDK needs. The session is created for the calling user and account whatever names or group the body carries, with the account's data access and entitlements as Looker user attributes and the permissions and model of the page. Before acquiring, the user's embed user is looked up in Looker: a disabled one is enabled again, its older sessions are signed out and its user attributes are brought up to date; a failure there is logged and does not stop the call. Internal: backs the embedded reports in the app.","operationId":"acquire-looker-cookieless-session","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["external_user_id","page","target"],"properties":{"external_user_id":{"description":"The calling user's embed ID, <account ID>-<user ID>. Required: any other value, or none, answers 403. externalUserId is accepted in its place.","type":"string","example":"1234-5"},"page":{"description":"The report page, which sets the Looker permissions and model. custom and cr_download_all need the custom reports entitlement; any other value answers 403.","type":"string","enum":["custom","cr_download_all","export","see_drills","deals"],"example":"export"},"target":{"description":"What to embed: <model>/<explore> for an explore, or <model>::<dashboard> for a LookML dashboard, in letters, digits, _ and -. Anything else answers 403.","type":"string","example":"reporting::tags_overview"},"user_timezone":{"description":"Time zone to show the report in, as an IANA name. America/Chicago when it is missing or not a known zone.","type":"string","example":"America/Chicago"},"embed_domain":{"description":"Origin of the page that hosts the embed, as http(s)://host[:port]. The origin of this request when it is missing or not of that form.","type":"string","example":"https://example.activehosted.com"},"session_reference_token":{"description":"The session_reference_token of the session the page already holds, to attach this embed to it instead of opening another. Needs session_token_hmac.","type":"string","example":"session-ref-789"},"session_token_hmac":{"description":"The session_token_hmac returned with session_reference_token. Required with session_reference_token: a missing or wrong value answers 403.","type":"string","example":"5f2b9c..."},"external_group_id":{"description":"Sent by the app; ignored. The session's group is always the account.","type":"string","example":"1234"},"first_name":{"description":"Sent by the app; ignored. The session carries the calling user's own name.","type":"string","example":"Jane"},"last_name":{"description":"Sent by the app; ignored. The session carries the calling user's own name.","type":"string","example":"Doe"}},"type":"object"}}}},"responses":{"200":{"description":"The session tokens, as Looker returns them, with the Looker host and the signature the app sends back when it reuses or refreshes the session.","content":{"application/json":{"schema":{"properties":{"authentication_token":{"description":"One-time token that establishes the embed session.","type":"string","example":"auth-token-123"},"authentication_token_ttl":{"description":"Seconds authentication_token stays valid.","type":"integer","example":30},"navigation_token":{"description":"Token that loads and navigates pages in the embedded session.","type":"string","example":"nav-token-456"},"navigation_token_ttl":{"description":"Seconds navigation_token stays valid.","type":"integer","example":600},"api_token":{"description":"Token the embedded Looker application calls Looker APIs with.","type":"string","example":"api-token-012"},"api_token_ttl":{"description":"Seconds api_token stays valid.","type":"integer","example":600},"session_reference_token":{"description":"Reference to the session, sent back to attach further embeds or refresh the tokens.","type":"string","example":"session-ref-789"},"session_reference_token_ttl":{"description":"Seconds the session stays valid.","type":"integer","example":90000},"looker_host":{"description":"The Looker embed host, without the scheme. Added by this endpoint.","type":"string","example":"example.looker.com"},"session_token_hmac":{"description":"Signature binding session_reference_token to the calling user. Added by this endpoint when Looker returns a session_reference_token; required to reuse or refresh the session.","type":"string","example":"5f2b9c..."}},"type":"object"}}}},"403":{"description":"external_user_id is not the calling user's, page is unknown or needs an entitlement the account lacks, target is not of either form, or session_token_hmac does not match.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Account not entitled for page: custom"}]}}}},"404":{"description":"Looker answered 404 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Looker resource not found, max retries exceeded"}]}}}},"422":{"description":"Looker answered 400 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute"}]}}}},"502":{"description":"After three retries, Looker could not be reached, answered with a status other than 400 or 404, or returned a body without the expected tokens.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Looker request failed\".","type":"string","example":"Looker request failed"}},"type":"object"}}}}},"x-canonical-resource":"report","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/looker/config":{"get":{"summary":"Retrieve the Looker embed host","description":"The host the Looker embed SDK loads reports from, which the app needs before it can open a cookieless embed session. The same for every account on the deployment. Internal: backs the embedded reports in the app.","operationId":"retrieve-looker-embed-config","responses":{"200":{"description":"The Looker host.","content":{"application/json":{"schema":{"required":["host"],"properties":{"host":{"description":"The Looker embed host, without the scheme.","type":"string","example":"example.looker.com"}},"type":"object"}}}}},"x-canonical-resource":"report","x-internal":true}},"/looker/embedUrl":{"get":{"summary":"Create a signed Looker embed URL","description":"Signs a single sign-on embed URL for one Looker dashboard or explore, for the calling user, the legacy (cookie-based) way of embedding a report. The URL logs the user into Looker as their embed user, with the account's data access and entitlements as Looker user attributes and the permission set the page names. When willForceLogin is true the embed user is looked up in Looker first: a disabled embed user is enabled again and its older sessions are signed out. Internal: backs the embedded reports in the app.","operationId":"retrieve-looker-embed-url","parameters":[{"name":"embedUser","in":"query","description":"The calling user's embed user, as a JSON object: firstName, lastName, email, externalUserId and externalGroupId. externalUserId must be the calling user's <account ID>-<user ID>. Keys are turned to snake_case; first_name, last_name, external_user_id and external_group_id are passed into the URL and the rest are dropped.","required":true,"schema":{"type":"string"},"example":"{\"firstName\":\"Jane\",\"lastName\":\"Doe\",\"email\":\"jane@example.com\",\"externalUserId\":\"1234-5\",\"externalGroupId\":\"1234\"}"},{"name":"dashboard","in":"query","description":"What to embed, as a JSON object: dashboard (the Looker content path, such as embed/dashboards/12), willForceLogin (true to log the user out of an existing Looker session first), page (custom, cr_download_all, deals, see_drills or export: picks the Looker permissions, and for custom the model; any other value grants no permissions), zone (the time zone to show the report in) and, optionally, filters (an object of Looker filter names to values, added to the content path as its query string).","required":true,"schema":{"type":"string"},"example":"{\"dashboard\":\"embed/dashboards/12\",\"willForceLogin\":true,\"page\":\"export\",\"zone\":\"America/Chicago\",\"filters\":{\"filter_seriesid\":10}}"}],"responses":{"200":{"description":"The signed URL. The Looker session it opens lasts up to 90000 seconds (25 hours).","content":{"application/json":{"schema":{"required":["embedUrl"],"properties":{"embedUrl":{"description":"The Looker single sign-on URL to load in the embed iframe: the Looker host, /login/embed/ and the content path, with the signed parameters as its query string.","type":"string","example":"https://example.looker.com/login/embed/embed%2Fdashboards%2F12?nonce=...&signature=..."}},"type":"object"}}}},"403":{"description":"embedUser or dashboard is missing or not JSON, externalUserId is not the calling user's, or, with willForceLogin, Looker refused the embed user lookup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Improper user credentials provided"}]}}}},"404":{"description":"With willForceLogin, Looker has no embed user for externalUserId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Looker embed user not found, max retries exceeded"}]}}}},"500":{"description":"With willForceLogin, Looker could not be reached or failed after three retries.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Something went wrong on our end. Please try again later\".","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"report","x-internal":true}},"/looker/generateCookielessTokens":{"put":{"summary":"Refresh the tokens of a Looker cookieless embed session","description":"Asks Looker for new navigation and API tokens for the calling user's cookieless embed session before the current ones expire. The app sends POST; PUT is routed to the same action and answers the same way. Internal: backs the embedded reports in the app.","operationId":"generate-looker-cookieless-tokens-via-put","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["external_user_id","session_reference_token","session_token_hmac"],"properties":{"external_user_id":{"description":"The calling user's embed ID, <account ID>-<user ID>. Required: any other value, or none, answers 403. externalUserId is accepted in its place.","type":"string","example":"1234-5"},"session_reference_token":{"description":"The session_reference_token the session was acquired with. Required: a missing or empty value answers 400.","type":"string","example":"session-ref-789"},"session_token_hmac":{"description":"The session_token_hmac returned with the session. Required: a missing or wrong value answers 403.","type":"string","example":"5f2b9c..."},"navigation_token":{"description":"The navigation token the session holds now. Sent to Looker as an empty string when missing.","type":"string","example":"nav-token-456"},"api_token":{"description":"The API token the session holds now. Sent to Looker as an empty string when missing.","type":"string","example":"api-token-012"}},"type":"object"}}}},"responses":{"200":{"description":"The new tokens, as Looker returns them.","content":{"application/json":{"schema":{"properties":{"navigation_token":{"description":"New token that loads and navigates pages in the embedded session.","type":"string","example":"new-nav-token"},"navigation_token_ttl":{"description":"Seconds navigation_token stays valid.","type":"integer","example":600},"api_token":{"description":"New token the embedded Looker application calls Looker APIs with.","type":"string","example":"new-api-token"},"api_token_ttl":{"description":"Seconds api_token stays valid.","type":"integer","example":600},"session_reference_token_ttl":{"description":"Seconds the session has left. 0 or missing once it has expired, which the app takes as the end of the session.","type":"integer","example":89400}},"type":"object"}}}},"400":{"description":"session_reference_token is missing or empty.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"session_reference_token is required\".","type":"string","example":"session_reference_token is required"}},"type":"object"}}}},"403":{"description":"external_user_id is not the calling user's, or session_token_hmac does not match the session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Improper user credentials provided"}]}}}},"404":{"description":"Looker answered 404 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Looker resource not found, max retries exceeded"}]}}}},"422":{"description":"Looker answered 400 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute"}]}}}},"502":{"description":"After three retries, Looker could not be reached, answered with a status other than 400 or 404, or returned a body without the expected tokens.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Looker request failed\".","type":"string","example":"Looker request failed"}},"type":"object"}}}}},"x-canonical-resource":"report","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"post":{"summary":"Refresh the tokens of a Looker cookieless embed session","description":"Asks Looker for new navigation and API tokens for the calling user's cookieless embed session before the current ones expire. The app sends POST; PUT is routed to the same action and answers the same way. Internal: backs the embedded reports in the app.","operationId":"generate-looker-cookieless-tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["external_user_id","session_reference_token","session_token_hmac"],"properties":{"external_user_id":{"description":"The calling user's embed ID, <account ID>-<user ID>. Required: any other value, or none, answers 403. externalUserId is accepted in its place.","type":"string","example":"1234-5"},"session_reference_token":{"description":"The session_reference_token the session was acquired with. Required: a missing or empty value answers 400.","type":"string","example":"session-ref-789"},"session_token_hmac":{"description":"The session_token_hmac returned with the session. Required: a missing or wrong value answers 403.","type":"string","example":"5f2b9c..."},"navigation_token":{"description":"The navigation token the session holds now. Sent to Looker as an empty string when missing.","type":"string","example":"nav-token-456"},"api_token":{"description":"The API token the session holds now. Sent to Looker as an empty string when missing.","type":"string","example":"api-token-012"}},"type":"object"}}}},"responses":{"200":{"description":"The new tokens, as Looker returns them.","content":{"application/json":{"schema":{"properties":{"navigation_token":{"description":"New token that loads and navigates pages in the embedded session.","type":"string","example":"new-nav-token"},"navigation_token_ttl":{"description":"Seconds navigation_token stays valid.","type":"integer","example":600},"api_token":{"description":"New token the embedded Looker application calls Looker APIs with.","type":"string","example":"new-api-token"},"api_token_ttl":{"description":"Seconds api_token stays valid.","type":"integer","example":600},"session_reference_token_ttl":{"description":"Seconds the session has left. 0 or missing once it has expired, which the app takes as the end of the session.","type":"integer","example":89400}},"type":"object"}}}},"400":{"description":"session_reference_token is missing or empty.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"session_reference_token is required\".","type":"string","example":"session_reference_token is required"}},"type":"object"}}}},"403":{"description":"external_user_id is not the calling user's, or session_token_hmac does not match the session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"Improper user credentials provided"}]}}}},"404":{"description":"Looker answered 404 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":404,"title":"Not Found","detail":"Looker resource not found, max retries exceeded"}]}}}},"422":{"description":"Looker answered 400 to the call three retries in a row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":422,"title":"Invalid attribute"}]}}}},"502":{"description":"After three retries, Looker could not be reached, answered with a status other than 400 or 404, or returned a body without the expected tokens.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Always \"Looker request failed\".","type":"string","example":"Looker request failed"}},"type":"object"}}}}},"x-canonical-resource":"report","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/lookupFields":{"get":{"summary":"List the fields a lookup field may show","description":"Given the CRM object a lookup field is added to, lists every other CRM object with every standard and custom field it has: object=deal returns account and contact, object=account returns contact and deal, object=contact returns account and deal. Accounts are left out for an account without the accounts feature, and deals for a user without the pg_deal permission. Contact custom fields are those the user may see. Lookup and calculated custom fields are left out, as they have no value of their own. Returns 404 while the crm-lookup-fields feature is off and 400 when object is missing or not one of the three.","operationId":"list-lookup-fields","parameters":[{"name":"object","in":"query","description":"The CRM object the lookup field is added to","required":true,"schema":{"type":"string","enum":["account","contact","deal"]}}],"responses":{"200":{"description":"The objects a lookup field may point at","content":{"application/json":{"schema":{"properties":{"lookupObjects":{"type":"array","items":{"properties":{"id":{"description":"The object","type":"string","enum":["account","contact","deal"]},"name":{"description":"The object name, translated for the user","type":"string","example":"Contact"},"fields":{"description":"Its standard fields, then its custom fields","type":"array","items":{"$ref":"#/components/schemas/LookupField"}}},"type":"object"}}},"type":"object"},"example":{"lookupObjects":[{"id":"contact","name":"Contact","fields":[{"id":"firstName","name":"First Name","type":"text","isCustom":false,"options":[]},{"id":"9","name":"Size","type":"dropdown","isCustom":true,"options":[{"label":"Small","value":"s"}]}]}]}}}},"400":{"description":"object is missing or not one of account, contact, deal. Body: errors, a list with one item carrying status and detail."},"404":{"description":"The crm-lookup-fields feature is off for the account. Body: errors, a list with one item carrying status and detail."}},"x-canonical-resource":"custom_field_definition","x-internal":true}},"/message/body_html":{"get":{"summary":"Retrieve the HTML preview of a message","description":"The full HTML of a message as one contact received it, wrapped in a small HTML page, for the full preview of an email in a contact's activity stream. A campaign or one-off email is rendered for `contact_id` with its personalization and conditional content applied. Any other message, such as a reply, is personalized for the contact (and for `deal_id` and `account_id` when given), falls back to its text when it has no HTML, and is sanitized before it is returned. Deal email previews are served by a different endpoint.\n\nWhen `message_id` or `contact_id` is missing, or `message_id` is `false`, the response is 200 with an empty body. Only GET is answered: any other method gets an empty 200 response.","operationId":"retrieve-a-message-html-preview","x-canonical-resource":"message","parameters":[{"name":"message_id","in":"query","description":"ID of the message.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"contact_id","in":"query","description":"ID of the contact the message is rendered for.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"deal_id","in":"query","description":"ID of a deal whose fields fill deal personalization tags. Only used for a message that is not part of a campaign.","schema":{"type":"integer","format":"int32"}},{"name":"account_id","in":"query","description":"ID of a CRM account whose fields fill account personalization tags. Only used for a message that is not part of a campaign.","schema":{"type":"integer","format":"int32"}},{"name":"notrack","in":"query","description":"`0`, or an empty value, keeps the message's tracked links as they are. Any other value, or leaving the parameter out, marks every tracked link `notrack=1` so clicks in the preview are not counted.","schema":{"type":"integer","format":"int32","default":1}},{"name":"encrypt-links","in":"query","description":"When present, `1` encrypts the tracked link URLs of the rendering and `0` leaves them unencrypted. Omit it to keep the default.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"An HTML page whose body is the message content. Empty when a required parameter is missing.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"The message is not part of a campaign and no message has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the id.","example":"No Result found for Message with id 543"}}}}}}},"deprecated":false,"x-internal":true}},"/message/body_text":{"get":{"summary":"Retrieve the text preview of a message","description":"The first 90 characters of a message's text as one contact received it, wrapped in a small HTML page, for the partial previews of emails, notes and tasks in a contact's activity stream. A campaign or one-off email is rendered for `contact_id` with its personalization and conditional content applied, and HTML tags are stripped from its text. Any other message, such as a reply, is personalized for the contact (and for `deal_id` and `account_id` when given) and sanitized. The full HTML preview is GET /message/body_html.\n\nWhen `message_id` or `contact_id` is missing, or `message_id` is `false` for a message that is not part of a campaign, the response is 200 with an empty body. Only GET is answered: any other method gets an empty 200 response.","operationId":"retrieve-a-message-text-preview","x-canonical-resource":"message","parameters":[{"name":"message_id","in":"query","description":"ID of the message.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"contact_id","in":"query","description":"ID of the contact the message is rendered for.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"deal_id","in":"query","description":"ID of a deal whose fields fill deal personalization tags. Only used for a message that is not part of a campaign.","schema":{"type":"integer","format":"int32"}},{"name":"account_id","in":"query","description":"ID of a CRM account whose fields fill account personalization tags. Only used for a message that is not part of a campaign.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"An HTML page whose body is the first 90 characters of the message text. Empty when a required parameter is missing.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"The message is not part of a campaign and no message has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the id.","example":"No Result found for Message with id 543"}}}}}}},"deprecated":false,"x-internal":true}},"/message/open":{"get":{"summary":"Retrieve the HTML preview of a campaign message with tracking left on","description":"The HTML of a campaign or one-off email as one contact received it, rendered for `contact_id` with its personalization and conditional content applied and wrapped in a small HTML page. Unlike GET /message/body_html, `notrack=1` is removed from the tracked links, so clicks made in this rendering are tracked.\n\nThe message is only rendered when it is part of a campaign. For any other message that exists the page body is empty. When `message_id` or `contact_id` is missing, or `message_id` is `false`, the response is 200 with an empty body. Only GET is answered: any other method gets an empty 200 response.","operationId":"retrieve-a-message-tracked-html-preview","x-canonical-resource":"message","parameters":[{"name":"message_id","in":"query","description":"ID of the message.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"contact_id","in":"query","description":"ID of the contact the message is rendered for.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"deal_id","in":"query","description":"Accepted for parity with GET /message/body_html; it has no effect on the response.","schema":{"type":"integer","format":"int32"}},{"name":"account_id","in":"query","description":"Accepted for parity with GET /message/body_html; it has no effect on the response.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"An HTML page whose body is the message content. Empty when a required parameter is missing or the message is not part of a campaign.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"The message is not part of a campaign and no message has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the id.","example":"No Result found for Message with id 543"}}}}}}},"deprecated":false,"x-internal":true}},"/message/populate_initial_content":{"put":{"summary":"Populate the initial content of campaign messages","description":"Gives each listed message that has no content yet the starting content of its campaign, built from the campaign's base message or base template (a message of the legacy drag-and-drop designer with neither gets the designer's default layout). For a message built with the current email designer an initial version is also recorded in its version history.\n\nA message that already has HTML or text content is skipped, so the call is safe to retry: a retry completes the messages that failed the first time. Every listed message is processed before the call answers; when any of them fails the call answers 409, and the messages that succeeded stay populated.\n\nThe request takes no body.","operationId":"populate-initial-message-content","parameters":[{"name":"message_ids","in":"query","description":"Comma-separated ids of the messages to populate. Each message must belong to a campaign; an id that is not a number names no message and fails.","required":true,"schema":{"type":"string"},"example":"12,13"}],"responses":{"200":{"description":"Every listed message has content: it was populated now or already had content.","content":{"application/json":{"schema":{"required":["succeeded"],"properties":{"succeeded":{"description":"Always true.","type":"boolean"}},"type":"object"},"example":{"succeeded":true}}}},"400":{"description":"The `message_ids` query parameter is missing or is not a single string. Nothing was populated.","content":{"application/json":{"schema":{"required":["succeeded","code","message"],"properties":{"succeeded":{"description":"Always false.","type":"boolean"},"code":{"description":"Machine-readable reason.","type":"string","enum":["invalid_message_ids"]},"message":{"description":"Always `Incorrect \"message_ids\"`.","type":"string"}},"type":"object"},"example":{"succeeded":false,"code":"invalid_message_ids","message":"Incorrect \"message_ids\""}}}},"409":{"description":"At least one message could not be populated: it belongs to no campaign, or building its content failed. The other messages were still processed; retry the call to complete the failed ones.","content":{"application/json":{"schema":{"required":["succeeded","code","message"],"properties":{"succeeded":{"description":"Always false.","type":"boolean"},"code":{"description":"Machine-readable reason.","type":"string","enum":["populate_failed"]},"message":{"description":"Always \"One or more messages could not be populated.\"","type":"string"}},"type":"object"},"example":{"succeeded":false,"code":"populate_failed","message":"One or more messages could not be populated."}}}}},"x-canonical-resource":"message","x-destructive":false,"x-bulk-operation":true,"x-internal":true}},"/message/source":{"get":{"summary":"Retrieve the source of a campaign message","description":"Render a campaign message and return the generated email. This is the v3 equivalent of the `source` and `structured` actions of the v1 `campaign_send` action.\n\nWith `structured=0` (the default) the rendered message is returned as one raw MIME string in `result`. With `structured=1` the message is parsed and its headers, parts and attachments are returned as separate members alongside the raw source.\n\nRendering personalizes the message for `email`; the default address `_t.e.s.t_@example.com` renders the message without a contact. No email is delivered by this endpoint.\n\nThe account must have the Campaigns module enabled, otherwise the request answers `403`. ","operationId":"retrieve-a-campaign-message-source","x-canonical-resource":"message","parameters":[{"name":"campaignId","in":"query","required":true,"description":"ID of the campaign the message belongs to.","schema":{"type":"integer","format":"int32"}},{"name":"messageId","in":"query","required":true,"description":"ID of the message to render. Use the message id of the campaign, or `0` for a non-split campaign.","schema":{"type":"integer","format":"int32"}},{"name":"email","in":"query","description":"Address the message is personalized for. Must be a valid email address; an invalid value answers `400`.","schema":{"type":"string","default":"_t.e.s.t_@example.com"}},{"name":"type","in":"query","description":"Which part of a MIME message to render. Any other value answers `400`.","schema":{"type":"string","enum":["html","text","mime"],"default":"mime"}},{"name":"structured","in":"query","description":"Set to `1` to receive the parsed representation instead of the raw MIME source.","schema":{"type":"integer","format":"int32","enum":[0,1],"default":0}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"result\": \"Content-Type: multipart/alternative; boundary=\\\"_=_swift_1234_=_\\\"\\nSubject: Welcome!\\nFrom: Sender <sender@example.com>\\nTo: contact@example.com\\n\\n--_=_swift_1234_=_\\n...\",\n    \"succeeded\": 1,\n    \"message\": \"Message sent\"\n}"}},"schema":{"type":"object","properties":{"result":{"type":"string","description":"The raw MIME source when `structured=0`. When `structured=1` this member is absent and the parsed members below are returned instead."},"subject":{"type":"string","description":"Rendered subject. Only with `structured=1`."},"ctype":{"type":"string","description":"Message content type. Only with `structured=1`."},"from":{"type":"string","description":"Rendered `From` header. Only with `structured=1`."},"from_name":{"type":"string","description":"Only with `structured=1`."},"from_email":{"type":"string","description":"Only with `structured=1`."},"to":{"type":"string","description":"Rendered `To` header. Only with `structured=1`."},"to_name":{"type":"string","description":"Only with `structured=1`."},"to_email":{"type":"string","description":"Only with `structured=1`."},"parts":{"type":"object","description":"Rendered `text` and `html` bodies with their character sets. Only with `structured=1`."},"attachments":{"type":"array","description":"Attachments of the message, each with a `hash` and a `link`. Only with `structured=1`."},"source":{"type":"string","description":"The raw MIME source. Only with `structured=1`."},"succeeded":{"type":"integer","format":"int32","example":1},"message":{"type":"string","example":"Message sent","description":"Always `Message sent` when the message rendered. This endpoint renders the message and does not deliver any email."}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Email address is not valid.\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32","example":0},"message":{"type":"string","example":"Email address is not valid."}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 0,\n    \"message\": \"Please upgrade your account to enable the Campaign module and access campaigns\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32","example":0},"message":{"type":"string"}}}}}}},"deprecated":false}},"/message/sources":{"get":{"summary":"Retrieve the sources of a campaign's messages for a spam check","description":"Renders each message of a campaign as the raw MIME email it would send, addressed to the sample test address, so the content can be run through a spam check. No email is delivered. GET /message/source renders one message for a chosen address.\n\nWhen rendering a message fails it is left out of `result`. When the campaign's RSS feed cannot be fetched, `src` carries a sentence saying so, followed by the feed URL, instead of a source.","operationId":"retrieve-campaign-message-sources-for-spam-check","x-canonical-resource":"message","parameters":[{"name":"campaignId","in":"query","description":"ID of the campaign.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"messageId","in":"query","description":"Only render this message of the campaign. Omit it, or send `0`, to render every message of the campaign.","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The rendered sources.","content":{"application/json":{"schema":{"type":"object","required":["result","succeeded","message"],"properties":{"result":{"type":"array","description":"One entry per rendered message.","items":{"type":"object","required":["mid","src"],"properties":{"mid":{"type":"integer","description":"ID of the message.","example":12},"src":{"type":"string","description":"The raw MIME source of the message.","example":"Content-Type: multipart/alternative; boundary=\"_=_swift_1234_=_\"\nSubject: Welcome!\n..."}}}},"succeeded":{"type":"integer","description":"Always 1.","example":1},"message":{"type":"string","description":"Always \"Sources Fetched Successfully.\"","example":"Sources Fetched Successfully."}}}}}},"400":{"description":"The `campaignId` query parameter is missing. The body is the plain text `CampaignId is a required query parameter.`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"The campaign has no message, or `messageId` is not one of its messages. The body is the plain text `Message not found`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}},"405":{"description":"The request used a method other than GET. The body is the plain text `Method not supported. Only GET supported.`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The sources could not be read, for example because `campaignId` is not a number. The body is the plain text `Error trying to fetch sources` or `Error connecting to database`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/message/split_copy":{"put":{"summary":"Copy a message into a split campaign","description":"Adds a copy of a message to a split (A/B) campaign as a new message: content, designer layout and settings are copied, a preview screenshot is requested, the links of the new message are tracked, and the link actions of the source message are copied to it. The campaign must be a split campaign with fewer than 5 messages. With an even split, every message of the campaign is given an equal share of the sends again.\n\nThe ids are read from the query string; the request takes no body. Any method other than PUT answers 405.","operationId":"copy-a-split-campaign-message","x-canonical-resource":"message","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"message_id","in":"query","description":"ID of the message to copy.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"campaign_id","in":"query","description":"ID of the split campaign the copy is added to.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"201":{"description":"The copy was created.","content":{"application/json":{"schema":{"type":"object","description":"The new message as stored, every column of the message record. Numbers are returned as strings.","properties":{"id":{"type":"string","description":"ID of the new message.","example":"57"},"userid":{"type":"string","description":"ID of the user who owns the message.","example":"1"},"ed_instanceid":{"type":"string","description":"ID of the legacy designer layout of the new message, a copy of the source message's; 0 when it has none.","example":"0"},"ed_version":{"type":"string","description":"Version of the email designer the message was built with.","example":"3"},"cdate":{"type":"string","description":"Creation date as stored, Y-m-d H:i:s.","example":"2026-01-10 09:00:00"},"mdate":{"type":"string","description":"Last change date as stored, Y-m-d H:i:s.","example":"2026-01-12 15:30:00"},"name":{"type":"string","description":"Name of the message.","example":""},"fromname":{"type":"string","description":"Name of the sender.","example":"Example Store"},"fromemail":{"type":"string","description":"Email address of the sender.","example":"news@example.com"},"reply2":{"type":"string","description":"Address replies go to.","example":"support@example.com"},"priority":{"type":"string","description":"X-Priority header value.","example":"3"},"charset":{"type":"string","description":"Character set.","example":"utf-8"},"encoding":{"type":"string","description":"Content-Transfer-Encoding.","example":"8bit"},"format":{"type":"string","description":"html, text or mime.","example":"mime"},"subject":{"type":"string","description":"Subject line.","example":"Our spring sale"},"preheader_text":{"type":"string","description":"Preheader text.","example":""},"text":{"type":"string","description":"Text content.","example":"Spring sale"},"html":{"type":"string","description":"HTML content.","example":"<html><body>Spring sale</body></html>"},"htmlfetch":{"type":"string","description":"When fetched HTML content is fetched.","example":"now"},"textfetch":{"type":"string","description":"When fetched text content is fetched.","example":"now"},"hidden":{"type":"string","description":"1 when the message is hidden from the message list, otherwise 0.","example":"0"},"preview_mime":{"type":"string","description":"MIME type of the stored preview image.","example":""},"has_predictive_content":{"type":"string","description":"1 when the message uses predictive content, otherwise 0.","example":"0"},"language_code":{"type":["string","null"],"description":"Code of the language the message was translated into; null for an original."},"source":{"type":"string","description":"The `source` column of the message record, copied from the source message; empty by default.","example":""},"preview_data":{"type":["string","null"],"description":"Stored preview image data, usually null."},"percentage":{"type":["number","string"],"description":"Share of the split campaign's sends the new message gets. With an even split every message of the campaign is reset to this share; otherwise it is the source message's share in this campaign.","example":33.333333333333}}}}}},"400":{"description":"Nothing was copied. The body is plain text, not JSON: `campaign id is required`, `message id is required`, or `unable to copy message` when the message does not exist, the campaign is not a split campaign, the campaign already has 5 messages or the copy could not be saved.","content":{"text/plain":{"schema":{"type":"string"}}}},"405":{"description":"The request used a method other than PUT. The body is the plain text `Method not supported. Only PUT supported.`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/message/split_delete":{"delete":{"summary":"Delete a message from a split campaign","description":"Removes a message from a campaign and deletes it: the message, its stored designer markup, its tracked links in that campaign, its files, and its legacy designer layout when no other campaign message uses that layout. The last message of a campaign cannot be deleted.\n\nThe ids are read from the query string; the request takes no body. Any method other than DELETE answers 405.","operationId":"delete-a-split-campaign-message","x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"message_id","in":"query","description":"ID of the message to delete.","schema":{"type":"integer","format":"int32"},"required":true},{"name":"campaign_id","in":"query","description":"ID of the campaign the message belongs to.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The message was deleted. The body is empty."},"400":{"description":"The body is plain text, not JSON: `campaign id is required` or `message id is required`; `Unfortunately you can not delete the only message in a campaign. To delete this one, add a new one first.`; or `Message not found.` when the message is not part of the campaign, in which case nothing was deleted, or when its record no longer exists, in which case the message was already removed from the campaign. The last two sentences are in the language of the account.","content":{"text/plain":{"schema":{"type":"string"}}}},"405":{"description":"The request used a method other than DELETE. The body is the plain text `Method not supported. Only DELETE supported.`, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/message/{messageId}/rebuildDesigner":{"put":{"summary":"Rebuild a message from its designer layout","description":"Regenerates the HTML of a message from the layout saved by the legacy email designer (designer versions 1 and 2) and saves it. The text version is regenerated from that HTML too, unless the campaign manages its text separately. On a split campaign whose messages share their content, the rebuilt content is copied to the other messages of the campaign.\n\nA message with no designer layout, or built with a newer designer, is returned unchanged. The request takes no body.","operationId":"rebuild-a-message-from-designer","parameters":[{"name":"messageId","in":"path","description":"ID of the message to rebuild","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The message after the rebuild.","content":{"application/json":{"schema":{"required":["messageId","subject","fromName","fromEmail","replyToEmail","html"],"properties":{"messageId":{"description":"ID of the message.","type":"string","example":"12"},"subject":{"description":"Subject line.","type":"string","example":"Our spring sale"},"fromName":{"description":"Name of the sender.","type":"string","example":"Example Store"},"fromEmail":{"description":"Email address of the sender.","type":"string","example":"news@example.com"},"replyToEmail":{"description":"Address replies go to.","type":"string","example":"support@example.com"},"html":{"description":"HTML content of the message, as rebuilt.","type":"string","example":"<html><body>Spring sale</body></html>"}},"type":"object"}}}},"500":{"description":"No message with this ID: the case is not handled, so the request fails with a server error."}},"x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/messages":{"post":{"summary":"Create a message","description":"","operationId":"create-a-new-message","x-canonical-resource":"message","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"properties":{"fromname":{"type":"string","description":"Name of sender"},"fromemail":{"type":"string","description":"Email of sender"},"reply2":{"type":"string","description":"Reply email for the recipient to reply to"},"subject":{"type":"string","description":"Subject of message"},"preheader_text":{"type":"string","description":"Preheader Text"},"text":{"type":"string","description":"Text content"},"html":{"type":"string","description":"HTML Content"},"name":{"type":"string"},"format":{"type":"string","enum":["html","text","mime"]},"priority":{"oneOf":[{"type":"integer","enum":[1,3,5]},{"type":"string","enum":["1","3","5"]}],"description":"X-Priority header value: 1 high, 3 normal, 5 low."},"charset":{"type":"string"},"encoding":{"type":"string","enum":["7bit","8bit","binary","quoted-printable","base64"],"description":"Content-Transfer-Encoding of the message."},"htmlfetch":{"type":"string","enum":["now","send","cust"]},"textfetch":{"type":"string","enum":["now","send","cust"]}},"required":["fromname","fromemail","reply2"],"type":"object","additionalProperties":false}}},"examples":{"Request Example":{"value":{"message":{"fromname":"AC Admin","fromemail":"noreply@example.com","reply2":"hello@example.com","subject":"You are subscribing to %LISTNAME%","preheader_text":"Pre-header Text"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": {\n        \"fromname\": \"AC Admin\",\n        \"fromemail\": \"noreply@example.com\",\n        \"reply2\": \"hello@example.com\",\n        \"subject\": \"You are subscribing to %LISTNAME%\",\n        \"preheader_text\": \"Pre-header Text\",\n        \"text\": \"hello\",\n        \"html\": \"<div>hello</div>\",\n        \"links\": {\n            \"user\": \"https://yourAccountName.api-us1.com/api/3/messages/28/user\",\n            \"hyperlinks\": \"https://yourAccountName.api-us1.com/api/3/messages/28/hyperlinks\"\n        },\n        \"id\": \"28\"\n    }\n}"}},"schema":{"type":"object","properties":{"message":{"type":"object","properties":{"fromname":{"type":"string","example":"AC Admin"},"fromemail":{"type":"string","example":"noreply@example.com"},"reply2":{"type":"string","example":"hello@example.com"},"subject":{"type":"string","example":"You are subscribing to %LISTNAME%"},"preheader_text":{"type":"string","example":"Pre-header Text"},"text":{"type":"string","example":"hello"},"html":{"type":"string","example":"<div>hello</div>"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/messages/28/user"},"hyperlinks":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/messages/28/hyperlinks"}}},"id":{"type":"string","example":"28"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all messages","description":"","operationId":"list-all-messages","x-canonical-resource":"message","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"messages\": [\n        {\n            \"userid\": \"1\",\n            \"ed_instanceid\": \"0\",\n            \"ed_version\": \"1\",\n            \"cdate\": \"2018-08-17T09:47:38-05:00\",\n            \"mdate\": \"2018-08-17T09:47:38-05:00\",\n            \"name\": \"\",\n            \"fromname\": \"John Doe\",\n            \"fromemail\": \"noreply@example.com\",\n            \"reply2\": \"hello@example.com\",\n            \"priority\": \"3\",\n            \"charset\": \"utf-8\",\n            \"encoding\": \"quoted-printable\",\n            \"format\": \"mime\",\n            \"subject\": \"Update your subscription to %LISTNAME%\",\n            \"preheader_text\": \"\",\n            \"text\": \" \\n\\n**Update your subscription details for %LISTNAME%** \\n\\n \\n\\nYou or someone entering your email has requested to update your\\nsubscription details for the address %EMAIL%.\\n\\n**To update your subscription details click the link below.**\\n\\nUpdate My Subscription <%LINK%> \\n\\n \\n\\n{\\\"If you believe that this is a mistake and you did not intend on\\nupdating your subscription to this list, you can ignore this message and\\nnothing else will happen.\\\"|alang\\n\\n \",\n            \"html\": \"<!DOCTYPE html PUBLIC \\\"-//W3C//DTD XHTML 1.0 Transitional//EN\\\" \\\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\\">\\n<html lang=\\\"en\\\" style=\\\"margin: 0; outline: none; padding: 0;\\\">\\n<head>\\n    <!--[if !mso]><meta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"><!--<![endif]-->\\n    <meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\n    <meta http-equiv=\\\"Content-Language\\\" content=\\\"en-us\\\">\\n    <title>Preview</title>\\n    <style>\\n        .ExternalClass         .ExternalClass p,\\n        .ExternalClass ul,\\n        .ExternalClass ol         .undoreset div p,\\n        .undoreset p     </style>\\n    <style>\\n        @media only screen and (max-width: 600px),\\n        only screen and (max-device-width: 600px)             *             table             thead,\\n            tbody,\\n            tr             th,\\n            td,\\n            p         }\\n    </style>\\n</head>\\n<body style=\\\"font-family: Arial; line-height: 1.1; margin: 0px; background-color: #F2F2F2; width: 100%; text-align: center;\\\">\\n    <div class=\\\"divbody\\\" style=\\\"margin: 0px; outline: none; padding: 0px; font-family: arial; line-height: 1.1; width: 100%; background-color: #F2F2F2; background: #F2F2F2; text-align: center;\\\">\\n        <table border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"100%\\\" style=\\\"font-size: 16px;\\\">\\n            <tr>\\n                <td valign=\\\"top\\\" height=\\\"40\\\" align=\\\"center\\\">&nbsp;</td>\\n            </tr>\\n            <tr>\\n                <td align=\\\"center\\\" valign=\\\"top\\\" width=\\\"100%\\\">\\n                    <table border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"100%\\\" bgcolor=\\\"#F2F2F2\\\" style=\\\"font-size: 16px; min-width: 650px;\\\">\\n                        <tr>\\n                            <td valign=\\\"top\\\" align=\\\"center\\\">\\n                                <table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" border=\\\"0\\\" width=\\\"100%\\\" style=\\\"font-size: 16px;\\\">\\n                                    <tr>\\n                                        <td valign=\\\"top\\\" style=\\\"padding: 0;\\\">\\n                                            <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                                                <tr style=\\\"margin: 0; padding: 0;\\\">\\n                                                    <td valign=\\\"top\\\">\\n                                                        <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                                                            <tr>\\n                                                                <td valign=\\\"top\\\" align=\\\"center\\\" style=\\\"Margin:0; padding:0; font-size:20px; font-family:Arial,Helvetica; line-height:26px; text-align:center!important;\\\"><strong style=\\\"font-weight:bold;\\\">Update your subscription details for %LISTNAME%</strong>\\n                                                                </td>\\n                                                            </tr>\\n                                                        </table>\\n                                                    </td>\\n                                                </tr>\\n                                            </table>\\n                                        </td>\\n                                    </tr>\\n                                    <tr>\\n                                        <td height=\\\"20\\\">&nbsp;</td>\\n                                    </tr>\\n                                    <tr>\\n                                        <td valign=\\\"top\\\" style=\\\"padding: 0;\\\">\\n                                            <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                                                <tr style=\\\"margin: 0; padding: 0;\\\">\\n                                                    <td valign=\\\"top\\\">\\n                                                        <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                                                            <tr>\\n                                                                <td valign=\\\"top\\\" align=\\\"center\\\" width=\\\"610\\\" style=\\\"color: inherit; font-size: inherit; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\">You or someone entering your email has requested to update your subscription details for the address %EMAIL%.</td>\\n                                                            </tr>\\n                                                        </table>\\n                                                    </td>\\n                                                </tr>\\n                                            </table>\\n                                        </td>\\n                                    </tr>\\n                                    <tr>\\n                                        <td valign=\\\"top\\\" style=\\\"padding: 20px;\\\">\\n                                            <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; border-collapse: initial !important;\\\">\\n                                                <tr style=\\\"background-color: #ffffff;\\\">\\n                                                    <td valign=\\\"top\\\" style=\\\"border-color: #c2c2c2; border-style: solid; border-width: 1px;\\\">\\n                                                        <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px;\\\">\\n                                                            <tr>\\n                                                                <td valign=\\\"top\\\" align=\\\"center\\\" style=\\\"padding:20px; font-size:16px; font-family:Arial,Helvetica; text-align:center;\\\"><strong style=\\\"font-weight:bold;\\\">To update your subscription details click the link below.</strong></td> </tr> <tr> <td valign=\\\"top\\\" align=\\\"center\\\"> <table border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px;\\\"> <tr> <td valign=\\\"top\\\" align=\\\"left\\\" width=\\\"558\\\">\\n                                                                                <div class=\\\"button-wrapper\\\" style=\\\"margin: 0; outline: none; padding: 0; text-align: center;\\\">\\n                                                                                    <!--[if mso]> <v:roundrect xmlns:v=\\\"urn:schemas-microsoft-com:vml\\\" xmlns:w=\\\"urn:schemas-microsoft-com:office:word\\\" href=\\\"%LINK%\\\" style=\\\"v-text-anchor:middle; width: 558px; height: 50px;\\\" arcsize=\\\"10%\\\" strokecolor=\\\"#4DCBA9\\\" strokeweight=\\\"1pt\\\" fillcolor=\\\"#4DCBA9\\\" > <w:anchorlock/> <center style=\\\"color:#ffffff;font-family:'Arial'; font-size:16px;\\\">Update My Subscription</center> </v:roundrect> <![endif]-->\\n                                                                                    <a href=\\\"%LINK%\\\" style=\\\"margin: 0; outline: none; padding: 16px; background-color: #4DCBA9; border: 1px solid #4DCBA9; border-radius: 4px; color: #ffffff; font-family: Arial; font-size: 16px; display: inline-block; text-align: center; text-decoration: none; mso-hide: all;\\\"> <span style=\\\"color:#ffffff;\\\">Update My Subscription</span> </a>\\n                                                                                </div>\\n                                                                            </td>\\n    </tr>\\n    </table>\\n    </td>\\n    </tr>\\n    <tr>\\n        <td height=\\\"20\\\">&nbsp;</td>\\n    </tr>\\n    </table>\\n    </td>\\n    </tr>\\n    </table>\\n    </td>\\n    </tr>\\n    <tr>\\n        <td valign=\\\"top\\\" style=\\\"padding: 0;\\\">\\n            <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                <tr style=\\\"margin: 0; padding: 0;\\\">\\n                    <td valign=\\\"top\\\" style=\\\"padding: 20px;\\\">\\n                        <table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 14px;\\\">\\n                            <tr>\\n                                <td valign=\\\"top\\\" height=\\\"25\\\" align=\\\"center\\\" style=\\\"Margin:0; padding:0; font-size:13px; line-height:13px; font-family:Arial,Helvetica; text-align:center!important; line-height:20px; text-align:center!important;\\\">{\\\"If you believe that this is a mistake and you did not intend on updating your subscription to this list, you can ignore this message and nothing else will happen.\\\"|alang</td>\\n                            </tr>\\n                        </table>\\n                    </td>\\n                </tr>\\n            </table>\\n        </td>\\n    </tr>\\n    </table>\\n    </td>\\n    </tr>\\n    </table>\\n    </td>\\n    </tr>\\n    <tr>\\n        <td valign=\\\"top\\\" height=\\\"40\\\" align=\\\"center\\\">&nbsp;</td>\\n    </tr>\\n    </table>\\n    </div>\\n</body>\\n\\n</html>\",\n            \"htmlfetch\": \"now\",\n            \"textfetch\": \"now\",\n            \"hidden\": \"0\",\n            \"preview_mime\": \"\",\n            \"preview_data\": null,\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/messages/2/user\"\n            },\n            \"id\": \"2\",\n            \"user\": \"1\"\n        },\n        {\n            \"userid\": \"1\",\n            \"ed_instanceid\": \"1\",\n            \"ed_version\": \"2\",\n            \"cdate\": \"2018-08-17T13:47:32-05:00\",\n            \"mdate\": \"2018-08-17T13:47:32-05:00\",\n            \"name\": \"Please confirm your subscription to %LISTNAME%\",\n            \"fromname\": \"AC Admin\",\n            \"fromemail\": \"admin@example.com\",\n            \"reply2\": \"\",\n            \"priority\": \"3\",\n            \"charset\": \"utf-8\",\n            \"encoding\": \"8bit\",\n            \"format\": \"mime\",\n            \"subject\": \"Please confirm your subscription to %LISTNAME%\",\n            \"preheader_text\": \"\",\n            \"text\": \" \\n\\nThank you for subscribing to %LISTNAME%!\\n\\nYou or someone has subscribed to this list on %SUBDATE% using the\\naddress %EMAIL%.\\n\\nTo confirm that you wish to be subscribed, please click the link below:\\n\\nConfirm My Subscription <%CONFIRMLINK%> \\n\\nIf you believe that this is a mistake and you did not intend on\\nsubscribing to this list,\\nyou can ignore this message and nothing else will happen.\",\n            \"html\": \"<!DOCTYPE html PUBLIC \\\"-//W3C//DTD XHTML 1.0 Transitional//EN\\\" \\\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\\">\\n<html lang=\\\"en\\\" style=\\\"margin: 0; outline: none; padding: 0;\\\"><head><!--[if !mso]><meta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"><!--<![endif]--><meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\"><meta http-equiv=\\\"Content-Language\\\" content=\\\"locale_contentlang\\\"><meta name=\\\"format-detection\\\" content=\\\"telephone=no\\\"><meta name=\\\"format-detection\\\" content=\\\"date=no\\\"><meta name=\\\"format-detection\\\" content=\\\"address=no\\\"><meta name=\\\"format-detection\\\" content=\\\"email=no\\\"><title>Preview</title><style data-ac-keep=\\\"true\\\">\\n.ExternalClass {width:100%; background:inherit; background-color:inherit;}\\n.ExternalClass p, .ExternalClass ul, .ExternalClass ol { Margin: 0; }\\n.undoreset div p, .undoreset p { margin-bottom: 20px; }\\ndiv[class^=\\\"aolmail_divbody\\\"] { overflow: auto; }\\n[owa] #ac-footer { padding: 20px 0px!important; background:inherit; background-color:inherit; }\\n</style><style data-ac-keep=\\\"true\\\">\\n@media only screen and (max-width: 600px) {\\t/*-------------------------------------------------------------------------*\\\\ Abandoned Cart widget \\\\*------------------------------------------------------------------------*/ .td_abandoned-cart img {display: block;padding-right: 0 !important;padding-bottom: 0 !important;width: 100% !important;max-width: 100% !important;height: auto !important;} body { padding: 0!important; font-size:1em!important; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *[class].divbody {-webkit-text-size-adjust:none !important; width:auto !important;} *[class].td_picture img {width:auto !important;} *[class].td_text { line-height: 110%; } *[class].td_button { width: auto; } /* Collapse all block elements */ :not(.body) table { display: block!important; float:none!important; border-collapse:collapse !important; width:100% !important; min-width:100% !important; clear:both!important; } :not(.body) thead, :not(.body) tbody, :not(.body) tr { display:block!important; float:none!important; width:100% !important; } :not(.body) th, :not(.body) td, :not(.body) p { display:block!important; float:none!important; width:100% !important; clear:both!important; } /* Remove browser default styling for elements */ ul, ol { margin-left: 20px; margin-bottom: 10px; margin-top: 10px; -webkit-margin-before: 0; -webkit-margin-after: 0; -webkit-padding-start: 0; } /* Set default height for spacer once collapse */ *[class].spacer { height: auto!important; } a[href^=date]{ color:inherit !important; text-decoration:none !important;} a[href^=telephone]{ color:inherit !important; text-decoration:none !important;} a[href^=address]{ color:inherit !important; text-decoration:none !important;} a[href^=email]{ color:inherit !important; text-decoration:none !important;} /* Default table cell height */ td[height=\\\"10\\\"]{height:10px!important;font-size:10px!important;line-height:10px!important;}\\ntd[height=\\\"13\\\"]{height:13px!important;font-size:13px!important;line-height:13px!important;}\\ntd[height=\\\"14\\\"]{height:14px!important;font-size:14px!important;line-height:14px!important;}\\ntd[height=\\\"12\\\"]{height:12px!important;font-size:12px!important;line-height:12px!important;} /* Default social icons */ *[class].ac-social-icon-16 {width:16px !important; height:16px !important;} *[class].ac-social-icon-24 {width:24px !important; height:24px !important;} *[class].ac-social-icon-28 {width:28px !important; height:28px !important;} *[class].__ac_social_icons { margin-right: 0px !important; } }\\n</style><style data-ac-keep=\\\"true\\\"> </style><!--[if !mso]><!-- webfonts --><!--<![endif]--><!--[if lt mso 12]> <![endif]--></head><body id=\\\"ac-designer\\\" class=\\\"body\\\" style=\\\"font-family: Arial; line-height: 1.1; margin: 0px; background-color: #f5f5f5; width: 100%; text-align: center;\\\"><div class=\\\"divbody\\\" style=\\\"margin: 0px; outline: none; padding: 0px; color: #000000; font-family: arial; line-height: 1.1; width: 100%; background-color: #f5f5f5; background: #f5f5f5; text-align: center;\\\"><table class=\\\"template-table\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"100%\\\" align=\\\"left\\\" style=\\\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5; background: #f5f5f5;\\\"><tr><td align=\\\"center\\\" valign=\\\"top\\\" width=\\\"100%\\\"><table class=\\\"template-table\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"650\\\" bgcolor=\\\"#f5f5f5\\\" style=\\\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; max-width: 650px;\\\"><tr><td id=\\\"layout_table_4c01fd59953b175598dbdb0163afc56680171ae4\\\" valign=\\\"top\\\" align=\\\"center\\\" width=\\\"650\\\" style=\\\"background-color: #f5f5f5;\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" border=\\\"0\\\" class=\\\"layout layout-table root-table\\\" width=\\\"650\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5;\\\"><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin2\\\" valign=\\\"top\\\" style=\\\"background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr id=\\\"layout-row2\\\" class=\\\"layout layout-row widget _widget_spacer \\\"><td id=\\\"layout-row-padding2\\\" valign=\\\"top\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td valign=\\\"top\\\" height=\\\"30\\\"><div class=\\\"spacer\\\" style=\\\"margin: 0; outline: none; padding: 0; height: 30px;\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" border=\\\"0\\\" width=\\\"100%\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tbody><tr><td class=\\\"spacer-body\\\" valign=\\\"top\\\" height=\\\"30\\\" width=\\\"650\\\"> </td></tr></tbody></table></div></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin1\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row1\\\" class=\\\"layout layout-row widget _widget_text style1\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding1\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 20px 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div1\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 10px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: #000000; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">Thank you for subscribing to %LISTNAME%!</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin3\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row3\\\" class=\\\"layout layout-row widget _widget_text style3\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding3\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 20px 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div3\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: inherit; font-size: 13px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">You or someone has subscribed to this list on %SUBDATE% using the address %EMAIL%.</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin4\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 0 20px; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row4\\\" class=\\\"layout layout-row widget _widget_text style4\\\" style=\\\"margin: 0; padding: 0; background-color: #ffffff;\\\"><td id=\\\"layout-row-padding4\\\" valign=\\\"top\\\" style=\\\"background-color: #ffffff; padding: 30px 30px 20px 30px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div4\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span class=\\\"\\\" style=\\\"color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\">To confirm that you wish to be subscribed, please click the link below:</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin5\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 0 20px; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row5\\\" class=\\\"layout layout-row widget _widget_button style5\\\" style=\\\"background-color: #ffffff;\\\"><td id=\\\"layout-row-padding5\\\" valign=\\\"top\\\" style=\\\"background-color: #ffffff; padding: 0px 30px 30px 30px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td class=\\\"td_button td_block customizable\\\" valign=\\\"top\\\" align=\\\"left\\\" width=\\\"550\\\"> <div class=\\\"button-wrapper\\\" style=\\\"margin: 0; outline: none; padding: 0; text-align: center;\\\">\\n<!--[if mso]> <v:roundrect xmlns:v=\\\"urn:schemas-microsoft-com:vml\\\" xmlns:w=\\\"urn:schemas-microsoft-com:office:word\\\" href=\\\"%CONFIRMLINK%\\\" style=\\\"v-text-anchor:middle; width:202px; height:64px; \\\" arcsize=\\\"10%\\\" strokecolor=\\\"#4dcba9\\\" strokeweight=\\\"1pt\\\" fillcolor=\\\"#4dcba9\\\" o:button=\\\"true\\\" o:allowincell=\\\"true\\\" o:allowoverlap=\\\"false\\\" > <v:textbox inset=\\\"2px,2px,2px,2px\\\"> <center style=\\\"color:#ffffff;font-family:Arial; font-size:14px; line-height: 1.1;\\\">Confirm My Subscription</center> </v:textbox> </v:roundrect>\\n<![endif]--> <a href=\\\"%CONFIRMLINK%\\\" style=\\\"margin: 0; outline: none; padding: 14px; color: #ffffff; background-color: #4dcba9; border: 1px solid #4dcba9; border-radius: 4px; font-family: Arial; font-size: 14px; display: inline-block; line-height: 1.1; text-align: center; text-decoration: none; mso-hide: all;\\\"> <span style=\\\"color:#ffffff;font-family:Arial;font-size:14px;\\\"> Confirm My Subscription </span> </a> </div>\\n</td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin6\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row6\\\" class=\\\"layout layout-row widget _widget_text style6\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding6\\\" valign=\\\"top\\\" style=\\\"padding: 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div6\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">If you believe that this is a mistake and you did not intend on subscribing to this list,<br>you can ignore this message and nothing else will happen.</span></p></td></tr></table></td></tr></table></td></tr></table></td></tr></table></td></tr></table></div></body></html>\\n\",\n            \"htmlfetch\": \"now\",\n            \"textfetch\": \"now\",\n            \"hidden\": \"0\",\n            \"preview_mime\": \"\",\n            \"preview_data\": \"\",\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/messages/3/user\"\n            },\n            \"id\": \"3\",\n            \"user\": \"1\"\n        },\n        {\n            \"userid\": \"1\",\n            \"ed_instanceid\": \"0\",\n            \"ed_version\": \"1\",\n            \"cdate\": \"2018-08-17T13:48:45-05:00\",\n            \"mdate\": \"2018-08-17T13:48:45-05:00\",\n            \"name\": \"testing\",\n            \"fromname\": \"John Doe\",\n            \"fromemail\": \"noreply@example.com\",\n            \"reply2\": \"\",\n            \"priority\": \"3\",\n            \"charset\": \"utf-8\",\n            \"encoding\": \"8bit\",\n            \"format\": \"mime\",\n            \"subject\": \"testing\",\n            \"preheader_text\": \"\",\n            \"text\": \"testing testing testing\",\n            \"html\": \"<br>\\ntesting testing testing\",\n            \"htmlfetch\": \"now\",\n            \"textfetch\": \"now\",\n            \"hidden\": \"0\",\n            \"preview_mime\": \"\",\n            \"preview_data\": null,\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/3/messages/4/user\"\n            },\n            \"id\": \"4\",\n            \"user\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"ed_instanceid":{"type":"string","example":"0"},"ed_version":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2018-08-17T09:47:38-05:00"},"mdate":{"type":"string","example":"2018-08-17T09:47:38-05:00"},"name":{"type":"string","example":""},"fromname":{"type":"string","example":"John Doe"},"fromemail":{"type":"string","example":"noreply@example.com"},"reply2":{"type":"string","example":"hello@example.com"},"priority":{"type":"string","example":"3"},"charset":{"type":"string","example":"utf-8"},"encoding":{"type":"string","example":"quoted-printable"},"format":{"type":"string","example":"mime"},"subject":{"type":"string","example":"Update your subscription to %LISTNAME%"},"preheader_text":{"type":"string","example":""},"text":{"type":"string","example":" \n\n**Update your subscription details for %LISTNAME%** \n\n \n\nYou or someone entering your email has requested to update your\nsubscription details for the address %EMAIL%.\n\n**To update your subscription details click the link below.**\n\nUpdate My Subscription <%LINK%> \n\n \n\n{\"If you believe that this is a mistake and you did not intend on\nupdating your subscription to this list, you can ignore this message and\nnothing else will happen.\"|alang\n\n "},"html":{"type":"string","example":"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html lang=\"en\" style=\"margin: 0; outline: none; padding: 0;\">\n<head>\n    <!--[if !mso]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><!--<![endif]-->\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <meta http-equiv=\"Content-Language\" content=\"en-us\">\n    <title>Preview</title>\n    <style>\n        .ExternalClass         .ExternalClass p,\n        .ExternalClass ul,\n        .ExternalClass ol         .undoreset div p,\n        .undoreset p     </style>\n    <style>\n        @media only screen and (max-width: 600px),\n        only screen and (max-device-width: 600px)             *             table             thead,\n            tbody,\n            tr             th,\n            td,\n            p         }\n    </style>\n</head>\n<body style=\"font-family: Arial; line-height: 1.1; margin: 0px; background-color: #F2F2F2; width: 100%; text-align: center;\">\n    <div class=\"divbody\" style=\"margin: 0px; outline: none; padding: 0px; font-family: arial; line-height: 1.1; width: 100%; background-color: #F2F2F2; background: #F2F2F2; text-align: center;\">\n        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"font-size: 16px;\">\n            <tr>\n                <td valign=\"top\" height=\"40\" align=\"center\">&nbsp;</td>\n            </tr>\n            <tr>\n                <td align=\"center\" valign=\"top\" width=\"100%\">\n                    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" bgcolor=\"#F2F2F2\" style=\"font-size: 16px; min-width: 650px;\">\n                        <tr>\n                            <td valign=\"top\" align=\"center\">\n                                <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"font-size: 16px;\">\n                                    <tr>\n                                        <td valign=\"top\" style=\"padding: 0;\">\n                                            <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                                                <tr style=\"margin: 0; padding: 0;\">\n                                                    <td valign=\"top\">\n                                                        <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                                                            <tr>\n                                                                <td valign=\"top\" align=\"center\" style=\"Margin:0; padding:0; font-size:20px; font-family:Arial,Helvetica; line-height:26px; text-align:center!important;\"><strong style=\"font-weight:bold;\">Update your subscription details for %LISTNAME%</strong>\n                                                                </td>\n                                                            </tr>\n                                                        </table>\n                                                    </td>\n                                                </tr>\n                                            </table>\n                                        </td>\n                                    </tr>\n                                    <tr>\n                                        <td height=\"20\">&nbsp;</td>\n                                    </tr>\n                                    <tr>\n                                        <td valign=\"top\" style=\"padding: 0;\">\n                                            <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                                                <tr style=\"margin: 0; padding: 0;\">\n                                                    <td valign=\"top\">\n                                                        <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                                                            <tr>\n                                                                <td valign=\"top\" align=\"center\" width=\"610\" style=\"color: inherit; font-size: inherit; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\">You or someone entering your email has requested to update your subscription details for the address %EMAIL%.</td>\n                                                            </tr>\n                                                        </table>\n                                                    </td>\n                                                </tr>\n                                            </table>\n                                        </td>\n                                    </tr>\n                                    <tr>\n                                        <td valign=\"top\" style=\"padding: 20px;\">\n                                            <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; border-collapse: initial !important;\">\n                                                <tr style=\"background-color: #ffffff;\">\n                                                    <td valign=\"top\" style=\"border-color: #c2c2c2; border-style: solid; border-width: 1px;\">\n                                                        <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px;\">\n                                                            <tr>\n                                                                <td valign=\"top\" align=\"center\" style=\"padding:20px; font-size:16px; font-family:Arial,Helvetica; text-align:center;\"><strong style=\"font-weight:bold;\">To update your subscription details click the link below.</strong></td> </tr> <tr> <td valign=\"top\" align=\"center\"> <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px;\"> <tr> <td valign=\"top\" align=\"left\" width=\"558\">\n                                                                                <div class=\"button-wrapper\" style=\"margin: 0; outline: none; padding: 0; text-align: center;\">\n                                                                                    <!--[if mso]> <v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" href=\"%LINK%\" style=\"v-text-anchor:middle; width: 558px; height: 50px;\" arcsize=\"10%\" strokecolor=\"#4DCBA9\" strokeweight=\"1pt\" fillcolor=\"#4DCBA9\" > <w:anchorlock/> <center style=\"color:#ffffff;font-family:'Arial'; font-size:16px;\">Update My Subscription</center> </v:roundrect> <![endif]-->\n                                                                                    <a href=\"%LINK%\" style=\"margin: 0; outline: none; padding: 16px; background-color: #4DCBA9; border: 1px solid #4DCBA9; border-radius: 4px; color: #ffffff; font-family: Arial; font-size: 16px; display: inline-block; text-align: center; text-decoration: none; mso-hide: all;\"> <span style=\"color:#ffffff;\">Update My Subscription</span> </a>\n                                                                                </div>\n                                                                            </td>\n    </tr>\n    </table>\n    </td>\n    </tr>\n    <tr>\n        <td height=\"20\">&nbsp;</td>\n    </tr>\n    </table>\n    </td>\n    </tr>\n    </table>\n    </td>\n    </tr>\n    <tr>\n        <td valign=\"top\" style=\"padding: 0;\">\n            <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                <tr style=\"margin: 0; padding: 0;\">\n                    <td valign=\"top\" style=\"padding: 20px;\">\n                        <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 14px;\">\n                            <tr>\n                                <td valign=\"top\" height=\"25\" align=\"center\" style=\"Margin:0; padding:0; font-size:13px; line-height:13px; font-family:Arial,Helvetica; text-align:center!important; line-height:20px; text-align:center!important;\">{\"If you believe that this is a mistake and you did not intend on updating your subscription to this list, you can ignore this message and nothing else will happen.\"|alang</td>\n                            </tr>\n                        </table>\n                    </td>\n                </tr>\n            </table>\n        </td>\n    </tr>\n    </table>\n    </td>\n    </tr>\n    </table>\n    </td>\n    </tr>\n    <tr>\n        <td valign=\"top\" height=\"40\" align=\"center\">&nbsp;</td>\n    </tr>\n    </table>\n    </div>\n</body>\n\n</html>"},"htmlfetch":{"type":"string","example":"now"},"textfetch":{"type":"string","example":"now"},"hidden":{"type":"string","example":"0"},"preview_mime":{"type":"string","example":""},"preview_data":{},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/3/messages/2/user"}}},"id":{"type":"string","example":"2"},"user":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/messages/bulk_delete":{"delete":{"summary":"Delete multiple messages","description":"Deletes several email messages in one call. This is the bulk counterpart of DELETE /messages/{id} and the v3 equivalent of the v1 `message_delete_list` action.\n\nThe body selects what to delete, in one of two shapes:\n\n- `{\"ids\": [1, 2]}` deletes the given messages, at most 25 per call.\n- `{\"deleteFirst\": 5}` deletes the account's oldest messages that are not already hidden, lowest id first, from 1 to 10 of them.\n\n`ids` and `deleteFirst` are mutually exclusive. A message that a campaign uses is hidden instead of deleted, so the campaign keeps its history; a message no campaign uses is deleted together with its files. `deleted`, `hidden` and `failed` report the outcome per message id.\n\nThe account must have the Campaigns module, and the API user needs the permission to delete campaigns, which also governs deleting messages.","operationId":"bulk-delete-messages","requestBody":{"description":"Which messages to delete: an explicit `ids` list or the `deleteFirst` oldest ones.","required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"By id","description":"Delete the listed messages.","required":["ids"],"properties":{"ids":{"description":"Ids of the messages to delete. Positive integers; numeric strings are accepted and duplicates are ignored.","type":"array","items":{"oneOf":[{"type":"integer","minimum":1},{"type":"string","pattern":"^0*[1-9][0-9]*$"}]},"maxItems":25,"minItems":1},"deleteFirst":{"description":"Not allowed together with `ids`; a body with both keys is rejected with 400. It is listed here so that such a body matches both shapes and fails the `oneOf` check.","type":"integer"}},"type":"object"},{"title":"Oldest messages","description":"Delete the oldest messages of the account that are not already hidden.","required":["deleteFirst"],"properties":{"deleteFirst":{"description":"How many of the oldest messages to delete. An integer from 1 to 10; a numeric string is accepted.","oneOf":[{"type":"integer","maximum":10,"minimum":1},{"type":"string","pattern":"^0*([1-9]|10)$"}]},"ids":{"description":"Not allowed together with `deleteFirst`; a body with both keys is rejected with 400. It is listed here so that such a body matches both shapes and fails the `oneOf` check.","type":"array","items":{"type":"integer"}}},"type":"object"}]},"examples":{"By id":{"summary":"Delete two messages","value":{"ids":[12,13]}},"Oldest messages":{"summary":"Delete the five oldest messages","value":{"deleteFirst":5}}}}}},"responses":{"200":{"description":"The request was processed. `deleted` and `hidden` list the messages removed from view; `failed` lists requested ids that do not exist. With `deleteFirst`, a message gone since the ids were collected is skipped silently, and an account with nothing to delete answers 200 with empty lists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageBulkDeleteResult"},"example":{"succeeded":1,"message":"Email Message deleted","deleted":[12],"hidden":[13],"failed":[{"id":14,"reason":"Message not found."}]}}}},"400":{"description":"The body is not valid and nothing was deleted. `message` is one of:\n\n- Bad request. Body must be an object with \"ids\" or \"deleteFirst\".\n- Bad request. \"ids\" and \"deleteFirst\" are mutually exclusive.\n- Bad request. Message ids must be non-empty.\n- Bad request. No more than 25 message ids may be given.\n- Bad request. Message ids must be positive integers.\n- Bad request. \"deleteFirst\" must be an integer between 1 and 10.","content":{"application/json":{"schema":{"required":["succeeded","message"],"properties":{"succeeded":{"description":"Always 0.","type":"integer"},"message":{"description":"Which rule the body broke.","type":"string"}},"type":"object"},"example":{"succeeded":0,"message":"Bad request. \"ids\" and \"deleteFirst\" are mutually exclusive."}}}},"403":{"description":"Nothing was deleted. Either the account does not have the Campaigns module (`message` asks to upgrade the account, and only `succeeded` and `message` are returned), or the API user may not delete campaigns (`deleted`, `hidden` and `failed` are returned empty).","content":{"application/json":{"schema":{"required":["succeeded","message"],"properties":{"succeeded":{"description":"Always 0.","type":"integer"},"message":{"description":"Why the request was refused, in the language of the account.","type":"string"},"deleted":{"description":"Empty. Only present when the permission is missing.","type":"array","items":{"type":"integer"}},"hidden":{"description":"Empty. Only present when the permission is missing.","type":"array","items":{"type":"integer"}},"failed":{"description":"Empty. Only present when the permission is missing.","type":"array","items":{"type":"object"}}},"type":"object"},"example":{"succeeded":0,"message":"You do not have a permission to delete campaigns","deleted":[],"hidden":[],"failed":[]}}}},"404":{"description":"None of the requested ids exists. Nothing was deleted; `message` is \"Message not found.\" and every id is listed in `failed` with that same reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageBulkDeleteResult"}}}}},"x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/messages/{id}":{"get":{"summary":"Retrieve a message","description":"","operationId":"retrieve-a-message","x-canonical-resource":"message","parameters":[{"name":"id","in":"path","description":"ID of the message to retrieve","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": {\n        \"userid\": \"1\",\n        \"ed_instanceid\": \"1\",\n        \"ed_version\": \"2\",\n        \"cdate\": \"2018-08-17T13:47:32-05:00\",\n        \"mdate\": \"2018-08-17T13:47:32-05:00\",\n        \"name\": \"Please confirm your subscription to %LISTNAME%\",\n        \"fromname\": \"John Doe\",\n        \"fromemail\": \"noreply@example.com\",\n        \"reply2\": \"\",\n        \"priority\": \"3\",\n        \"charset\": \"utf-8\",\n        \"encoding\": \"8bit\",\n        \"format\": \"mime\",\n        \"subject\": \"Please confirm your subscription to %LISTNAME%\",\n        \"preheader_text\": \"\",\n        \"text\": \" \\n\\nThank you for subscribing to %LISTNAME%!\\n\\nYou or someone has subscribed to this list on %SUBDATE% using the\\naddress %EMAIL%.\\n\\nTo confirm that you wish to be subscribed, please click the link below:\\n\\nConfirm My Subscription <%CONFIRMLINK%> \\n\\nIf you believe that this is a mistake and you did not intend on\\nsubscribing to this list,\\nyou can ignore this message and nothing else will happen.\",\n        \"html\": \"<!DOCTYPE html PUBLIC \\\"-//W3C//DTD XHTML 1.0 Transitional//EN\\\" \\\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\\">\\n<html lang=\\\"en\\\" style=\\\"margin: 0; outline: none; padding: 0;\\\"><head><!--[if !mso]><meta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"><!--<![endif]--><meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\"><meta http-equiv=\\\"Content-Language\\\" content=\\\"locale_contentlang\\\"><meta name=\\\"format-detection\\\" content=\\\"telephone=no\\\"><meta name=\\\"format-detection\\\" content=\\\"date=no\\\"><meta name=\\\"format-detection\\\" content=\\\"address=no\\\"><meta name=\\\"format-detection\\\" content=\\\"email=no\\\"><title>Preview</title><style data-ac-keep=\\\"true\\\">\\n.ExternalClass {width:100%; background:inherit; background-color:inherit;}\\n.ExternalClass p, .ExternalClass ul, .ExternalClass ol { Margin: 0; }\\n.undoreset div p, .undoreset p { margin-bottom: 20px; }\\ndiv[class^=\\\"aolmail_divbody\\\"] { overflow: auto; }\\n[owa] #ac-footer { padding: 20px 0px!important; background:inherit; background-color:inherit; }\\n</style><style data-ac-keep=\\\"true\\\">\\n@media only screen and (max-width: 600px) {\\t/*-------------------------------------------------------------------------*\\\\ Abandoned Cart widget \\\\*------------------------------------------------------------------------*/ .td_abandoned-cart img {display: block;padding-right: 0 !important;padding-bottom: 0 !important;width: 100% !important;max-width: 100% !important;height: auto !important;} body { padding: 0!important; font-size:1em!important; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *[class].divbody {-webkit-text-size-adjust:none !important; width:auto !important;} *[class].td_picture img {width:auto !important;} *[class].td_text { line-height: 110%; } *[class].td_button { width: auto; } /* Collapse all block elements */ :not(.body) table { display: block!important; float:none!important; border-collapse:collapse !important; width:100% !important; min-width:100% !important; clear:both!important; } :not(.body) thead, :not(.body) tbody, :not(.body) tr { display:block!important; float:none!important; width:100% !important; } :not(.body) th, :not(.body) td, :not(.body) p { display:block!important; float:none!important; width:100% !important; clear:both!important; } /* Remove browser default styling for elements */ ul, ol { margin-left: 20px; margin-bottom: 10px; margin-top: 10px; -webkit-margin-before: 0; -webkit-margin-after: 0; -webkit-padding-start: 0; } /* Set default height for spacer once collapse */ *[class].spacer { height: auto!important; } a[href^=date]{ color:inherit !important; text-decoration:none !important;} a[href^=telephone]{ color:inherit !important; text-decoration:none !important;} a[href^=address]{ color:inherit !important; text-decoration:none !important;} a[href^=email]{ color:inherit !important; text-decoration:none !important;} /* Default table cell height */ td[height=\\\"10\\\"]{height:10px!important;font-size:10px!important;line-height:10px!important;}\\ntd[height=\\\"13\\\"]{height:13px!important;font-size:13px!important;line-height:13px!important;}\\ntd[height=\\\"14\\\"]{height:14px!important;font-size:14px!important;line-height:14px!important;}\\ntd[height=\\\"12\\\"]{height:12px!important;font-size:12px!important;line-height:12px!important;} /* Default social icons */ *[class].ac-social-icon-16 {width:16px !important; height:16px !important;} *[class].ac-social-icon-24 {width:24px !important; height:24px !important;} *[class].ac-social-icon-28 {width:28px !important; height:28px !important;} *[class].__ac_social_icons { margin-right: 0px !important; } }\\n</style><style data-ac-keep=\\\"true\\\"> </style><!--[if !mso]><!-- webfonts --><!--<![endif]--><!--[if lt mso 12]> <![endif]--></head><body id=\\\"ac-designer\\\" class=\\\"body\\\" style=\\\"font-family: Arial; line-height: 1.1; margin: 0px; background-color: #f5f5f5; width: 100%; text-align: center;\\\"><div class=\\\"divbody\\\" style=\\\"margin: 0px; outline: none; padding: 0px; color: #000000; font-family: arial; line-height: 1.1; width: 100%; background-color: #f5f5f5; background: #f5f5f5; text-align: center;\\\"><table class=\\\"template-table\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"100%\\\" align=\\\"left\\\" style=\\\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5; background: #f5f5f5;\\\"><tr><td align=\\\"center\\\" valign=\\\"top\\\" width=\\\"100%\\\"><table class=\\\"template-table\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" width=\\\"650\\\" bgcolor=\\\"#f5f5f5\\\" style=\\\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; max-width: 650px;\\\"><tr><td id=\\\"layout_table_4c01fd59953b175598dbdb0163afc56680171ae4\\\" valign=\\\"top\\\" align=\\\"center\\\" width=\\\"650\\\" style=\\\"background-color: #f5f5f5;\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" border=\\\"0\\\" class=\\\"layout layout-table root-table\\\" width=\\\"650\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5;\\\"><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin2\\\" valign=\\\"top\\\" style=\\\"background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr id=\\\"layout-row2\\\" class=\\\"layout layout-row widget _widget_spacer \\\"><td id=\\\"layout-row-padding2\\\" valign=\\\"top\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td valign=\\\"top\\\" height=\\\"30\\\"><div class=\\\"spacer\\\" style=\\\"margin: 0; outline: none; padding: 0; height: 30px;\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" border=\\\"0\\\" width=\\\"100%\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tbody><tr><td class=\\\"spacer-body\\\" valign=\\\"top\\\" height=\\\"30\\\" width=\\\"650\\\"> </td></tr></tbody></table></div></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin1\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row1\\\" class=\\\"layout layout-row widget _widget_text style1\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding1\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 20px 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div1\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 10px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: #000000; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">Thank you for subscribing to %LISTNAME%!</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin3\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row3\\\" class=\\\"layout layout-row widget _widget_text style3\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding3\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 20px 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div3\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: inherit; font-size: 13px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">You or someone has subscribed to this list on %SUBDATE% using the address %EMAIL%.</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin4\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 0 20px; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row4\\\" class=\\\"layout layout-row widget _widget_text style4\\\" style=\\\"margin: 0; padding: 0; background-color: #ffffff;\\\"><td id=\\\"layout-row-padding4\\\" valign=\\\"top\\\" style=\\\"background-color: #ffffff; padding: 30px 30px 20px 30px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div4\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span class=\\\"\\\" style=\\\"color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\">To confirm that you wish to be subscribed, please click the link below:</span></p></td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin5\\\" valign=\\\"top\\\" style=\\\"padding: 0 20px 0 20px; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row5\\\" class=\\\"layout layout-row widget _widget_button style5\\\" style=\\\"background-color: #ffffff;\\\"><td id=\\\"layout-row-padding5\\\" valign=\\\"top\\\" style=\\\"background-color: #ffffff; padding: 0px 30px 30px 30px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td class=\\\"td_button td_block customizable\\\" valign=\\\"top\\\" align=\\\"left\\\" width=\\\"550\\\"> <div class=\\\"button-wrapper\\\" style=\\\"margin: 0; outline: none; padding: 0; text-align: center;\\\">\\n<!--[if mso]> <v:roundrect xmlns:v=\\\"urn:schemas-microsoft-com:vml\\\" xmlns:w=\\\"urn:schemas-microsoft-com:office:word\\\" href=\\\"%CONFIRMLINK%\\\" style=\\\"v-text-anchor:middle; width:202px; height:64px; \\\" arcsize=\\\"10%\\\" strokecolor=\\\"#4dcba9\\\" strokeweight=\\\"1pt\\\" fillcolor=\\\"#4dcba9\\\" o:button=\\\"true\\\" o:allowincell=\\\"true\\\" o:allowoverlap=\\\"false\\\" > <v:textbox inset=\\\"2px,2px,2px,2px\\\"> <center style=\\\"color:#ffffff;font-family:Arial; font-size:14px; line-height: 1.1;\\\">Confirm My Subscription</center> </v:textbox> </v:roundrect>\\n<![endif]--> <a href=\\\"%CONFIRMLINK%\\\" style=\\\"margin: 0; outline: none; padding: 14px; color: #ffffff; background-color: #4dcba9; border: 1px solid #4dcba9; border-radius: 4px; font-family: Arial; font-size: 14px; display: inline-block; line-height: 1.1; text-align: center; text-decoration: none; mso-hide: all;\\\"> <span style=\\\"color:#ffffff;font-family:Arial;font-size:14px;\\\"> Confirm My Subscription </span> </a> </div>\\n</td></tr></table></td></tr></table></td></tr><tr style=\\\"background-color: #f5f5f5;\\\"><td id=\\\"layout-row-margin6\\\" valign=\\\"top\\\" style=\\\"padding: 0; background-color: #f5f5f5;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\\\"><tr id=\\\"layout-row6\\\" class=\\\"layout layout-row widget _widget_text style6\\\" style=\\\"margin: 0; padding: 0;\\\"><td id=\\\"layout-row-padding6\\\" valign=\\\"top\\\" style=\\\"padding: 20px;\\\"><table width=\\\"100%\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\\\"><tr><td id=\\\"text_div6\\\" class=\\\"td_text td_block\\\" valign=\\\"top\\\" align=\\\"left\\\" style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\\\"> <span class=\\\"\\\" style=\\\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\"> </span><p style=\\\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\\\"><span style=\\\"color: inherit; font-size: 12px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\\\" class=\\\"\\\">If you believe that this is a mistake and you did not intend on subscribing to this list,<br>you can ignore this message and nothing else will happen.</span></p></td></tr></table></td></tr></table></td></tr></table></td></tr></table></td></tr></table></div></body></html>\\n\",\n        \"htmlfetch\": \"now\",\n        \"textfetch\": \"now\",\n        \"hidden\": \"0\",\n        \"preview_mime\": \"\",\n        \"preview_data\": \"\",\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/3/messages/3/user\"\n        },\n        \"id\": \"3\",\n        \"user\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"message":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"ed_instanceid":{"type":"string","example":"1"},"ed_version":{"type":"string","example":"2"},"cdate":{"type":"string","example":"2018-08-17T13:47:32-05:00"},"mdate":{"type":"string","example":"2018-08-17T13:47:32-05:00"},"name":{"type":"string","example":"Please confirm your subscription to %LISTNAME%"},"fromname":{"type":"string","example":"John Doe"},"fromemail":{"type":"string","example":"noreply@example.com"},"reply2":{"type":"string","example":""},"priority":{"type":"string","example":"3"},"charset":{"type":"string","example":"utf-8"},"encoding":{"type":"string","example":"8bit"},"format":{"type":"string","example":"mime"},"subject":{"type":"string","example":"Please confirm your subscription to %LISTNAME%"},"preheader_text":{"type":"string","example":""},"text":{"type":"string","example":" \n\nThank you for subscribing to %LISTNAME%!\n\nYou or someone has subscribed to this list on %SUBDATE% using the\naddress %EMAIL%.\n\nTo confirm that you wish to be subscribed, please click the link below:\n\nConfirm My Subscription <%CONFIRMLINK%> \n\nIf you believe that this is a mistake and you did not intend on\nsubscribing to this list,\nyou can ignore this message and nothing else will happen."},"html":{"type":"string","example":"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html lang=\"en\" style=\"margin: 0; outline: none; padding: 0;\"><head><!--[if !mso]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><!--<![endif]--><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><meta http-equiv=\"Content-Language\" content=\"locale_contentlang\"><meta name=\"format-detection\" content=\"telephone=no\"><meta name=\"format-detection\" content=\"date=no\"><meta name=\"format-detection\" content=\"address=no\"><meta name=\"format-detection\" content=\"email=no\"><title>Preview</title><style data-ac-keep=\"true\">\n.ExternalClass {width:100%; background:inherit; background-color:inherit;}\n.ExternalClass p, .ExternalClass ul, .ExternalClass ol { Margin: 0; }\n.undoreset div p, .undoreset p { margin-bottom: 20px; }\ndiv[class^=\"aolmail_divbody\"] { overflow: auto; }\n[owa] #ac-footer { padding: 20px 0px!important; background:inherit; background-color:inherit; }\n</style><style data-ac-keep=\"true\">\n@media only screen and (max-width: 600px) {\t/*-------------------------------------------------------------------------*\\ Abandoned Cart widget \\*------------------------------------------------------------------------*/ .td_abandoned-cart img {display: block;padding-right: 0 !important;padding-bottom: 0 !important;width: 100% !important;max-width: 100% !important;height: auto !important;} body { padding: 0!important; font-size:1em!important; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *[class].divbody {-webkit-text-size-adjust:none !important; width:auto !important;} *[class].td_picture img {width:auto !important;} *[class].td_text { line-height: 110%; } *[class].td_button { width: auto; } /* Collapse all block elements */ :not(.body) table { display: block!important; float:none!important; border-collapse:collapse !important; width:100% !important; min-width:100% !important; clear:both!important; } :not(.body) thead, :not(.body) tbody, :not(.body) tr { display:block!important; float:none!important; width:100% !important; } :not(.body) th, :not(.body) td, :not(.body) p { display:block!important; float:none!important; width:100% !important; clear:both!important; } /* Remove browser default styling for elements */ ul, ol { margin-left: 20px; margin-bottom: 10px; margin-top: 10px; -webkit-margin-before: 0; -webkit-margin-after: 0; -webkit-padding-start: 0; } /* Set default height for spacer once collapse */ *[class].spacer { height: auto!important; } a[href^=date]{ color:inherit !important; text-decoration:none !important;} a[href^=telephone]{ color:inherit !important; text-decoration:none !important;} a[href^=address]{ color:inherit !important; text-decoration:none !important;} a[href^=email]{ color:inherit !important; text-decoration:none !important;} /* Default table cell height */ td[height=\"10\"]{height:10px!important;font-size:10px!important;line-height:10px!important;}\ntd[height=\"13\"]{height:13px!important;font-size:13px!important;line-height:13px!important;}\ntd[height=\"14\"]{height:14px!important;font-size:14px!important;line-height:14px!important;}\ntd[height=\"12\"]{height:12px!important;font-size:12px!important;line-height:12px!important;} /* Default social icons */ *[class].ac-social-icon-16 {width:16px !important; height:16px !important;} *[class].ac-social-icon-24 {width:24px !important; height:24px !important;} *[class].ac-social-icon-28 {width:28px !important; height:28px !important;} *[class].__ac_social_icons { margin-right: 0px !important; } }\n</style><style data-ac-keep=\"true\"> </style><!--[if !mso]><!-- webfonts --><!--<![endif]--><!--[if lt mso 12]> <![endif]--></head><body id=\"ac-designer\" class=\"body\" style=\"font-family: Arial; line-height: 1.1; margin: 0px; background-color: #f5f5f5; width: 100%; text-align: center;\"><div class=\"divbody\" style=\"margin: 0px; outline: none; padding: 0px; color: #000000; font-family: arial; line-height: 1.1; width: 100%; background-color: #f5f5f5; background: #f5f5f5; text-align: center;\"><table class=\"template-table\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" align=\"left\" style=\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5; background: #f5f5f5;\"><tr><td align=\"center\" valign=\"top\" width=\"100%\"><table class=\"template-table\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"650\" bgcolor=\"#f5f5f5\" style=\"font-size: 13px; min-width: auto; mso-table-lspace: 0pt; mso-table-rspace: 0pt; max-width: 650px;\"><tr><td id=\"layout_table_4c01fd59953b175598dbdb0163afc56680171ae4\" valign=\"top\" align=\"center\" width=\"650\" style=\"background-color: #f5f5f5;\"><table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"layout layout-table root-table\" width=\"650\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5;\"><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin2\" valign=\"top\" style=\"background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr id=\"layout-row2\" class=\"layout layout-row widget _widget_spacer \"><td id=\"layout-row-padding2\" valign=\"top\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td valign=\"top\" height=\"30\"><div class=\"spacer\" style=\"margin: 0; outline: none; padding: 0; height: 30px;\"><table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tbody><tr><td class=\"spacer-body\" valign=\"top\" height=\"30\" width=\"650\"> </td></tr></tbody></table></div></td></tr></table></td></tr></table></td></tr><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin1\" valign=\"top\" style=\"padding: 0; background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\"><tr id=\"layout-row1\" class=\"layout layout-row widget _widget_text style1\" style=\"margin: 0; padding: 0;\"><td id=\"layout-row-padding1\" valign=\"top\" style=\"padding: 0 20px 20px 20px;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td id=\"text_div1\" class=\"td_text td_block\" valign=\"top\" align=\"left\" style=\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\"> <span class=\"\" style=\"color: inherit; font-size: 10px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\"> </span><p style=\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\"><span style=\"color: #000000; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\" class=\"\">Thank you for subscribing to %LISTNAME%!</span></p></td></tr></table></td></tr></table></td></tr><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin3\" valign=\"top\" style=\"padding: 0; background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\"><tr id=\"layout-row3\" class=\"layout layout-row widget _widget_text style3\" style=\"margin: 0; padding: 0;\"><td id=\"layout-row-padding3\" valign=\"top\" style=\"padding: 0 20px 20px 20px;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td id=\"text_div3\" class=\"td_text td_block\" valign=\"top\" align=\"left\" style=\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\"> <span class=\"\" style=\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\"> </span><p style=\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\"><span style=\"color: inherit; font-size: 13px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\" class=\"\">You or someone has subscribed to this list on %SUBDATE% using the address %EMAIL%.</span></p></td></tr></table></td></tr></table></td></tr><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin4\" valign=\"top\" style=\"padding: 0 20px 0 20px; background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\"><tr id=\"layout-row4\" class=\"layout layout-row widget _widget_text style4\" style=\"margin: 0; padding: 0; background-color: #ffffff;\"><td id=\"layout-row-padding4\" valign=\"top\" style=\"background-color: #ffffff; padding: 30px 30px 20px 30px;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td id=\"text_div4\" class=\"td_text td_block\" valign=\"top\" align=\"left\" style=\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\"> <span class=\"\" style=\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\"> </span><p style=\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\"><span class=\"\" style=\"color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit;\">To confirm that you wish to be subscribed, please click the link below:</span></p></td></tr></table></td></tr></table></td></tr><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin5\" valign=\"top\" style=\"padding: 0 20px 0 20px; background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\"><tr id=\"layout-row5\" class=\"layout layout-row widget _widget_button style5\" style=\"background-color: #ffffff;\"><td id=\"layout-row-padding5\" valign=\"top\" style=\"background-color: #ffffff; padding: 0px 30px 30px 30px;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td class=\"td_button td_block customizable\" valign=\"top\" align=\"left\" width=\"550\"> <div class=\"button-wrapper\" style=\"margin: 0; outline: none; padding: 0; text-align: center;\">\n<!--[if mso]> <v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" href=\"%CONFIRMLINK%\" style=\"v-text-anchor:middle; width:202px; height:64px; \" arcsize=\"10%\" strokecolor=\"#4dcba9\" strokeweight=\"1pt\" fillcolor=\"#4dcba9\" o:button=\"true\" o:allowincell=\"true\" o:allowoverlap=\"false\" > <v:textbox inset=\"2px,2px,2px,2px\"> <center style=\"color:#ffffff;font-family:Arial; font-size:14px; line-height: 1.1;\">Confirm My Subscription</center> </v:textbox> </v:roundrect>\n<![endif]--> <a href=\"%CONFIRMLINK%\" style=\"margin: 0; outline: none; padding: 14px; color: #ffffff; background-color: #4dcba9; border: 1px solid #4dcba9; border-radius: 4px; font-family: Arial; font-size: 14px; display: inline-block; line-height: 1.1; text-align: center; text-decoration: none; mso-hide: all;\"> <span style=\"color:#ffffff;font-family:Arial;font-size:14px;\"> Confirm My Subscription </span> </a> </div>\n</td></tr></table></td></tr></table></td></tr><tr style=\"background-color: #f5f5f5;\"><td id=\"layout-row-margin6\" valign=\"top\" style=\"padding: 0; background-color: #f5f5f5;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: initial !important;\"><tr id=\"layout-row6\" class=\"layout layout-row widget _widget_text style6\" style=\"margin: 0; padding: 0;\"><td id=\"layout-row-padding6\" valign=\"top\" style=\"padding: 20px;\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-size: 13px; min-width: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;\"><tr><td id=\"text_div6\" class=\"td_text td_block\" valign=\"top\" align=\"left\" style=\"color: inherit; font-size: 12px; font-weight: inherit; line-height: 1; text-decoration: inherit; font-family: Arial;\"> <span class=\"\" style=\"color: inherit; font-size: 16px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\"> </span><p style=\"margin: 0; outline: none; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; text-decoration: inherit; text-align: center;\"><span style=\"color: inherit; font-size: 12px; font-weight: inherit; line-height: inherit; text-decoration: inherit;\" class=\"\">If you believe that this is a mistake and you did not intend on subscribing to this list,<br>you can ignore this message and nothing else will happen.</span></p></td></tr></table></td></tr></table></td></tr></table></td></tr></table></td></tr></table></div></body></html>\n"},"htmlfetch":{"type":"string","example":"now"},"textfetch":{"type":"string","example":"now"},"hidden":{"type":"string","example":"0"},"preview_mime":{"type":"string","example":""},"preview_data":{"type":"string","example":""},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/3/messages/3/user"}}},"id":{"type":"string","example":"3"},"user":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Message with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Message with id 10"}}}}}}},"deprecated":false},"put":{"summary":"Update a message","description":"","operationId":"update-a-message","x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the message to update","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"properties":{"fromname":{"type":"string","description":"Name of sender"},"fromemail":{"type":"string","description":"Email of sender"},"reply2":{"type":"string","description":"Reply email for the recipient to reply to"},"subject":{"type":"string","description":"Subject of message"},"preheader_text":{"type":"string","description":"Preheader Text"},"name":{"type":"string","description":"Name of the message"},"text":{"type":"string","description":"Text content"},"html":{"type":"string","description":"HTML Content"},"format":{"type":"string","enum":["html","text","mime"]},"priority":{"oneOf":[{"type":"integer","enum":[1,3,5]},{"type":"string","enum":["1","3","5"]}],"description":"X-Priority header value: 1 high, 3 normal, 5 low."},"charset":{"type":"string"},"encoding":{"type":"string","enum":["7bit","8bit","binary","quoted-printable","base64"],"description":"Content-Transfer-Encoding of the message."},"htmlfetch":{"type":"string","enum":["now","send","cust"]},"textfetch":{"type":"string","enum":["now","send","cust"]}},"required":[],"type":"object","additionalProperties":false}}},"examples":{"Request Example":{"value":{"message":{"fromname":"John Doe","fromemail":"noreply@example.com","reply2":"hello@example.com","subject":"You are subscribing to %LISTNAME%","preheader_text":"Pre-header Text"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": {\n        \"userid\": \"0\",\n        \"ed_instanceid\": \"0\",\n        \"ed_version\": \"1\",\n        \"cdate\": \"2024-08-06T16:31:45-05:00\",\n        \"mdate\": \"2024-08-06T16:33:23-05:00\",\n        \"name\": \"\",\n        \"fromname\": \"AC Admin\",\n        \"fromemail\": \"noreply@example.com\",\n        \"reply2\": \"hello@example.com\",\n        \"priority\": \"3\",\n        \"charset\": \"utf-8\",\n        \"encoding\": \"8bit\",\n        \"format\": \"mime\",\n        \"subject\": \"You are subscribing to %LISTNAME%\",\n        \"preheader_text\": \"Pre-header Text\",\n        \"text\": \"hello\",\n        \"html\": \"<div>hello</div>\",\n        \"htmlfetch\": \"now\",\n        \"textfetch\": \"now\",\n        \"hidden\": \"0\",\n        \"preview_mime\": \"\",\n        \"preview_data\": null,\n        \"has_predictive_content\": \"0\",\n        \"links\": {\n            \"user\": \"https://accountName.api-us1.com/api/3/messages/56/user\",\n            \"hyperlinks\": \"https://accountName.api-us1.com/api/3/messages/56/hyperlinks\"\n        },\n        \"id\": \"56\",\n        \"user\": null\n    }\n}"}},"schema":{"type":"object","properties":{"message":{"type":"object","properties":{"userid":{"type":"string","example":"0"},"ed_instanceid":{"type":"string","example":"0"},"ed_version":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2024-08-06T16:31:45-05:00"},"mdate":{"type":"string","example":"2024-08-06T16:33:23-05:00"},"name":{"type":"string","example":""},"fromname":{"type":"string","example":"AC Admin"},"fromemail":{"type":"string","example":"noreply@example.com"},"reply2":{"type":"string","example":"hello@example.com"},"priority":{"type":"string","example":"3"},"charset":{"type":"string","example":"utf-8"},"encoding":{"type":"string","example":"8bit"},"format":{"type":"string","example":"mime"},"subject":{"type":"string","example":"You are subscribing to %LISTNAME%"},"preheader_text":{"type":"string","example":"Pre-header Text"},"text":{"type":"string","example":"hello"},"html":{"type":"string","example":"<div>hello</div>"},"htmlfetch":{"type":"string","example":"now"},"textfetch":{"type":"string","example":"now"},"hidden":{"type":"string","example":"0"},"preview_mime":{"type":"string","example":""},"preview_data":{},"has_predictive_content":{"type":"string","example":"0"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://accountName.api-us1.com/api/3/messages/56/user"},"hyperlinks":{"type":"string","example":"https://accountName.api-us1.com/api/3/messages/56/hyperlinks"}}},"id":{"type":"string","example":"56"},"user":{}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Message with id 543\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Message with id 543"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a message","description":"","operationId":"delete-a-message","x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the message to delete","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"patch":{"summary":"Update a message (PATCH)","description":"Answered exactly as PUT /messages/{id}: the fields sent under `message` replace the stored values and every other field keeps its value. Fields of `message` that the request schema does not list are ignored.\n\nWhen the message belongs to a campaign, that campaign can no longer skip approval: an account whose campaigns are reviewed sends it through full approval again before it goes out.","operationId":"patch-a-message","parameters":[{"name":"id","in":"path","description":"ID of the message to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"description":"The fields to change.","properties":{"name":{"description":"Name of the message.","type":"string"},"subject":{"description":"Subject line.","type":"string"},"preheader_text":{"description":"Preheader text shown after the subject in the inbox.","type":"string"},"fromname":{"description":"Name of the sender.","type":"string"},"fromemail":{"description":"Email address of the sender.","type":"string"},"reply2":{"description":"Address replies go to.","type":"string"},"html":{"description":"HTML content. A value starting with `fetch:` must be followed by an http or https URL the content is fetched from; any other URL is rejected with 422.","type":"string"},"text":{"description":"Text content. Takes `fetch:` followed by a URL the same way as `html`.","type":"string"},"format":{"description":"Which parts the message is sent with: html only, text only, or both (mime).","type":"string","enum":["html","text","mime"]},"priority":{"description":"X-Priority header value: 1 (high), 3 (normal) or 5 (low). Sent as a number or a string.","oneOf":[{"type":"integer","enum":[1,3,5]},{"type":"string","enum":["1","3","5"]}]},"charset":{"description":"Character set the message is sent in, such as utf-8. A name the server cannot convert to is rejected with 422.","type":"string"},"encoding":{"description":"Content-Transfer-Encoding of the message.","type":"string","enum":["7bit","8bit","binary","quoted-printable","base64"]},"htmlfetch":{"description":"When fetched HTML content is fetched: now, once when sending starts, or per contact.","type":"string","enum":["now","send","cust"]},"textfetch":{"description":"When fetched text content is fetched: now, once when sending starts, or per contact.","type":"string","enum":["now","send","cust"]}},"type":"object"}},"type":"object"},"example":{"message":{"subject":"You are subscribing to %LISTNAME%","preheader_text":"Pre-header Text"}}}}},"responses":{"200":{"description":"The updated message, in the shape GET /messages/{id} returns.","content":{"application/json":{"schema":{"properties":{"message":{"description":"The message after the update. Numbers are returned as strings.","properties":{"id":{"description":"ID of the message.","type":"string","example":"56"},"userid":{"description":"ID of the user who owns the message.","type":"string","example":"1"},"ed_instanceid":{"description":"ID of the legacy designer layout the message is built from; 0 when it has none.","type":"string","example":"0"},"ed_version":{"description":"Version of the email designer the message was built with.","type":"string","example":"1"},"cdate":{"description":"When the message was created, with UTC offset.","type":"string","example":"2024-08-06T16:31:45-05:00"},"mdate":{"description":"When the message was last changed, with UTC offset.","type":"string","example":"2024-08-06T16:33:23-05:00"},"name":{"description":"Name of the message.","type":"string","example":""},"fromname":{"description":"Name of the sender.","type":"string","example":"AC Admin"},"fromemail":{"description":"Email address of the sender.","type":"string","example":"noreply@example.com"},"reply2":{"description":"Address replies go to.","type":"string","example":"hello@example.com"},"priority":{"description":"X-Priority header value.","type":"string","example":"3"},"charset":{"description":"Character set.","type":"string","example":"utf-8"},"encoding":{"description":"Content-Transfer-Encoding.","type":"string","example":"8bit"},"format":{"description":"html, text or mime.","type":"string","example":"mime"},"subject":{"description":"Subject line.","type":"string","example":"You are subscribing to %LISTNAME%"},"preheader_text":{"description":"Preheader text.","type":"string","example":"Pre-header Text"},"text":{"description":"Text content.","type":"string","example":"hello"},"html":{"description":"HTML content.","type":"string","example":"<div>hello</div>"},"htmlfetch":{"description":"When fetched HTML content is fetched.","type":"string","example":"now"},"textfetch":{"description":"When fetched text content is fetched.","type":"string","example":"now"},"hidden":{"description":"1 when the message is hidden from the message list, otherwise 0.","type":"string","example":"0"},"links":{"description":"URLs of the records related to the message.","properties":{"user":{"description":"URL of the user who owns the message.","type":"string","example":"https://:account.api-us1.com/api/3/messages/56/user"},"hyperlinks":{"description":"URL of the tracked links in the message.","type":"string","example":"https://:account.api-us1.com/api/3/messages/56/hyperlinks"}},"type":"object"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The API user may not access this message. Body: errors, a list with one item carrying status and detail."},"404":{"description":"No message with this ID. Body: message, a sentence naming the id."},"422":{"description":"A field failed validation. Body: errors, one item per rejected field, each with title, detail and source.pointer."}},"x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/messages/{messageId}/reportTotals":{"get":{"summary":"Retrieve the report totals of a campaign message","description":"Reporting totals of the campaign the message belongs to, with the message applied as the filter. This replaces calling the v1 `campaign_report_totals` action with only `messageid`. As in v1, the message narrows the totals only on a split campaign; for any other campaign the whole campaign is reported.\n\nTotals are lifetime unless both `startDate` and `endDate` are given, which restricts them to that window. Every field is always present and is null when the report taken does not provide it: lifetime, date-window and split-message totals come from different queries.\n\nThe account must have the Campaigns module and the API user must be able to access the campaign.","operationId":"retrieve-message-report-totals","parameters":[{"name":"messageId","in":"path","description":"ID of the message whose campaign is reported","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}},{"name":"startDate","in":"query","description":"Start of the date window, as Y-m-d, Y-m-d H:i:s or Y-m-dTH:i:s. Requires `endDate`; a date without a time starts at midnight.","required":false,"schema":{"type":"string"},"example":"2026-01-01"},{"name":"endDate","in":"query","description":"End of the date window, in the same formats as `startDate`. Requires `startDate` and may not be earlier than it.","required":false,"schema":{"type":"string"},"example":"2026-01-31 23:59:59"},{"name":"includeBots","in":"query","description":"`true` (the default) or `false`. With `false`, lifetime unique link clicks leave out contacts whose clicks on several links all came within 5 seconds, which is treated as automated clicking.","required":false,"schema":{"type":"string","default":"true","enum":["true","false"]}}],"responses":{"200":{"description":"The totals.","content":{"application/json":{"schema":{"properties":{"ldate":{"description":"When the campaign last sent.","type":["string","null"],"example":"2026-01-15 10:00:00"},"status":{"description":"Status code of the campaign; 5 is completed.","type":["integer","null"],"example":5},"type":{"description":"Type of the campaign, such as single or split. Null for date-window totals of a split campaign message.","type":["string","null"],"example":"split"},"messageId":{"description":"On a split campaign the ID of the message reported; otherwise the IDs of the campaign's messages, comma-separated.","type":["string","null"],"example":"12"},"totalAmt":{"description":"Number of contacts the campaign was addressed to.","type":["integer","null"],"example":1000},"sendAmt":{"description":"Number of emails sent.","type":["integer","null"],"example":990},"uniqueOpens":{"description":"Contacts who opened at least once.","type":["integer","null"],"example":400},"verifiedUniqueOpens":{"description":"Unique opens that were not machine opens such as Apple Mail Privacy Protection prefetches.","type":["integer","null"],"example":310},"uniqueLinkClicks":{"description":"Contacts who clicked at least one link.","type":["integer","null"],"example":120},"subscriberClicks":{"description":"Contacts who clicked, as the v1 report counts them.","type":["integer","null"],"example":120},"unsubscribes":{"description":"Contacts who unsubscribed from the campaign.","type":["integer","null"],"example":3},"forwards":{"description":"Times the campaign was forwarded.","type":["integer","null"],"example":2},"uniqueForwards":{"description":"Contacts who forwarded the campaign.","type":["integer","null"],"example":2},"uniqueReplies":{"description":"Lifetime totals only: contacts who replied.","type":["integer","null"],"example":1},"updates":{"description":"Lifetime totals only: contacts who updated their details from the campaign.","type":["integer","null"],"example":0},"totalBounces":{"description":"Lifetime totals only: hard and soft bounces together.","type":["integer","null"],"example":10},"socialShares":{"description":"Lifetime totals only: times the campaign was shared on social media.","type":["integer","null"],"example":0},"replies":{"description":"Date-window totals only: reply records in the window, as the v1 report counts them.","type":["integer","null"],"example":null},"bounces":{"description":"Date-window totals only: contacts who bounced in the window.","type":["integer","null"],"example":null},"shares":{"description":"Date-window totals only: shares in the window.","type":["integer","null"],"example":null},"revenue":{"description":"Revenue attributed to the campaign, per currency, as the v1 report returns it.","type":["array","null"],"items":{"type":"object"}}},"type":"object"}}}},"400":{"description":"The report refused the request. Body: errors, a list with one item carrying status and detail."},"403":{"description":"The account does not have the Campaigns module, or the API user may not access the campaign. Body: errors, a list with one item carrying status and detail."},"404":{"description":"The message belongs to no campaign, or there are no totals for its campaign. Body: errors, a list with one item carrying status and detail."},"422":{"description":"A query parameter is not valid: a date in another format, only one of the two dates, `endDate` before `startDate`, `includeBots` other than true or false, or an empty or repeated parameter. Body: errors, a list with one item carrying status and detail."}},"x-canonical-resource":"campaign","x-internal":true}},"/microsoftDynamics/connect":{"get":{"summary":"Retrieve the Microsoft Dynamics connection","description":"Internal: manages the account's Microsoft Dynamics connection record, not meant for direct use. Returns the account's Microsoft Dynamics connection, or the string `not found` in its place when there is none; both answer 200. Legacy endpoint; its method guard accepts only GET, POST, PUT and DELETE.","operationId":"get-microsoft-dynamics-connection","x-canonical-resource":"connections","responses":{"200":{"description":"The connection, or `not found`.","content":{"application/json":{"schema":{"type":"object","properties":{"connection":{"oneOf":[{"$ref":"#/components/schemas/MicrosoftDynamicsConnection"},{"type":"string","const":"not found","description":"The account has no Microsoft Dynamics connection."}]}}}}}},"405":{"description":"The request used another verb. The response carries an `Allow` header naming the accepted verbs."},"500":{"description":"The controller threw, for example on a body that is not a JSON object. The body is the exception message followed by `null`; it is not valid JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Connect Microsoft Dynamics","description":"Internal: manages the account's Microsoft Dynamics connection record, not meant for direct use. An account has at most one Microsoft Dynamics connection: this sets `name` and `external_id` on it, creating it when it does not exist. POST and PUT behave identically. Legacy endpoint; its method guard accepts only GET, POST, PUT and DELETE.","operationId":"connect-microsoft-dynamics","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectRequest"}}}},"responses":{"200":{"description":"The saved connection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectResult"}}}},"405":{"description":"The request used another verb. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`name` or `external_id` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectErrors"}}}},"500":{"description":"The controller threw, for example on a body that is not a JSON object. The body is the exception message followed by `null`; it is not valid JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update the Microsoft Dynamics connection","description":"Internal: manages the account's Microsoft Dynamics connection record, not meant for direct use. An account has at most one Microsoft Dynamics connection: this sets `name` and `external_id` on it, creating it when it does not exist. POST and PUT behave identically. Legacy endpoint; its method guard accepts only GET, POST, PUT and DELETE.","operationId":"update-microsoft-dynamics-connection","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectRequest"}}}},"responses":{"200":{"description":"The saved connection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectResult"}}}},"405":{"description":"The request used another verb. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`name` or `external_id` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MicrosoftDynamicsConnectErrors"}}}},"500":{"description":"The controller threw, for example on a body that is not a JSON object. The body is the exception message followed by `null`; it is not valid JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"delete":{"summary":"Delete the Microsoft Dynamics connection","description":"Internal: manages the account's Microsoft Dynamics connection record, not meant for direct use. Deletes the account's Microsoft Dynamics connection. Answers 200 whether or not one existed; the body says which. Legacy endpoint; its method guard accepts only GET, POST, PUT and DELETE.","operationId":"delete-microsoft-dynamics-connection","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"responses":{"200":{"description":"Deleted, or there was nothing to delete.","content":{"application/json":{"schema":{"type":"object","properties":{"connection":{"type":"string","enum":["deleted","not found"],"description":"`deleted`, or `not found` when the account had no Microsoft Dynamics connection."}}}}}},"405":{"description":"The request used another verb. The response carries an `Allow` header naming the accepted verbs."},"500":{"description":"The controller threw, for example on a body that is not a JSON object. The body is the exception message followed by `null`; it is not valid JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/notes":{"get":{"summary":"Retrieve list of all notes","description":"Lists notes. A note belongs to one record: a contact, a deal, a deal task, a contact activity entry or an account, named by reltype and relid. Only notes the caller is allowed to see are returned. Notes on activity entries are always shown. Notes on contacts need permission to edit contacts (pg_subscriber_edit), notes on deals need deal access (pg_deal) and an account with Deals, notes on deal tasks need permission to see all deals (pg_deal_list_all), and notes on accounts need permission to edit accounts (pg_account_edit). Drafts are left out unless filters[is_draft] asks for them. Without orders, the order of the notes is not defined. There is no error response of its own: unknown filters are ignored. GET /contacts/{id}/notes lists the notes of one contact.","operationId":"retrieve-list-of-all-notes","x-canonical-resource":"note","parameters":[{"name":"filters[reltype]","in":"query","description":"Only notes on this kind of record. Exact match.","schema":{"type":"string","enum":["Subscriber","Deal","DealTask","Activity","CustomerAccount"]}},{"name":"filters[relid]","in":"query","description":"Only notes on the record with this id. Send filters[reltype] too, because ids of different kinds of record overlap.","schema":{"type":"integer"}},{"name":"filters[contact_id]","in":"query","description":"Only notes on this contact. The same as filters[reltype]=Subscriber with filters[relid], and replaces both. When more than one of filters[account_id], filters[contact_id] and filters[deal_id] is sent, only the first in that order is used.","schema":{"type":"integer"}},{"name":"filters[deal_id]","in":"query","description":"Only notes on this deal. Works like filters[contact_id], with reltype Deal.","schema":{"type":"integer"}},{"name":"filters[account_id]","in":"query","description":"Only notes on this account. Works like filters[contact_id], with reltype CustomerAccount.","schema":{"type":"integer"}},{"name":"filters[include_related]","in":"query","description":"Send with filters[account_id] to also return the notes on the account's contacts and deals, newest first. Sending the parameter at all switches to this mode, but the contact and deal notes are only added when its value is not empty or 0. In this mode drafts are included, and filters[is_draft], filters[reltype], filters[relid], filters[cdate] and orders are ignored; ids no longer picks notes but still caps how many are returned. Known defect: with filters[contact_id] or filters[deal_id] instead, it returns notes on any contact, deal or account whose id equals the given id.","schema":{"type":"string"}},{"name":"filters[is_draft]","in":"query","description":"0 for published notes, the default, or 1 for drafts. Send it twice as filters[is_draft][]=0&filters[is_draft][]=1 to get both.","schema":{"type":"integer","enum":[0,1]}},{"name":"filters[cdate]","in":"query","description":"Only notes created at exactly this date and time, written as YYYY-MM-DD HH:MM:SS. Comparison operators are not supported.","schema":{"type":"string"}},{"name":"orders[cdate]","in":"query","description":"Sort by creation time: DESC for newest first; any other value sorts oldest first. orders[reltype] and orders[relid] sort the same way by those fields.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of notes to return. Defaults to 20; values above 100 are treated as 100. 0 or a negative number returns every note and ignores offset.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of notes to skip. Use with limit to page through the notes.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated note IDs to return. When set, only those notes are returned; limit does not apply, but offset still does.","schema":{"type":"string"}}],"responses":{"200":{"description":"The matching notes, with their total.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"notes\": [\n        {\n            \"relid\": \"126\",\n            \"reltype\": \"Activity\",\n            \"userid\": \"1\",\n            \"is_draft\": \"0\",\n            \"cdate\": \"2022-05-26T08:58:34-05:00\",\n            \"mdate\": \"2022-05-26T08:58:34-05:00\",\n            \"note\": \"Oh, hi Mark\",\n            \"links\": {\n                \"activities\": \"https://:account.api-us1.com/api/3/notes/1/activities\",\n                \"user\": \"https://:account.api-us1.com/api/3/notes/1/user\",\n                \"mentions\": \"https://:account.api-us1.com/api/3/notes/1/mentions\",\n                \"notes\": \"https://:account.api-us1.com/api/3/notes/1/notes\",\n                \"owner\": \"https://:account.api-us1.com/api/3/notes/1/owner\"\n            },\n            \"id\": \"1\",\n            \"user\": \"1\",\n            \"owner\": {\n                \"type\": \"activity\",\n                \"id\": \"126\"\n            }\n        },\n        {\n            \"relid\": \"6\",\n            \"reltype\": \"Deal\",\n            \"userid\": \"1\",\n            \"is_draft\": \"0\",\n            \"cdate\": \"2023-08-18T11:09:38-05:00\",\n            \"mdate\": \"2023-08-18T11:09:40-05:00\",\n            \"note\": \"Here is a note\",\n            \"links\": {\n                \"activities\": \"https://:account.api-us1.com/api/3/notes/2/activities\",\n                \"user\": \"https://:account.api-us1.com/api/3/notes/2/user\",\n                \"mentions\": \"https://:account.api-us1.com/api/3/notes/2/mentions\",\n                \"notes\": \"https://:account.api-us1.com/api/3/notes/2/notes\",\n                \"owner\": \"https://:account.api-us1.com/api/3/notes/2/owner\"\n            },\n            \"id\": \"2\",\n            \"user\": \"1\",\n            \"owner\": {\n                \"type\": \"deal\",\n                \"id\": \"6\"\n            }\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}},"schema":{"type":"object","properties":{"notes":{"type":"array","items":{"type":"object","properties":{"relid":{"type":"string","description":"Id of the record the note belongs to. reltype says what kind of record it is.","examples":["126"]},"reltype":{"type":"string","description":"The kind of record the note belongs to: Subscriber (a contact), Deal, DealTask (a deal task), Activity (a contact activity entry) or CustomerAccount (an account).","examples":["Activity"]},"userid":{"type":"string","description":"Id of the account user who wrote the note.","examples":["1"]},"is_draft":{"type":"string","description":"1 while the note is a draft, 0 once published.","examples":["0"]},"cdate":{"type":["string","null"],"description":"When the note was created, as a date and time with UTC offset.","examples":["2022-05-26T08:58:34-05:00"]},"mdate":{"type":["string","null"],"description":"When the note was last changed, as a date and time with UTC offset.","examples":["2022-05-26T08:58:34-05:00"]},"note":{"type":"string","description":"The text of the note. Notes saved through the API have HTML characters escaped, emoji removed and surrounding spaces trimmed; notes saved by the app or by older paths may not.","examples":["Oh, hi Mark"]},"links":{"type":"object","properties":{"activities":{"type":"string","description":"URL of the contact activity entries that reference the note.","examples":["https://:account.api-us1.com/api/3/notes/1/activities"]},"user":{"type":"string","description":"URL of the account user who wrote the note.","examples":["https://:account.api-us1.com/api/3/notes/1/user"]},"mentions":{"type":"string","description":"URL of the mentions on the note. Known defect: it currently returns the mention whose own id equals the note id, not the mentions on this note, so do not rely on it.","examples":["https://:account.api-us1.com/api/3/notes/1/mentions"]},"notes":{"type":"string","description":"URL of notes attached to this note. A note cannot be attached to another note, so this list is always empty.","examples":["https://:account.api-us1.com/api/3/notes/1/notes"]},"owner":{"type":"string","description":"URL of the record the note belongs to.","examples":["https://:account.api-us1.com/api/3/notes/1/owner"]}},"description":"URLs of the records related to the note."},"id":{"type":"string","description":"Id of the note.","examples":["1"]},"user":{"type":"string","description":"Id of the account user who wrote the note. The same value as userid.","examples":["1"]},"owner":{"type":"object","properties":{"type":{"type":"string","description":"API type of that record: contact, deal, deal-task, activity or account.","examples":["activity"]},"id":{"type":"string","description":"Id of that record. The same value as relid.","examples":["126"]}},"description":"The record the note belongs to."}}},"description":"The notes on this page."},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Number of notes that match, ignoring limit and offset.","examples":[2]}},"description":"Information about the whole result."}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_notes","title":"List Notes","description":"List the notes added to contacts, deals and accounts, to read the context a rep left before their next action.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}},"post":{"summary":"Create a note on a contact, deal, task, activity, or account","description":"Create a note on one record. reltype names the record type and relid its id: reltype Subscriber with the contact id in relid adds a note to a contact. The record is named in the body; POST /notes takes no path parameter. The author is always the authenticated API user. Fails with 422 when reltype is not one of the five allowed values, when no record with relid exists for that type, or when note is empty, and with 403 when the API user may not edit notes on that record type.","operationId":"create-a-note","x-canonical-resource":"note","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"The text of the note. Required and must not be empty. HTML characters are escaped, emoji removed and surrounding spaces trimmed before it is saved."},"is_draft":{"type":"integer","description":"0 or 1. 1 saves the note as a draft: the note webhook does not fire and, on a deal, no deal activity is recorded. Defaults to 0."},"reltype":{"type":"string","enum":["Deal","Subscriber","DealTask","Activity","CustomerAccount"],"description":"Record type the note attaches to. Case-sensitive; a contact is Subscriber."},"relid":{"type":"integer","format":"int32","description":"Id of the record named by reltype; for reltype Subscriber this is the contact id. 422 if no such record exists."},"ownerType":{"type":"string","description":"Alternative to reltype: the record type as an API type name, such as contact, or as a reltype value. Takes precedence over reltype when both are sent, and may be combined with relid."},"owner":{"type":"integer","format":"int32","description":"Alternative to relid: the id of the record. Takes precedence over relid when both are sent, and may be combined with reltype."},"mentionStrings":{"type":"array","items":{"type":"string"},"description":"Usernames to mention, each written as @username. Every matching user who is not already mentioned on this note gets a mention record and a notification. Not returned on the note."},"listId":{"type":"integer","format":"int32","description":"Contact notes only. Id of the list whose contact-note webhooks fire for this note; 0, the default, fires the webhooks of every list. Not stored on the note. 400 when sent for a note on any other record type or when it is not a whole number of 0 or more."}},"required":["note"],"type":"object","allOf":[{"anyOf":[{"required":["reltype"]},{"required":["ownerType"]}]},{"anyOf":[{"required":["relid"]},{"required":["owner"]}]}],"description":"The note to create.","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"note":{"note":"This is the text of the note","relid":2,"reltype":"Subscriber"}}}}}}},"responses":{"201":{"description":"The created note, under note. The record it was created on comes along under the plural name of its type, for example contacts for a note on a contact.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contacts\": [\n        {\n            \"cdate\": \"2018-08-06T16:26:04-05:00\",\n            \"email\": \"sam@example.com\",\n            \"phone\": \"\",\n            \"firstName\": \"Sam\",\n            \"lastName\": \"Example\",\n            \"orgid\": \"0\",\n            \"segmentio_id\": \"\",\n            \"bounced_hard\": \"0\",\n            \"bounced_soft\": \"0\",\n            \"bounced_date\": null,\n            \"ip\": \"0\",\n            \"ua\": null,\n            \"hash\": \"14d8c4418ae944c68e9dde4a975854cc\",\n            \"socialdata_lastcheck\": null,\n            \"email_local\": \"\",\n            \"email_domain\": \"\",\n            \"sentcnt\": \"0\",\n            \"rating_tstamp\": null,\n            \"gravatar\": \"0\",\n            \"deleted\": \"0\",\n            \"anonymized\": \"0\",\n            \"adate\": null,\n            \"udate\": \"2018-09-28T17:45:11-05:00\",\n            \"edate\": null,\n            \"deleted_at\": null,\n            \"created_utc_timestamp\": \"2018-09-21 12:04:40\",\n            \"updated_utc_timestamp\": \"2018-09-28 17:45:11\",\n            \"links\": {\n                \"bounceLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs\",\n                \"contactAutomations\": \"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations\",\n                \"contactData\": \"https://:account.api-us1.com/api/:version/contacts/2/contactData\",\n                \"contactGoals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactGoals\",\n                \"contactLists\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLists\",\n                \"contactLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/contactLogs\",\n                \"contactTags\": \"https://:account.api-us1.com/api/:version/contacts/2/contactTags\",\n                \"contactDeals\": \"https://:account.api-us1.com/api/:version/contacts/2/contactDeals\",\n                \"deals\": \"https://:account.api-us1.com/api/:version/contacts/2/deals\",\n                \"fieldValues\": \"https://:account.api-us1.com/api/:version/contacts/2/fieldValues\",\n                \"geoIps\": \"https://:account.api-us1.com/api/:version/contacts/2/geoIps\",\n                \"notes\": \"https://:account.api-us1.com/api/:version/contacts/2/notes\",\n                \"organization\": \"https://:account.api-us1.com/api/:version/contacts/2/organization\",\n                \"plusAppend\": \"https://:account.api-us1.com/api/:version/contacts/2/plusAppend\",\n                \"trackingLogs\": \"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs\",\n                \"scoreValues\": \"https://:account.api-us1.com/api/:version/contacts/2/scoreValues\"\n            },\n            \"id\": \"2\",\n            \"organization\": null\n        }\n    ],\n    \"note\": {\n        \"note\": \"This is the text of the note\",\n        \"cdate\": \"2018-09-28T17:45:11-05:00\",\n        \"mdate\": \"2018-09-28T17:45:11-05:00\",\n        \"reltype\": \"Subscriber\",\n        \"relid\": 2,\n        \"userid\": \"1\",\n        \"links\": {\n            \"activities\": \"https://:account.api-us1.com/api/:version/notes/2/activities\",\n            \"user\": \"https://:account.api-us1.com/api/:version/notes/2/user\",\n            \"mentions\": \"https://:account.api-us1.com/api/:version/notes/2/mentions\",\n            \"notes\": \"https://:account.api-us1.com/api/:version/notes/2/notes\",\n            \"owner\": \"https://:account.api-us1.com/api/:version/notes/2/owner\"\n        },\n        \"owner\": {\n            \"type\": \"contact\",\n            \"id\": 2\n        },\n        \"id\": \"2\",\n        \"user\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"type":"object","properties":{"cdate":{"type":"string","example":"2018-08-06T16:26:04-05:00"},"email":{"type":"string","example":"jdoe@example.com"},"phone":{"type":"string","example":""},"firstName":{"type":"string","example":""},"lastName":{"type":"string","example":""},"orgid":{"type":"string","example":"0"},"segmentio_id":{"type":"string","example":""},"bounced_hard":{"type":"string","example":"0"},"bounced_soft":{"type":"string","example":"0"},"bounced_date":{},"ip":{"type":"string","example":"0"},"ua":{},"hash":{"type":"string","example":"14d8c4418ae944c68e9dde4a975854cc"},"socialdata_lastcheck":{},"email_local":{"type":"string","example":""},"email_domain":{"type":"string","example":""},"sentcnt":{"type":"string","example":"0"},"rating_tstamp":{},"gravatar":{"type":"string","example":"0"},"deleted":{"type":"string","example":"0"},"anonymized":{"type":"string","example":"0"},"adate":{},"udate":{"type":"string","example":"2018-09-28T17:45:11-05:00"},"edate":{},"deleted_at":{},"created_utc_timestamp":{"type":"string","example":"2018-09-21 12:04:40"},"updated_utc_timestamp":{"type":"string","example":"2018-09-28 17:45:11"},"links":{"type":"object","properties":{"bounceLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/bounceLogs"},"contactAutomations":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactAutomations"},"contactData":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactData"},"contactGoals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactGoals"},"contactLists":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLists"},"contactLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactLogs"},"contactTags":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactTags"},"contactDeals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/contactDeals"},"deals":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/deals"},"fieldValues":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/fieldValues"},"geoIps":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/geoIps"},"notes":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/notes"},"organization":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/organization"},"plusAppend":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/plusAppend"},"trackingLogs":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/trackingLogs"},"scoreValues":{"type":"string","example":"https://:account.api-us1.com/api/:version/contacts/2/scoreValues"}}},"id":{"type":"string","example":"2"},"organization":{}}},"description":"On a note created on a contact: that contact, as the only item, in the shape GET /contacts/{id} returns. See that operation for what each field means."},"note":{"type":"object","properties":{"note":{"type":"string","example":"This is the text of the note","description":"The text of the note. Notes saved through the API have HTML characters escaped, emoji removed and surrounding spaces trimmed; notes saved by the app or by older paths may not."},"cdate":{"type":["string","null"],"example":"2018-09-28T17:45:11-05:00","description":"When the note was created, as a date and time with UTC offset."},"mdate":{"type":["string","null"],"example":"2018-09-28T17:45:11-05:00","description":"When the note was last changed, as a date and time with UTC offset."},"reltype":{"type":"string","example":"Subscriber","description":"The kind of record the note belongs to: Subscriber (a contact), Deal, DealTask (a deal task), Activity (a contact activity entry) or CustomerAccount (an account)."},"relid":{"type":"integer","example":2,"default":0,"description":"Id of the record the note belongs to, as it was sent."},"userid":{"type":"string","example":"1","description":"Id of the account user who wrote the note."},"is_draft":{"type":"string","example":"0","description":"1 while the note is a draft, 0 once published."},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/activities","description":"URL of the contact activity entries that reference the note."},"user":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/user","description":"URL of the account user who wrote the note."},"mentions":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/mentions","description":"URL of the mentions on the note. Known defect: it currently returns the mention whose own id equals the note id, not the mentions on this note, so do not rely on it."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/notes","description":"URL of notes attached to this note. A note cannot be attached to another note, so this list is always empty."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/owner","description":"URL of the record the note belongs to."}},"description":"URLs of the records related to the note."},"owner":{"type":"object","properties":{"type":{"type":"string","example":"contact","description":"API type of that record: contact, deal, deal-task, activity or account."},"id":{"type":"integer","example":2,"default":0,"description":"Id of that record, as it was sent."}},"description":"The record the note belongs to."},"id":{"type":"string","example":"2","description":"Id of the note."},"user":{"type":"string","example":"1","description":"Id of the account user who wrote the note. The same value as userid."}},"description":"The created note."}}}}}},"400":{"description":"listId was sent for a note that is not on a contact, or is not a whole number of 0 or more.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The API user may not edit notes on this record type."},"422":{"description":"reltype is not one of Deal, Subscriber, DealTask, Activity, CustomerAccount; or no record with relid exists for that type; or note is empty."}},"deprecated":false}},"/notes/{id}":{"get":{"summary":"Retrieve a note","description":"Returns one note by its id, drafts included. As with GET /notes, only notes the caller is allowed to see can be read: notes on activity entries are always shown. Notes on contacts need permission to edit contacts (pg_subscriber_edit), notes on deals need deal access (pg_deal) and an account with Deals, notes on deal tasks need permission to see all deals (pg_deal_list_all), and notes on accounts need permission to edit accounts (pg_account_edit). Any other note returns 404, the same as an unknown id.","operationId":"retrieve-a-note","x-canonical-resource":"note","parameters":[{"name":"id","in":"path","description":"ID of the note to retrieve","schema":{"type":"integer"},"required":true}],"responses":{"200":{"description":"The note.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"note\": {\n        \"relid\": \"2\",\n        \"reltype\": \"Subscriber\",\n        \"userid\": \"1\",\n        \"cdate\": \"2018-09-12T17:20:20-05:00\",\n        \"mdate\": \"2018-09-20T09:10:06-05:00\",\n        \"note\": \"TEST NOTE\",\n        \"links\": {\n            \"activities\": \"https://:account.api-us1.com/api/:version/notes/2/activities\",\n            \"user\": \"https://:account.api-us1.com/api/:version/notes/2/user\",\n            \"mentions\": \"https://:account.api-us1.com/api/:version/notes/2/mentions\",\n            \"notes\": \"https://:account.api-us1.com/api/:version/notes/2/notes\",\n            \"owner\": \"https://:account.api-us1.com/api/:version/notes/2/owner\"\n        },\n        \"id\": \"2\",\n        \"user\": \"1\",\n        \"owner\": {\n            \"type\": \"contact\",\n            \"id\": \"2\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"note":{"type":"object","properties":{"relid":{"type":"string","example":"2","description":"Id of the record the note belongs to. reltype says what kind of record it is."},"reltype":{"type":"string","example":"Subscriber","description":"The kind of record the note belongs to: Subscriber (a contact), Deal, DealTask (a deal task), Activity (a contact activity entry) or CustomerAccount (an account)."},"userid":{"type":"string","example":"1","description":"Id of the account user who wrote the note."},"cdate":{"type":["string","null"],"example":"2018-09-12T17:20:20-05:00","description":"When the note was created, as a date and time with UTC offset."},"mdate":{"type":["string","null"],"example":"2018-09-20T09:10:06-05:00","description":"When the note was last changed, as a date and time with UTC offset."},"note":{"type":"string","example":"TEST NOTE","description":"The text of the note. Notes saved through the API have HTML characters escaped, emoji removed and surrounding spaces trimmed; notes saved by the app or by older paths may not."},"links":{"type":"object","properties":{"activities":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/activities","description":"URL of the contact activity entries that reference the note."},"user":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/user","description":"URL of the account user who wrote the note."},"mentions":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/mentions","description":"URL of the mentions on the note. Known defect: it currently returns the mention whose own id equals the note id, not the mentions on this note, so do not rely on it."},"notes":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/notes","description":"URL of notes attached to this note. A note cannot be attached to another note, so this list is always empty."},"owner":{"type":"string","example":"https://:account.api-us1.com/api/:version/notes/2/owner","description":"URL of the record the note belongs to."}},"description":"URLs of the records related to the note."},"id":{"type":"string","example":"2","description":"Id of the note."},"user":{"type":"string","example":"1","description":"Id of the account user who wrote the note. The same value as userid."},"owner":{"type":"object","properties":{"type":{"type":"string","example":"contact","description":"API type of that record: contact, deal, deal-task, activity or account."},"id":{"type":"string","example":"2","description":"Id of that record. The same value as relid."}},"description":"The record the note belongs to."},"is_draft":{"type":"string","example":"0","description":"1 while the note is a draft, 0 once published."}},"description":"The note."}}}}}},"404":{"description":"No note with this id, or the caller is not allowed to see the note.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the type and the id.","example":"No Result found for Note with id 1"}}},"examples":{"Result":{"value":{"message":"No Result found for Note with id 1"}}}}}}},"deprecated":false},"put":{"summary":"Update a note","description":"Update an existing note on a contact, deal, task, activity, or account. The note is addressed by its own id in the path. note, the text, and is_draft can be changed. reltype and relid in the body do not move the note to another record. Only the API user who created the note can update it.","operationId":"update-a-note","x-canonical-resource":"note","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the note to update","schema":{"type":"integer"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"properties":{"note":{"type":"string","description":"The new text of the note. Must not be empty. HTML characters are escaped, emoji removed and surrounding spaces trimmed before it is saved."},"is_draft":{"type":"integer","description":"0 or 1. 1 keeps the note as a draft, 0 publishes it; omit to leave it as it is. Publishing a draft fires the note webhook, as creating the note would."},"reltype":{"type":"string","description":"Does not move the note: it stays on the record it was created for. Possible Values: Activity, Deal, DealTask, Subscriber, CustomerAccount"},"relid":{"type":"string","description":"Does not move the note: it stays on the record it was created for."},"mentionStrings":{"type":"array","items":{"type":"string"},"description":"Usernames to mention, each written as @username. Every matching user who is not already mentioned on this note gets a mention record and a notification. Not returned on the note."},"is_new":{"type":"boolean","description":"When true and reltype is Deal, a note activity is recorded on the deal named by relid after the update."}},"required":[],"type":"object","description":"The fields to change.","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"note":{"note":"This is the text of the note","relid":2,"reltype":"Subscriber"}}}}}}},"responses":{"200":{"description":"The updated note.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"note\": {\n        \"relid\": \"107\",\n        \"reltype\": \"Subscriber\",\n        \"userid\": \"1\",\n        \"cdate\": \"2018-09-21T11:52:41-05:00\",\n        \"mdate\": \"2018-09-28T18:39:44-05:00\",\n        \"note\": \"This is the text of the note\",\n        \"links\": {\n            \"activities\": \"https://:account.api-us1.com/api/:version/notes/1/activities\",\n            \"user\": \"https://:account.api-us1.com/api/:version/notes/1/user\",\n            \"mentions\": \"https://:account.api-us1.com/api/:version/notes/1/mentions\",\n            \"notes\": \"https://:account.api-us1.com/api/:version/notes/1/notes\",\n            \"owner\": \"https://:account.api-us1.com/api/:version/notes/1/owner\"\n        },\n        \"id\": \"1\",\n        \"user\": \"1\",\n        \"owner\": {\n            \"type\": \"contact\",\n            \"id\": \"107\"\n        }\n    }\n}"}},"schema":{"type":"object","properties":{"note":{"type":"object","properties":{"relid":{"type":"string","description":"Id of the record the note belongs to. reltype says what kind of record it is.","examples":["107"]},"reltype":{"type":"string","description":"The kind of record the note belongs to: Subscriber (a contact), Deal, DealTask (a deal task), Activity (a contact activity entry) or CustomerAccount (an account).","examples":["Subscriber"]},"userid":{"type":"string","description":"Id of the account user who wrote the note.","examples":["1"]},"is_draft":{"type":"string","description":"1 while the note is a draft, 0 once published.","examples":["0"]},"cdate":{"type":["string","null"],"description":"When the note was created, as a date and time with UTC offset.","examples":["2018-09-21T11:52:41-05:00"]},"mdate":{"type":["string","null"],"description":"When the note was last changed, as a date and time with UTC offset.","examples":["2018-09-28T18:39:44-05:00"]},"note":{"type":"string","description":"The text of the note. Notes saved through the API have HTML characters escaped, emoji removed and surrounding spaces trimmed; notes saved by the app or by older paths may not.","examples":["This is the text of the note"]},"links":{"type":"object","properties":{"activities":{"type":"string","description":"URL of the contact activity entries that reference the note.","examples":["https://:account.api-us1.com/api/:version/notes/1/activities"]},"user":{"type":"string","description":"URL of the account user who wrote the note.","examples":["https://:account.api-us1.com/api/:version/notes/1/user"]},"mentions":{"type":"string","description":"URL of the mentions on the note. Known defect: it currently returns the mention whose own id equals the note id, not the mentions on this note, so do not rely on it.","examples":["https://:account.api-us1.com/api/:version/notes/1/mentions"]},"notes":{"type":"string","description":"URL of notes attached to this note. A note cannot be attached to another note, so this list is always empty.","examples":["https://:account.api-us1.com/api/:version/notes/1/notes"]},"owner":{"type":"string","description":"URL of the record the note belongs to.","examples":["https://:account.api-us1.com/api/:version/notes/1/owner"]}},"description":"URLs of the records related to the note."},"id":{"type":"string","description":"Id of the note.","examples":["1"]},"user":{"type":"string","description":"Id of the account user who wrote the note. The same value as userid.","examples":["1"]},"owner":{"type":"object","properties":{"type":{"type":"string","description":"API type of that record: contact, deal, deal-task, activity or account.","examples":["contact"]},"id":{"type":"string","description":"Id of that record. The same value as relid.","examples":["107"]}},"description":"The record the note belongs to."}},"description":"The updated note."}}}}}},"403":{"description":"The API user is not the note's author. The body is a plain sentence, not a JSON object, although it is sent as application/json.","content":{"application/json":{"schema":{"type":"string","example":"Not authorized to edit note"}}}},"404":{"description":"No note with this id, or the caller is not allowed to see the note.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the type and the id.","example":"No Result found for Note with id 1"}}},"examples":{"Result":{"value":{"message":"No Result found for Note with id 1"}}}}}},"422":{"description":"note is empty."}},"deprecated":false,"x-mcp-tool":{"name":"update_note","title":"Update Note","description":"Change the text of an existing note by its id.","annotations":{"readOnlyHint":false,"idempotentHint":true,"openWorldHint":false}}},"delete":{"summary":"Delete a note","description":"Deletes a note. Contact activity entries that referenced the note are kept but no longer point to it. Only the note's author or a user in the Admin group may delete it. A note the caller is not allowed to see returns 404, the same as an unknown id.","operationId":"delete-note","x-canonical-resource":"note","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the note to delete","schema":{"type":"integer"},"required":true}],"responses":{"200":{"description":"The note was deleted. The body is an empty object.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"403":{"description":"The API user is neither the note's author nor in the Admin group (Not authorized to delete note), or the delete failed (Failed to delete note). The body is a plain sentence, not a JSON object, although it is sent as application/json.","content":{"application/json":{"schema":{"type":"string","example":"Not authorized to delete note"}}}},"404":{"description":"No note with this id, or the caller is not allowed to see the note.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"A sentence naming the type and the id.","example":"No Result found for Note with id 1"}}},"examples":{"Result":{"value":{"message":"No Result found for Note with id 1"}}}}}}},"deprecated":false}},"/notification/runChecks":{"post":{"summary":"Rebuild the account's status alerts","description":"Recomputes the in-app status alerts shown in the notification menu, adding, updating or clearing each one: the email credit, sending limit, contact limit and expiring connection alerts of the calling user's group; deal email connection alerts when the account has deals and the deal connection alert feature flag is on; and, when concurrent session detection is on, the calling user's concurrent session alert. The work runs before the response is sent, and nothing is returned. The request body is not read. Internal: notification maintenance.","operationId":"run-notification-checks","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":true,"responses":{"202":{"description":"The checks ran. The body is empty."},"405":{"description":"The method is not POST. The body is empty and the `Allow` header lists POST.","headers":{"Allow":{"description":"`POST`","schema":{"type":"string"}}}},"500":{"description":"A check failed. The failure is logged and the generic API error body is returned.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Generic error text.","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true}},"/nylas/authorize":{"get":{"summary":"Redirect to the Nylas mailbox connection flow","description":"Older entry point to connecting a mailbox, still opened by parts of the app and by the Reconnect link of the connected email notifications. Redirects to GET /api/3/nylas/v3/authorize, passing returnData on and dropping every other parameter, so the Nylas sign-in page is not prefilled and the trial-account limit of that endpoint applies. Internal: backs mailbox connection in the app. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app and the Reconnect link use.","operationId":"redirect-to-the-nylas-email-connection-flow","x-canonical-resource":"deal_connection","parameters":[{"name":"returnData","in":"query","description":"Passed on to GET /nylas/v3/authorize. Defaults to 1.","required":false,"schema":{"type":"string","default":"1"},"example":"1"}],"responses":{"302":{"description":"Redirect to `/api/3/nylas/v3/authorize?returnData=<returnData>`, in the `Location` header. The body is empty."}},"deprecated":false,"x-internal":true}},"/nylas/v3/authorize":{"get":{"summary":"Start connecting a mailbox through Nylas","description":"Redirects the browser to the Nylas sign-in page, whose URL AC Nylas builds for this account, so the user can connect a mailbox to the CRM and sync its emails as deal emails. The app opens it in a popup; after sign-in Nylas returns to GET /nylas/v3/oauthCallback. Without `email`, a trial account whose user already has a connected email is refused. With `email`, which the app sends to reconnect a mailbox, the sign-in page is prefilled and the provider of the connected email with that address is preselected.","operationId":"authorize-a-nylas-email-connection","parameters":[{"name":"returnData","in":"query","description":"Passed to AC Nylas, which uses it to decide whether the connection data is returned once sign-in completes. Defaults to `false`.","required":false,"schema":{"type":"string","default":"false"},"example":"true"},{"name":"email","in":"query","description":"Address of the mailbox to reconnect. Prefills the Nylas sign-in page and skips the trial-account limit.","required":false,"schema":{"type":"string"},"example":"jane@example.com"}],"responses":{"302":{"description":"Redirect to the Nylas sign-in page, whose URL is in the `Location` header."},"400":{"description":"The account is on a trial, its user already has a connected email, and no `email` was sent. The body is plain text, not JSON.","content":{"text/html":{"schema":{"type":"string"},"example":"Trial accounts can only have one connected email per user"}}},"500":{"description":"AC Nylas did not return a sign-in URL. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"deal_connection","x-internal":true}},"/nylas/v3/bounce_detected":{"post":{"summary":"Record a bounce of an email sent from a connected mailbox","description":"Called by AC Nylas when an email a connected mailbox sent bounces. Marks the bounced address's recipient rows on the matching deal email as bounced, gives the contact with that address a bounce record when the code is one AC tracks, and for a hard bounce of an outbound deal email enters the contact into bounce-triggered automations. Keys may be sent in camelCase or snake_case.","operationId":"receive-a-nylas-bounce-detected-event","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NylasBounceDetectedWebhook"}}}},"responses":{"200":{"description":"The bounce was processed, including when no deal email or contact matched. The body is empty."},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"description":"Always `400`.","type":"string"},"detail":{"description":"Why the body could not be read.","type":"string"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"422":{"description":"`grantId` or `bouncedAddresses` is missing or blank, or a field has the wrong JSON type.","content":{"application/json":{"schema":{"properties":{"errors":{"type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer"},"title":{"description":"Always `Invalid attribute`.","type":"string"},"detail":{"description":"What is wrong with the field.","type":"string"},"source":{"properties":{"pointer":{"description":"The field, as `/data/attributes/<field>`.","type":"string"}},"type":"object"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/grantId"}}]}}}},"500":{"description":"Recording the bounce failed (the body names the error, with the header `Content-Type: json`), or `origin`, `origin.id` or `code` is missing (the body is the API's generic error).","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"What failed.","type":"string"}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/grant_event":{"post":{"summary":"Update a connected email from a Nylas grant event","description":"Called by AC Nylas when the Nylas grant of a connected mailbox changes. `grant.created` and `grant.updated` set the connected email to running; `grant.deleted` and `grant.expired` set it to invalid and revoke the grant. A `grant.created` that carries `account_id` upgrades the Nylas v2 connected email with that account ID to v3 with this grant. A grant that belongs to no connected email is revoked, and when the account no longer has the deals entitlement the connected email's grant is revoked; neither changes a connected email.","operationId":"receive-a-nylas-grant-event","requestBody":{"description":"The Nylas notification as AC Nylas forwards it. `type` is read from the envelope and the rest from `data.object`; a key in `data.object` wins over the envelope key of the same name. Other envelope fields are accepted and ignored. A field with the wrong JSON type fails with 422.","required":true,"content":{"application/json":{"schema":{"required":["type","data"],"properties":{"type":{"description":"Notification type: `grant.created`, `grant.updated`, `grant.deleted` or `grant.expired`. Any other type for a grant that belongs to a connected email fails with 500.","type":"string","example":"grant.expired"},"data":{"description":"Notification data.","required":["object"],"properties":{"object":{"description":"The grant. A missing `object` fails with 500.","required":["grant_id"],"properties":{"grant_id":{"description":"Nylas grant the event is about, matched against the connected emails.","type":"string","example":"5b6e29b0-7245-47ce-be02-16c4717751de"},"provider":{"description":"Email provider of the grant, such as `google` or `microsoft`. Stored on a migrated connected email.","type":"string","example":"google"},"account_id":{"description":"Nylas v2 account ID, sent on `grant.created` for a mailbox migrated from Nylas v2.","type":"string","example":"b4zy4bmoqz8ycxp4w3qt5rw5y"}},"type":"object"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The event was processed. The body is empty."},"422":{"description":"The body is empty or not JSON (`Invalid body`), or a field has the wrong JSON type. Responses carry the header `Content-Type: json`.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Invalid body`, or which field has the wrong type.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Invalid body"}}}}},"500":{"description":"Updating the connected email failed (the body names the error), or `type` or `data.object` was not usable (the body is the API's generic error).","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"What failed.","type":"string"}},"type":"object"}},"type":"object"}}}}},"x-canonical-resource":"deal_connection","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/link_clicked":{"post":{"summary":"Record a link click in a tracked outbound email","description":"Called by AC Nylas when a contact clicks a tracked link in an email the CRM sent through a connected mailbox. Records the click on the matching tracked link and, the first time, adds a click activity and enters the contact into click-triggered automations. Clicks of a contact whose email hard-bounced are ignored; with file attachment link tracking on, a click on a file download link publishes a file download event instead. Overwrites the stored click count, so it is marked destructive. Responses carry the header `Content-Type: json`.","operationId":"receive-a-nylas-link-clicked-event","requestBody":{"description":"The Nylas notification as AC Nylas forwards it. Only `data.object` is read; the other envelope fields (`specversion`, `type`, `source`, `id`, `time`, `webhook_delivery_attempt`, `data.application_id`, `data.grant_id`) are accepted and ignored.","required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"description":"Notification data. A missing `object` fails with 422.","required":["object"],"properties":{"object":{"$ref":"#/components/schemas/NylasLinkClickedWebhook"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The notification was processed. `created` is true when processing finished, including when the click was ignored or matched no tracked link; false, with `message`, when recording it failed.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"created":{"description":"False when recording the click failed.","type":"boolean","example":true},"message":{"description":"Why recording the click failed. Absent when `created` is true.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"created":true}}}}},"422":{"description":"The body is empty or not JSON (`Invalid body`), or `data.object` is missing or has a field of the wrong JSON type.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Invalid body`, or what failed to read.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Invalid body"}}}}},"500":{"description":"The label is not valid JSON, names another account in `ac_account_id` or lacks the keys that identify the email and contact, or a required field is empty. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/message_body":{"post":{"summary":"Publish the body of a synced email","description":"Called by AC Nylas with the body of an email already stored as a deal email. Publishes the body and the deal email for email body processing; the deal email itself is not changed. Responses carry the header `Content-Type: json`.","operationId":"receive-a-nylas-message-body","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NylasMessageBody"}}}},"responses":{"200":{"description":"The body was published. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"400":{"description":"No deal email has the ID in `deal_email_id`.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"Always `Deal email not found for message body`.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Deal email not found for message body"}}}}},"422":{"description":"The body is empty or not JSON (`Invalid body`), or a field has the wrong JSON type.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Invalid body`, or which field has the wrong type.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Expected deal_email_id to be of type integer, got string"}}}}},"500":{"description":"An unexpected error. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"emailActivities","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/message_created":{"post":{"summary":"Store an email synced from a connected mailbox","description":"Called by AC Nylas for each email a connected mailbox sends or receives. When the sender or a recipient is a contact, the email is stored as a deal email with its recipients and its deal and account relations, appears on the activity stream of each matching contact and of their deals, and, when `body` is not empty, is published for email body processing; a reply to an email sent from the CRM also records the contact's reply and can enter the contact into reply-triggered automations. Nothing is stored, and `created` is false, when no contact matches, for an attachment notification, an email already stored, an email dated more than one year ago, or a grant that belongs to no connected email of the account; `message` then says why, except when no contact matched. When the account no longer has the deals entitlement, the mailbox's Nylas grant is revoked instead and nothing is stored: that is why the operation is marked destructive. Responses carry the header `Content-Type: json`.","operationId":"receive-a-nylas-message-created-event","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["message"],"properties":{"message":{"$ref":"#/components/schemas/NylasMessageCreatedWebhook"}},"type":"object"}}}},"responses":{"200":{"description":"The email was processed. `created` says whether a deal email was stored.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"deal_email_id":{"description":"ID of the stored deal email; 0 when no contact matched or the account lost the deals entitlement. Absent when `message` is set.","type":"integer","example":7},"created":{"description":"True when a deal email was stored.","type":"boolean","example":true},"message":{"description":"Why the email was skipped, such as `Message already processed.`, `Skip attachment notification.`, `Message date outside of timeframe.` or `Grant not found: <grant_id>.`. Absent when processing finished.","type":"string"}},"type":"object"}},"type":"object"},"examples":{"Stored":{"summary":"A deal email was stored","value":{"result":{"deal_email_id":7,"created":true}}},"Skipped":{"summary":"The email was already stored","value":{"result":{"message":"Message already processed.","created":false}}}}}}},"422":{"description":"The body has no `message`, or a field of it has the wrong JSON type. Nothing was stored.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Message is empty`, or which field has the wrong type.","type":"string"},"created":{"description":"Always false.","type":"boolean"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Message is empty","created":false}}}}},"500":{"description":"An unexpected error. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/message_opened":{"post":{"summary":"Record an open of a tracked outbound email","description":"Called by AC Nylas when a contact opens an email the CRM sent through a connected mailbox. Records the open count on the email's open link and, the first time, adds an open activity and enters the contact into open-triggered automations. Opens of a contact whose email hard-bounced, or who opted out of open tracking, are ignored. Overwrites the stored open count, so it is marked destructive. Responses carry the header `Content-Type: json`.","operationId":"receive-a-nylas-message-opened-event","requestBody":{"description":"The Nylas notification as AC Nylas forwards it. Only `data.object` is read; the other envelope fields (`specversion`, `type`, `source`, `id`, `time`, `webhook_delivery_attempt`, `data.application_id`, `data.grant_id`) are accepted and ignored.","required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"description":"Notification data. A missing `object` fails with 422.","required":["object"],"properties":{"object":{"$ref":"#/components/schemas/NylasMessageOpenedWebhook"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The notification was processed. `created` is true when processing finished, including when the open was ignored; false, with `message`, when recording it failed.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"created":{"description":"False when recording the open failed.","type":"boolean","example":true},"message":{"description":"Why recording the open failed. Absent when `created` is true.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"created":true}}}}},"400":{"description":"The label names another account in `ac_account_id`.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"Always `Account mismatch in tracking data`.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Account mismatch in tracking data"}}}}},"422":{"description":"The body is empty or not JSON (`Invalid body`), or `data.object` is missing or has a field of the wrong JSON type.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Invalid body`, or what failed to read.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Invalid body"}}}}},"500":{"description":"The label is not valid JSON or lacks the keys that identify the email and contact, or a required field is empty. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/nylas/v3/oauthCallback":{"get":{"summary":"Finish connecting a mailbox through Nylas","description":"Where Nylas sends the browser after the user signs in to connect a mailbox. Exchanges `code` for a Nylas grant through AC Nylas and saves the mailbox as a connected email: the connected email with the same address gets the new grant, otherwise one is created for the current user, and either way it is set to running on Nylas v3. Answers an HTML page that sends the window that opened the popup to the connected emails settings page and closes the popup. Although a GET, it creates or updates a connected email.","operationId":"complete-a-nylas-email-connection","parameters":[{"name":"code","in":"query","description":"Authorization code Nylas issued for the sign-in.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The mailbox is connected. The body is an HTML page with a script that reloads the opener on the connected emails settings page and closes the window.","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Saving the connected email failed. The body is plain text, not JSON.","content":{"text/html":{"schema":{"type":"string"},"example":"Error saving connected email data"}}},"422":{"description":"AC Nylas returned a grant without an email address, grant ID or provider. Nothing was saved. The body is plain text, not JSON.","content":{"text/html":{"schema":{"type":"string"},"example":"Token is invalid"}}},"500":{"description":"AC Nylas could not exchange the code, for instance because it is missing or invalid. The body is the API's generic error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"deal_connection","x-internal":true}},"/nylas/v3/thread_replied":{"post":{"summary":"Record a reply to a tracked outbound email","description":"Called by AC Nylas when someone replies to an email the CRM sent through a connected mailbox. When the reply comes from the contact the email was sent to, records the contact's reply (updating the time of an existing one) and enters the contact into reply-triggered automations. A reply from anyone else, from the mailbox itself, or from a contact whose email hard-bounced is ignored. Updates an existing reply, so it is marked destructive. Responses carry the header `Content-Type: json`.","operationId":"receive-a-nylas-thread-replied-event","requestBody":{"description":"The Nylas notification as AC Nylas forwards it. Only `data.object` is read; the other envelope fields (`specversion`, `type`, `source`, `id`, `time`, `webhook_delivery_attempt`, `data.application_id`, `data.grant_id`) are accepted and ignored.","required":true,"content":{"application/json":{"schema":{"required":["data"],"properties":{"data":{"description":"Notification data. A missing `object` fails with 422.","required":["object"],"properties":{"object":{"$ref":"#/components/schemas/NylasThreadRepliedWebhook"}},"type":"object"}},"type":"object"}}}},"responses":{"200":{"description":"The reply was recorded or ignored. The body is empty."},"404":{"description":"The reply in `message_id` is not stored as a deal email yet; AC Nylas can retry once it has synced.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always `Reply message not synced`.","type":"string"}},"type":"object"},"example":{"message":"Reply message not synced"}}}},"422":{"description":"The body is empty or not JSON (`Invalid body`), or `data.object` is missing or has a field of the wrong JSON type.","content":{"application/json":{"schema":{"properties":{"result":{"properties":{"message":{"description":"`Invalid body`, or what failed to read.","type":"string"}},"type":"object"}},"type":"object"},"example":{"result":{"message":"Invalid body"}}}}},"500":{"description":"The label is not valid JSON, names another account in `ac_account_id` or lacks the keys that identify the email and contact, or a required field is empty (the body is the API's generic error); or recording the reply failed, in which case the body is the error text, not JSON.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Generic error text.","type":"string"}},"type":"object"},"example":{"message":"Something went wrong on our end. Please try again later"}}}}},"x-canonical-resource":"emailActivities","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/outboundemail/trial_limit_hit":{"get":{"summary":"Retrieve the one-to-one email trial limit status","description":"Whether a trial account has used up its allowance of one-to-one emails (emails sent to a contact or deal from the app, or by an automation's one-to-one email action). A trial account may send 100; the count is kept for a year from the last email sent. Always false for an account that is not on a trial. Internal: a trial account that has hit the limit has its one-to-one emails refused. Only GET is accepted; any other method is answered 405 with an `Allow` header and a JSON `errors` list.","operationId":"retrieve-outbound-email-trial-limit","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The status.","content":{"application/json":{"schema":{"type":"object","properties":{"trialLimitHit":{"type":"boolean","description":"True when the account is on a trial and has sent its 100 one-to-one emails.","example":false}}}}}}},"deprecated":false,"x-internal":true}},"/overview":{"get":{"summary":"List Overview dashboard sections","description":"The overview resource has no list. This route reaches the generic list action the controller inherits, which needs a database model that does not exist for overview, so every call fails with a server error. Read the sections one at a time with GET /overview/{id}. Internal.","operationId":"list-overview-sections","x-canonical-resource":"activecampaign_account","responses":{"500":{"description":"Always: the list action cannot run for this resource.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Something went wrong on our end. Please try again later\".","example":"Something went wrong on our end. Please try again later"}}}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Create an Overview dashboard section","description":"Overview sections cannot be created. This route reaches the generic create action the controller inherits, which needs a database model that does not exist for overview, so every call with an object body, or none, fails with a server error and creates nothing. Internal.","operationId":"create-an-overview-section","x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":false,"description":"Decoded but never used. A body that is JSON but not an object answers 400.","content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"400":{"description":"The body is JSON but not an object.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Always exactly one error.","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 400.","example":400},"title":{"type":"string","description":"Short name of the HTTP status.","example":"Bad Request"},"detail":{"type":"string","description":"Names the JSON type that was sent instead of an object.","example":"Request body must be a JSON object, array given."}}}}}}}}},"500":{"description":"Always, for an object body or none: the create action cannot run for this resource.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Something went wrong on our end. Please try again later\".","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/overview/favorites":{"post":{"summary":"Add a business goal to the calling user's favorites","description":"Adds one business goal to the calling user's favorites list for the domain and section in the body, creating the list on first use. Adding a goal that is already a favorite changes nothing and answers the same way. Favorites are per user. Internal: backs the favorite star on the Overview goals dashboard.","operationId":"add-an-overview-favorite-goal","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewFavoriteRequest"}}}},"responses":{"200":{"description":"The goal is a favorite.","content":{"application/json":{"schema":{"required":["result"],"properties":{"result":{"description":"Always \"Favorite saved\".","type":"string","example":"Favorite saved"}},"type":"object"}}}},"422":{"description":"A field is missing or blank, goalId is not a JSON number, or no label or business goal has that ID.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed check.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What failed, such as \"The entity does not exist\".","type":"string","example":"The entity does not exist"},"source":{"description":"The body field that failed.","properties":{"pointer":{"description":"The field, as /data/attributes/<name>.","type":"string","example":"/data/attributes/goalId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The favorites list could not be saved.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Why it failed.","type":"string","example":"Unable to save favorite data"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/overview/favorites/{goalId}":{"delete":{"summary":"Remove a business goal from the calling user's favorites","description":"Removes one business goal from the calling user's goals favorites on the Overview dashboard (domain overview, section goals). Answers the same way when the goal was not a favorite or the user has no favorites. Internal: backs the favorite star on the Overview goals dashboard.","operationId":"remove-an-overview-favorite-goal","parameters":[{"name":"goalId","in":"path","description":"ID of the business goal to remove from the favorites.","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"The goal is not a favorite any more. A failure to save the list is logged and answers the same way.","content":{"application/json":{"schema":{"required":["result"],"properties":{"result":{"description":"Always \"Favorite deleted\".","type":"string","example":"Favorite deleted"}},"type":"object"}}}},"500":{"description":"goalId is not a whole number.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Something went wrong on our end. Please try again later\".","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/overview/sortOrderConfiguration":{"post":{"summary":"Save the items pinned to a section of the Overview goals dashboard","description":"Saves which business goals or conversions the calling user pins to a section of the Overview goals dashboard, and in which order, replacing the configuration saved before for that domain and section. The configuration is per user. When it is new or differs from the saved one, an AI performance summary of the user's goals is regenerated in the background; a failure there is logged and does not fail the call. Internal: backs the goals dashboard on the Overview page.","operationId":"save-overview-sort-order-configuration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewSortOrderConfigurationRequest"}}}},"responses":{"200":{"description":"Saved, whether it was created or replaced.","content":{"application/json":{"schema":{"required":["result"],"properties":{"result":{"description":"Always \"created\".","type":"string","example":"created"}},"type":"object"}}}},"422":{"description":"domain or section is missing or blank, config is missing, or a field has the wrong type.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per failed check.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always \"Invalid attribute\".","type":"string","example":"Invalid attribute"},"detail":{"description":"What failed, such as \"Missing domain\".","type":"string","example":"Missing domain"},"source":{"description":"The body field that failed.","properties":{"pointer":{"description":"The field, as /data/attributes/<name>.","type":"string","example":"/data/attributes/domain"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The configuration could not be saved.","content":{"application/json":{"schema":{"properties":{"error":{"description":"Why it failed.","type":"string","example":"Unable to save sort order configuration data"}},"type":"object"}}}}},"x-canonical-resource":"business_goal","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/overview/{id}":{"get":{"summary":"Retrieve one section of the Overview dashboard","description":"Returns the data of one section of the legacy Overview dashboard, picked by id: news (the latest ActiveCampaign blog posts), widgetOrder (the calling user's saved widget layout) or activities (the recent activity stream). activities no longer works: it renders HTML templates that have been removed, and fails with a server error. Any other id answers 200 with an error object. Internal: written for the legacy Overview dashboard.","operationId":"retrieve-an-overview-section","parameters":[{"name":"id","in":"path","description":"The section: news, widgetOrder or activities.","required":true,"schema":{"type":"string","enum":["news","widgetOrder","activities"]},"example":"news"}],"responses":{"200":{"description":"The section's data; its shape depends on id.","content":{"application/json":{"schema":{"oneOf":[{"title":"News","description":"For news: the three latest posts of one category of the ActiveCampaign blog (www.activecampaign.com), in Brazilian Portuguese for users whose language is Portuguese (Brazil) and in English for everyone else. Cached for 30 minutes per language.","required":["posts"],"properties":{"posts":{"description":"The posts, newest first.","type":"array","items":{"required":["thumb","title","url"],"properties":{"thumb":{"description":"URL of the post author's 24-pixel avatar.","type":"string","example":"https://secure.gravatar.com/avatar/0123456789abcdef?s=24"},"title":{"description":"The post title as the blog renders it, HTML entities included.","type":"string","example":"A post title"},"url":{"description":"URL of the post.","type":"string","example":"https://www.activecampaign.com/blog/a-post"}},"type":"object"}}},"type":"object"},{"title":"Widget order","description":"For widgetOrder: the layout the calling user saved with PUT /overview/widgetOrder. An empty object when they never saved one.","properties":{"widgetOrder":{"description":"The value last saved, returned as it was sent: any JSON value the app chose to store."}},"type":"object"},{"title":"Unsupported section","description":"Any other id. The status is still 200.","required":["error","endpoint"],"properties":{"error":{"description":"Always \"unsupported overview end point for GET\".","type":"string","example":"unsupported overview end point for GET"},"endpoint":{"description":"The id from the path.","type":"string","example":"favorites"}},"type":"object"}]},"example":{"posts":[{"thumb":"https://secure.gravatar.com/avatar/0123456789abcdef?s=24","title":"A post title","url":"https://www.activecampaign.com/blog/a-post"}]}}}},"500":{"description":"id is activities, or id is news and the blog could not be read with nothing cached.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Always \"Something went wrong on our end. Please try again later\".","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true},"put":{"summary":"Update one section of the Overview dashboard","description":"Saves the calling user's widget layout of the legacy Overview dashboard when id is widgetOrder, replacing the one saved before; GET /overview/widgetOrder returns it. widgetOrder is the only section that can be written: any other id answers 200 with an error object and saves nothing. PATCH is routed to the same action and answers the same way. Internal: written for the legacy Overview dashboard.","operationId":"update-an-overview-section","parameters":[{"name":"id","in":"path","description":"The section. Only widgetOrder is supported.","required":true,"schema":{"type":"string","enum":["widgetOrder"]},"example":"widgetOrder"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"widgetOrder":{"description":"The layout to save, as any JSON value; it is stored and returned as sent. Leaving it out saves null."}},"type":"object"}}}},"responses":{"200":{"description":"Saved, or an error object for an id other than widgetOrder.","content":{"application/json":{"schema":{"oneOf":[{"title":"Saved","description":"For widgetOrder.","required":["status"],"properties":{"status":{"description":"Always \"ok\".","type":"string","example":"ok"}},"type":"object"},{"title":"Unsupported section","description":"Any other id. The status is still 200.","required":["error","endpoint"],"properties":{"error":{"description":"Always \"unsupported overview end point for PUT\".","type":"string","example":"unsupported overview end point for PUT"},"endpoint":{"description":"The id from the path.","type":"string","example":"favorites"}},"type":"object"}]},"example":{"status":"ok"}}}},"400":{"description":"The body is JSON but not an object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Update one section of the Overview dashboard","description":"Saves the calling user's widget layout of the legacy Overview dashboard when id is widgetOrder, replacing the one saved before; GET /overview/widgetOrder returns it. widgetOrder is the only section that can be written: any other id answers 200 with an error object and saves nothing. PUT is routed to the same action and answers the same way. Internal: written for the legacy Overview dashboard.","operationId":"patch-an-overview-section","parameters":[{"name":"id","in":"path","description":"The section. Only widgetOrder is supported.","required":true,"schema":{"type":"string","enum":["widgetOrder"]},"example":"widgetOrder"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"widgetOrder":{"description":"The layout to save, as any JSON value; it is stored and returned as sent. Leaving it out saves null."}},"type":"object"}}}},"responses":{"200":{"description":"Saved, or an error object for an id other than widgetOrder.","content":{"application/json":{"schema":{"oneOf":[{"title":"Saved","description":"For widgetOrder.","required":["status"],"properties":{"status":{"description":"Always \"ok\".","type":"string","example":"ok"}},"type":"object"},{"title":"Unsupported section","description":"Any other id. The status is still 200.","required":["error","endpoint"],"properties":{"error":{"description":"Always \"unsupported overview end point for PUT\".","type":"string","example":"unsupported overview end point for PUT"},"endpoint":{"description":"The id from the path.","type":"string","example":"favorites"}},"type":"object"}]},"example":{"status":"ok"}}}},"400":{"description":"The body is JSON but not an object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Request body must be a JSON object, array given."}]}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete an Overview dashboard section","description":"Overview sections cannot be deleted. This route reaches the generic delete action the controller inherits, which needs a database model that does not exist for overview, so every call fails with a server error and deletes nothing. Internal.","operationId":"delete-an-overview-section","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"The section. Any value fails the same way.","schema":{"type":"string"}}],"responses":{"500":{"description":"Always: the delete action cannot run for this resource.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always \"Something went wrong on our end. Please try again later\".","example":"Something went wrong on our end. Please try again later"}}}}}}},"x-internal":true}},"/performance/meta":{"get":{"summary":"Run one account performance check","description":"Internal: account-performance diagnostics for support and engineering, not a customer API. Runs the complexity check named by `type`. Without `type` the endpoint returns an HTML page of links to each type instead of JSON. Legacy endpoint with no method guard.","operationId":"run-performance-check-by-type","x-canonical-resource":"activecampaign_account","parameters":[{"name":"type","in":"query","description":"Check to run.","schema":{"type":"string","enum":["complexity","automations","crm","segments","recommendations"]}}],"responses":{"200":{"description":"Check results as pretty-printed JSON, or an HTML link index when `type` is omitted","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"One check result; the shape depends on the check."}}},"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/performance/view":{"get":{"summary":"Run all account performance checks","description":"Internal: account-performance diagnostics for support and engineering, not a customer API. Runs the account, automation and segment complexity checks and returns their combined results. Legacy endpoint with no method guard.","operationId":"run-all-performance-checks","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"Combined check results as pretty-printed JSON","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"One check result; the shape depends on the check."}}}}}},"deprecated":false,"x-internal":true}},"/persTags":{"get":{"summary":"List all personalization tags","description":"Returns every personalization tag the account can use in campaign and automation content: the built-in tags for contacts, lists, campaigns, deals, accounts, ecommerce and custom objects, plus one tag per custom field. Categories the account is not entitled to (deals, accounts, ecommerce, custom objects) are omitted. `categories` maps each category code to its display label, returned as a translation key.\n\nThe catalog is not paginated: `limit` and `offset` are ignored and the response has no `meta`.\n\nEcommerce and custom object tags are read from the account's custom object schemas. If that read fails, any request that includes `ECOMMERCE` or `CUSTOM_OBJECT` (the unfiltered request does) returns 500 and no tags at all. To keep the rest of the catalog when this happens, request those two categories separately.\n\nIf an account's contact, deal or account custom fields cannot be read, the catalog still returns 200 and includes one placeholder tag for that category with `type` `error` and `perstag` `%ERROR%`.","operationId":"list-all-personalization-tags","x-canonical-resource":"personalizations","parameters":[{"name":"filters[category]","in":"query","description":"Only tags in this category code, a key of `categories`, for example `CONTACT`, `CONTACT_CUSTOM`, `DEAL`, `LIST`, `CAMPAIGN`. An unknown code returns no tags. Combined with `filters[groups]`, the result is the union of both.","schema":{"type":"string"}},{"name":"filters[groups]","in":"query","description":"Comma-separated groups, or repeat `filters[groups][]`. `SUBSCRIBER` expands to `CONTACT`, `SUBSCRIBER`, `SUBSCRIBER_GEO`, `SUBSCRIBER_DATE_TIME` and `CONTACT_CUSTOM`; `CUSTOMER_ACCOUNT` to `CUSTOMER_ACCOUNT` and `ACCOUNT_CUSTOM`; `DEAL` to `DEAL` and `DEAL_CUSTOM`. Any other value is taken as a category code, and unknown values are ignored. Combined with `filters[category]`, the result is the union of both.","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"categories\": {\n        \"CONTACT\": \"contacts:personalization:group-label\",\n        \"CONTACT_CUSTOM\": \"perstags:categories:contact_custom\"\n    },\n    \"persTags\": [\n        {\n            \"id\": \"CONTACT_EMAIL\",\n            \"title\": \"columns:contact:email\",\n            \"type\": \"text\",\n            \"category\": \"CONTACT\",\n            \"perstag\": \"%EMAIL%\",\n            \"is_custom_field\": false\n        },\n        {\n            \"id\": \"CONTACT_CUSTOM_12\",\n            \"title\": \"Favourite colour\",\n            \"type\": \"text\",\n            \"category\": \"CONTACT_CUSTOM\",\n            \"perstag\": \"%FAVOURITE_COLOUR%\",\n            \"is_custom_field\": true,\n            \"required\": false\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"categories":{"type":["object","array"],"additionalProperties":{"type":"string"},"description":"Category code to label for the requested categories, or all categories when unfiltered; labels are returned as stored, which for built-in categories is a translation key such as `contacts:list`. When no category matches the filters this is an empty JSON array `[]`, not an object","maxItems":0},"persTags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"CONTACT_EMAIL","description":"Category and tag name joined; unique even where the same tag appears in two categories; absent on the error placeholder tag"},"title":{"type":"string","example":"columns:contact:email","description":"Label of the custom field or custom object field; for built-in tags, the label as stored, which is a translation key such as `fields:contacts:standard:email`"},"type":{"type":"string","example":"text","description":"`text` for built-in tags; the field type for custom fields and custom object fields, for example `dropdown` or `date`; `error` on the placeholder tag returned when a category's custom fields cannot be read"},"category":{"type":"string","example":"CONTACT","description":"Category code, a key of `categories`; for custom object tags, the schema's singular label instead"},"perstag":{"type":"string","example":"%EMAIL%","description":"The tag as written in content; `%ERROR%` on the error placeholder tag"},"is_custom_field":{"type":"boolean","example":false,"description":"True for contact, deal and account custom fields; false for built-in and custom object tags; absent on the error placeholder tag"},"required":{"type":"boolean","description":"Whether the field is required. Custom fields and custom object fields only"},"appId":{"type":["string","null"],"example":null,"description":"Ecommerce and custom object tags only: ID of the app that owns the custom object schema, or null when no app owns it. An ecommerce app ID is what places a schema's tags in the `ECOMMERCE` category"},"schemaId":{"type":"string","example":"0f6a3e0c-6c1b-4d0e-9f7a-2b8c1d5e4a3f","description":"Ecommerce and custom object tags only: ID of the custom object schema the field belongs to"},"visibility":{"type":"string","example":"private","description":"Ecommerce and custom object tags only: visibility of the custom object schema the field belongs to"}}},"description":"Built-in tags, followed by custom field and custom object tags"}}}}}},"500":{"description":"The account's custom object schemas could not be read and the request included `ECOMMERCE` or `CUSTOM_OBJECT`, explicitly or by being unfiltered.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Something went wrong on our end. Please try again later\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"Something went wrong on our end. Please try again later","description":"Generic error; no tags are returned"}}}}}}},"deprecated":false}},"/persTags/{id}":{"get":{"summary":"Retrieve a personalization tag","description":"This operation does not work. It never returns a personalization tag, for any id. Personalization tags are built when the list is requested and have no stored record to look up by id. To get tags, use the list operation, filtered by category if needed, and find the tag by its id.\n\nInternal: the app does not call it, and it has no recent traffic.","operationId":"retrieve-a-personalization-tag","x-canonical-resource":"personalizations","x-internal":true,"parameters":[{"name":"id","in":"path","required":true,"description":"Any value. No value returns a tag.","schema":{"type":"string"},"example":"CONTACT_EMAIL"}],"deprecated":false}},"/personalizations":{"get":{"summary":"List Variables","description":"Retrieve a list of personalization variables","operationId":"list-variables","x-canonical-resource":"personalizations","parameters":[{"name":"orders[format]","in":"query","description":"Order variables by format (ASC/DESC)","schema":{"type":"string"}},{"name":"orders[tag]","in":"query","description":"Order variables by tag (ASC/DESC)","schema":{"type":"string"}},{"name":"orders[name]","in":"query","description":"Order variables by name (ASC/DESC)","schema":{"type":"string"}},{"name":"orders[content]","in":"query","description":"Order variables by content (ASC/DESC)","schema":{"type":"string"}},{"name":"filter[name]","in":"query","description":"Filter by variable name","schema":{"type":"string"}},{"name":"filter[tag]","in":"query","description":"Filter by variable tag","schema":{"type":"string"}},{"name":"filter[listName]","in":"query","description":"Filter by name of list","schema":{"type":"string"}},{"name":"filter[content]","in":"query","description":"Contents of variable","schema":{"type":"string"}},{"name":"filter[format]","in":"query","description":"Filter by tag format (html, text)","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Result limit (Default: 20)","schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":{"personalizations":[{"name":"address","tag":"awesometag","format":"html","content":"this is the first content","listIds":"1,2,3","listNames":"List1,List2,List3","listsCount":"3","isLocked":false,"links":[],"id":"1"},{"name":"phone","tag":"greattag","format":"html","content":"this is the second one","listIds":"3,4","listNames":"List3,List4","listsCount":"2","isLocked":false,"links":[],"id":"2"},{"name":"signature","tag":"hellotag","format":"text","content":"this is the third one","listIds":"1,3","listNames":"List1,List3","listsCount":"2","isLocked":false,"links":[],"id":"3"},{"name":"hahah","tag":"goodtag","format":"html","content":"fourth","listIds":"1,4","listNames":"List1,List4","listsCount":"2","isLocked":false,"links":[],"id":"4"},{"name":"hello world","tag":"nicetag","format":"text","content":"fifth","listIds":"2,3,4","listNames":"List2,List3,List4","listsCount":"3","isLocked":true,"links":[],"id":"5"}],"meta":{"total":"5"}}}},"schema":{"type":"object","properties":{"personalizations":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"address"},"tag":{"type":"string","example":"awesometag"},"format":{"type":"string","example":"html"},"content":{"type":"string","example":"this is the first content"},"listIds":{"type":"string","example":"1,2,3"},"listNames":{"type":"string","example":"List1,List2,List3"},"links":{"type":"array"},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"5"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"post":{"summary":"Create a Variable","description":"Create a personalization variable","operationId":"create-variable","x-canonical-resource":"personalizations","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"personalization":{"properties":{"tag":{"type":"string","description":"tag name"},"name":{"type":"string","description":"Tag name"},"format":{"type":"string","description":"\"html\" or \"text\""},"content":{"type":"string","description":"Personalization/Variable contents"},"listids":{"type":"string","description":"Comma-separated list of list ids (string), ie: \"2,3,4,5\""},"isLocked":{"type":"boolean","description":"Must be false or left out; true is refused with 403."}},"required":[],"type":"object"}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":{"personalization":{"tag":"brand-new-tag","name":"brand new name","format":"text","content":"Hello World!","listids":"2,3,4,5","userid":"1","isLocked":false,"links":[],"id":"8"}}}},"schema":{"type":"object","properties":{"personalization":{"type":"object","properties":{"tag":{"type":"string","example":"brand-new-tag"},"name":{"type":"string","example":"brand new name"},"format":{"type":"string","example":"text"},"content":{"type":"string","example":"Hello World!"},"listids":{"type":"string","example":"2,3,4,5"},"userid":{"type":"string","example":"1"},"links":{"type":"array"},"id":{"type":"string","example":"8"}}}}}}}}},"deprecated":false}},"/personalizations/bulkdelete":{"delete":{"summary":"Bulk Delete Variables","description":"Bulk delete personalization variables","operationId":"bulk-delete-variables","x-canonical-resource":"personalizations","x-destructive":true,"x-bulk-operation":true,"parameters":[{"name":"ids","in":"query","description":"List of variables to be deleted, ie: 1,2,3","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"text/plain":{"examples":{"Result":{"value":"Delete successful"}}}}}},"deprecated":false}},"/personalizations/{variableId}":{"get":{"summary":"Retrieve a Variable","description":"Retrieve an individual personalization variable","operationId":"retrieve-variable","x-canonical-resource":"personalizations","parameters":[{"name":"variableId","in":"path","description":"ID (int) of variable","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":{"personalization":{"name":"brand new name","tag":"brand-new-tag","format":"text","content":"Hello World!","listIds":"2,3,5,4","listNames":"Another List,League Players,real,Test Segmentation","listsCount":"4","isLocked":false,"links":[],"id":"8"}}}},"schema":{"type":"object","properties":{"personalization":{"type":"object","properties":{"name":{"type":"string","example":"brand new name"},"tag":{"type":"string","example":"brand-new-tag"},"format":{"type":"string","example":"text"},"content":{"type":"string","example":"Hello World!"},"listIds":{"type":"string","example":"2,3,5,4"},"listNames":{"type":"string","example":"Another List,League Players,real,Test Segmentation"},"listsCount":{"type":"string","example":"4"},"links":{"type":"array"},"id":{"type":"string","example":"8"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Personalization with id 22\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Personalization with id 22"}}}}}}},"deprecated":false},"put":{"summary":"Edit a Variable","description":"Edit a personalization variable","operationId":"edit-variable","x-canonical-resource":"personalizations","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"variableId","in":"path","description":"ID (int) of personalization/variable","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"personalization":{"properties":{"tag":{"type":"string","description":"tag name"},"name":{"type":"string","description":"Tag name"},"format":{"type":"string","description":"\"html\" or \"text\""},"content":{"type":"string","description":"Personalization/Variable contents"},"listids":{"type":"string","description":"Comma-separated list of list ids (string), ie: \"2,3,4,5\""},"isLocked":{"type":"boolean","description":"Send false to unlock a locked variable (admins only). Any other value is ignored."}},"required":[],"type":"object"}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":{"personalization":{"userid":"1","tag":"brand-new-tag","name":"changed name","content":"Hello World!","format":"text","created_timestamp":"2024-08-14 12:31:35","updated_timestamp":"2024-08-14 12:31:35","created_by":null,"updated_by":null,"isLocked":false,"listids":"2,3,4,5","links":[],"id":"8"}}}},"schema":{"type":"object","properties":{"personalization":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"tag":{"type":"string","example":"brand-new-tag"},"name":{"type":"string","example":"changed name"},"content":{"type":"string","example":"Hello World!"},"format":{"type":"string","example":"text"},"created_timestamp":{"type":"string","example":"2024-08-14 12:31:35"},"updated_timestamp":{"type":"string","example":"2024-08-14 12:31:35"},"created_by":{},"updated_by":{},"listids":{"type":"string","example":"2,3,4,5"},"links":{"type":"array"},"id":{"type":"string","example":"8"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for ActiveCampaign\\\\Hosted\\\\Personalization\\\\Personalization with id 22\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for ActiveCampaign\\Hosted\\Personalization\\Personalization with id 22"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a Variable","description":"Delete a personalization variable","operationId":"delete-variable","x-canonical-resource":"personalizations","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"variableId","in":"path","description":"ID (int) of personalization/variable","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Personalization with id 22\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Personalization with id 22"}}}}}}},"deprecated":false}},"/personalizations/{variableId}/lock":{"patch":{"description":"","operationId":"get_{personalizationId}lock","x-canonical-resource":"personalizations","x-destructive":true,"x-bulk-operation":false,"responses":{"200":{"description":"The personalization was locked (or was already locked).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":""},"message":{"type":"string"}}},"examples":{"Success":{"summary":"Success","value":{"success":true,"message":"Personalization updated successfully"}}}}}},"403":{"description":"The authenticated user is not an admin. Only admins can lock a personalization.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"No rights to lock (not an admin)":{"summary":"No rights to lock (not an admin)","value":{"success":false,"message":"Only admin can lock/unlock personalizations"}}}}}},"404":{"description":"No personalization exists with this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"Not found":{"summary":"Not found","value":{"success":false,"message":"Personalization not found"}}}}}},"500":{"description":"The personalization could not be saved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"Not updated":{"summary":"Not updated","value":{"success":false,"message":"Personalization was not updated"}}}}}}},"parameters":[{"in":"path","name":"variableId","schema":{"type":"string"},"required":true}]}},"/personalizations/{variableId}/unlock":{"patch":{"description":"","operationId":"patch_new-endpoint","x-canonical-resource":"personalizations","x-destructive":true,"x-bulk-operation":false,"responses":{"200":{"description":"The personalization was unlocked (or was already unlocked).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"Success":{"summary":"Success","value":{"success":true,"message":"Personalization updated successfully"}}}}}},"403":{"description":"The authenticated user is not an admin. Only admins can unlock a personalization.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"No rights to unlock (not an admin)":{"summary":"No rights to unlock (not an admin)","value":{"success":false,"message":"Only admin can lock/unlock personalizations"}}}}}},"404":{"description":"No personalization exists with this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"Not found":{"summary":"Not found","value":{"success":false,"message":"Personalization not found"}}}}}},"500":{"description":"The personalization could not be saved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"examples":{"Not updated":{"summary":"Not updated","value":{"success":false,"message":"Personalization was not updated"}}}}}}},"parameters":[{"in":"path","name":"variableId","schema":{"type":"string"},"required":true}]}},"/platform/maintenance":{"get":{"summary":"Check whether the account is ready for maintenance","description":"Runs the maintenance readiness checks against the account's database (reader connection) and reports each outcome: whether campaigns are due to send soon and whether campaign, import, export or bulk-edit processes are still running. Read `globalStatus` to decide; the HTTP status does not change with the outcome. Internal: platform maintenance tooling.","operationId":"retrieve-platform-maintenance-status","responses":{"200":{"description":"The check results. Returned whether or not the checks pass: the controller's failure status is configured as 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformMaintenanceReport"},"example":{"checks":[{"checkName":"pending_campaigns","message":"Query passed: 0 returned","status":0,"status_name":"check_result_ok","service_id":0,"duration":0.0123},{"checkName":"running_processes","message":"Query failed: 2 returned","status":3,"status_name":"check_result_critical","service_id":1,"duration":0.0087}],"globalStatus":false}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/plusAppend/verify_image_url":{"post":{"summary":"Re-check a contact's photo URL (internal)","description":"Checks whether the stored imageUrl of a social profile record still loads. If the URL does not answer, or answers with an error status, imageUrl is cleared and the record is saved. Used by the app when a contact photo fails to load. Send id as a query parameter or a form field, not in a JSON body. Any method other than POST returns 405 with an empty body. No permission beyond API access is checked.","operationId":"verify-a-plus-append-image-url","x-canonical-resource":"contact","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"query","description":"ID of the social profile record (from GET /plusAppends), not the contact ID.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record after the check, with imageUrl cleared if the URL did not load.","content":{"application/json":{"schema":{"type":"object","properties":{"plusAppend":{"type":"object","description":"The record, with the same fields as GET /plusAppends/{id}."}}}}}},"404":{"description":"No record has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"\"No Result found for PlusAppend with id\" followed by the ID as a whole number.","example":"No Result found for PlusAppend with id 2"}}}}}},"405":{"description":"The method was not POST. The body is empty."},"422":{"description":"id was not sent or is 0.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the error.","items":{"type":"object","properties":{"status":{"type":"string","description":"HTTP status code, as a string.","example":"422"},"detail":{"type":"string","description":"Says that id is required, in the API user's language.","example":"\"id\" is a required parameter."}}}}}}}}}}}},"/plusAppends":{"get":{"summary":"List contact social profile records","description":"Lists the social profile and enrichment records of contacts, 20 per page by default and at most 100 per page (limit). Send contact to get one contact's record, or use GET /contacts/{id}/plusAppend. Other filters and orders are ignored, and the order of the records is not guaranteed. No permission beyond API access is checked. A normal contact delete keeps the record, so the list can include records of contacts that no longer exist.","operationId":"list-all-plus-appends","x-canonical-resource":"contact","parameters":[{"name":"contact","in":"query","description":"Only the record of this contact. Ignored when 0 or missing.","schema":{"type":"integer"}},{"name":"ids","in":"query","description":"Comma-separated record IDs to return. Overrides limit; offset still applies.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of records per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of records to skip. Default 0.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The records on this page.","content":{"application/json":{"schema":{"type":"object","properties":{"plusAppends":{"type":"array","description":"The records.","items":{"$ref":"#/components/schemas/PlusAppend"}},"meta":{"type":"object","description":"Paging information.","properties":{"total":{"type":"integer","description":"Number of matching records, ignoring limit and offset.","example":1}}}}},"examples":{"Result":{"value":"{\n    \"plusAppends\": [\n        {\n            \"contact\": \"3\",\n            \"imageUrl\": \"https://example.com/avatars/sam.png\",\n            \"membershipsFacebook\": \"\",\n            \"membershipsTwitter\": \"https://x.com/samexample\",\n            \"membershipsLinkedin\": \"\",\n            \"firstName\": \"\",\n            \"lastName\": \"\",\n            \"name\": \"\",\n            \"company\": \"\",\n            \"title\": \"\",\n            \"location\": \"\",\n            \"last_updated_fullcontact\": \"2026-09-18T10:52:26-05:00\",\n            \"last_updated_rapleaf\": null,\n            \"last_updated_fliptop\": null,\n            \"links\": {\n                \"contact\": \"https://:account.api-us1.com/api/3/plusAppends/2/contact\"\n            },\n            \"id\": \"2\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 1\n    }\n}"}}}}}}},"post":{"summary":"Create a contact social profile record","description":"Creates the social profile record of a contact. This is an internal operation. A contact can have only one record. The contact is not checked to exist. last_updated_fullcontact is set to the time of the request. The response has only the fields that were sent, plus last_updated_fullcontact, links and id. No permission beyond API access is checked. Without the plusAppend object nothing is set, so a create makes an empty record with no contact. Only one record can have no contact; a second one fails with 422.","operationId":"create-a-plus-append","x-canonical-resource":"contact","x-internal":true,"x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plusAppend"],"properties":{"plusAppend":{"$ref":"#/components/schemas/PlusAppendWrite"}}},"examples":{"Request Example":{"value":{"plusAppend":{"contact":3,"membershipsTwitter":"https://x.com/samexample"}}}}}}},"responses":{"201":{"description":"The record was created.","content":{"application/json":{"schema":{"type":"object","properties":{"plusAppend":{"$ref":"#/components/schemas/PlusAppendSaved"}}},"examples":{"Result":{"value":"{\n    \"plusAppend\": {\n        \"contact\": 3,\n        \"membershipsTwitter\": \"https://x.com/samexample\",\n        \"last_updated_fullcontact\": \"2026-10-16T09:30:00-05:00\",\n        \"links\": {\n            \"contact\": \"https://:account.api-us1.com/api/3/plusAppends/2/contact\"\n        },\n        \"id\": \"2\"\n    }\n}"}}}}},"400":{"description":"The body is a JSON list or a single JSON value, not an object. An empty list, 0, false and an empty string count as an empty body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendBodyNotObjectError"}}}},"422":{"description":"The contact already has a record. A contact can have only one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendDuplicateError"}}}},"500":{"description":"The save failed, for example because the body has a key that is not a field of the record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendSaveError"}}}}}}},"/plusAppends/{id}":{"get":{"summary":"Retrieve a contact social profile record","description":"Returns one social profile and enrichment record by its ID. No permission beyond API access is checked.","operationId":"retrieve-a-plus-append","x-canonical-resource":"contact","parameters":[{"name":"id","in":"path","description":"ID of the record.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"type":"object","properties":{"plusAppend":{"$ref":"#/components/schemas/PlusAppend"}}}}}},"404":{"description":"No record has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendNotFoundError"}}}}}},"put":{"summary":"Update a contact social profile record","description":"Changes a social profile record. Fields left out keep their value. PATCH /plusAppends/{id} does the same thing. This is an internal operation. last_updated_fullcontact is set to the time of the request. The response is the whole record, with the sent values in place. No permission beyond API access is checked. Without the plusAppend object nothing is set, and only last_updated_fullcontact changes.","operationId":"update-a-plus-append","x-canonical-resource":"contact","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the record to change.","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plusAppend"],"properties":{"plusAppend":{"$ref":"#/components/schemas/PlusAppendWrite"}}}}}},"responses":{"200":{"description":"The record was changed.","content":{"application/json":{"schema":{"type":"object","properties":{"plusAppend":{"$ref":"#/components/schemas/PlusAppendSaved"}}}}}},"400":{"description":"The body is a JSON list or a single JSON value, not an object. An empty list, 0, false and an empty string count as an empty body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendBodyNotObjectError"}}}},"404":{"description":"No record has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendNotFoundError"}}}},"422":{"description":"Another record already belongs to the contact sent. A contact can have only one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendDuplicateError"}}}},"500":{"description":"The save failed, for example because the body has a key that is not a field of the record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendSaveError"}}}}}},"delete":{"summary":"Delete a contact social profile record","description":"Deletes a social profile record. The contact is not changed. This is an internal operation. No permission beyond API access is checked.","operationId":"delete-a-plus-append","x-canonical-resource":"contact","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the record to delete.","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"The record was deleted. The body is an empty object.","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"The delete failed in the database. The body is a plain sentence, not JSON, such as \"Failed to delete plusAppend\"."},"404":{"description":"No record has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusAppendNotFoundError"}}}}}}},"/postmark/authcode":{"post":{"summary":"Exchange a Postmark authorization code","description":"Internal: the last step of connecting Postmark through OAuth, called by the app's Postmark OAuth page, not meant for direct use. Exchanges the authorization code at Postmark's token endpoint and stores the access token as the account's Postmark credential, replacing any stored one. Legacy endpoint; its method guard accepts only POST.","operationId":"exchange-postmark-auth-code","x-canonical-resource":"postmark","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"auth_code","in":"query","required":true,"description":"The authorization code Postmark returned to the OAuth redirect. A form-encoded body field of the same name is read when the query has none.","schema":{"type":"string"}}],"responses":{"200":{"description":"The token was stored. The body is empty."},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header."},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/config":{"get":{"summary":"Retrieve the Postmark OAuth configuration","description":"Internal: backs the app's Postmark integration, not meant for direct use. Returns what the app needs to start Postmark's OAuth flow and whether the account is connected. When a token is stored, it is checked against Postmark; a token Postmark rejects with 401 is deleted and `isConnected` is false. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"get-postmark-config","x-canonical-resource":"postmark","responses":{"200":{"description":"The configuration.","content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","description":"ActiveCampaign's OAuth client ID at Postmark."},"authEndpoint":{"type":"string","description":"Postmark's authorization endpoint."},"tokenEndpoint":{"type":"string","description":"Postmark's token endpoint."},"redirectUri":{"type":"string","description":"The OAuth redirect URI registered for ActiveCampaign."},"isConnected":{"type":"boolean","description":"Whether a stored token exists and Postmark accepts it."}}}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/message/{messageId}/server/{serverId}":{"get":{"summary":"Retrieve a Postmark message's subject","description":"Internal: backs the app's Postmark integration, not meant for direct use. Reads an outbound message's details from Postmark and returns only its subject. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"get-postmark-message-subject","x-canonical-resource":"postmark","parameters":[{"name":"messageId","in":"path","required":true,"description":"ID of the outbound message at Postmark.","schema":{"type":"string"}},{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The subject.","content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"string","description":"Subject of the message."}}}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark has no such message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/servers":{"get":{"summary":"List Postmark servers","description":"Internal: backs the app's Postmark integration, not meant for direct use. Lists the servers of the connected Postmark account whose delivery type is `Live`, from the first 500. Server API tokens are cached for later calls and never returned. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"list-postmark-servers","x-canonical-resource":"postmark","responses":{"200":{"description":"The servers: an array, or `{}` when there is none.","content":{"application/json":{"schema":{"type":["array","object"],"items":{"$ref":"#/components/schemas/PostmarkIdName"},"description":"The servers."}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/servers/{serverId}/streams":{"get":{"summary":"List a Postmark server's transactional streams","description":"Internal: backs the app's Postmark integration, not meant for direct use. Lists the server's transactional message streams, archived streams excluded. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"list-postmark-message-streams","x-canonical-resource":"postmark","parameters":[{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The streams: an array, or `{}` when there is none.","content":{"application/json":{"schema":{"type":["array","object"],"description":"The streams.","items":{"type":"object","properties":{"id":{"type":"string","description":"The stream ID."},"name":{"type":"string","description":"The stream name."}}}}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/servers/{serverId}/streams/{streamId}/tags":{"get":{"summary":"List a Postmark stream's tags","description":"Internal: backs the app's Postmark integration, not meant for direct use. Lists up to 150 tags used on the stream's outbound messages, as Postmark's outbound statistics report them. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"list-postmark-stream-tags","x-canonical-resource":"postmark","parameters":[{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}},{"name":"streamId","in":"path","required":true,"description":"ID of the Postmark message stream.","schema":{"type":"string"}}],"responses":{"200":{"description":"Postmark's `Tags` list, passed through: an array, or `{}` when it is empty.","content":{"application/json":{"schema":{"type":["array","object"],"description":"The tags.","items":{"description":"A tag entry as Postmark returns it."}}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/postmark/webhooks/server/{serverId}":{"post":{"summary":"Create a Postmark webhook","description":"Internal: backs the app's Postmark integration, not meant for direct use. Creates a webhook on the server that calls ActiveCampaign, adding an `ac_accountid` header with the account ID. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"create-postmark-webhook","x-canonical-resource":"postmark","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PostmarkWebhook"},{"type":"object","required":["HttpHeaders"]}],"description":"A Postmark webhook definition, sent to Postmark after ActiveCampaign overwrites `Url`, `Integration`, `IntegrationDescription` and `HttpAuth` with its own values. `HttpHeaders` must be an array; `ac_accountid` is appended to it."}}}},"responses":{"201":{"description":"Postmark's copy of the created webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"400":{"description":"Postmark refused the webhook. The body echoes the webhook as it was to be sent, credentials included.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"405":{"description":"The file routes this path for another verb."},"500":{"description":"The server is unknown, `HttpHeaders` is not an array, or another failure. The API's generic handler answers with a fixed message."}},"deprecated":false,"x-internal":true}},"/postmark/webhooks/server/{serverId}/stream/{streamId}/action/{actionType}":{"get":{"summary":"Find the Postmark webhook for a trigger or action type","description":"Internal: backs the app's Postmark integration, not meant for direct use. Finds the ActiveCampaign webhook on the stream that carries an `X-Ref-<actionType>-Cnt` header. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"get-postmark-webhook-for-action","x-canonical-resource":"postmark","parameters":[{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}},{"name":"streamId","in":"path","required":true,"description":"ID of the Postmark message stream.","schema":{"type":"string"}},{"name":"actionType","in":"path","required":true,"description":"The automation trigger or action type the webhook serves.","schema":{"type":"string"}}],"responses":{"200":{"description":"The webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"No webhook on the stream carries the header; the body is `{}`.","content":{"application/json":{"schema":{"type":"object","maxProperties":0}}}},"500":{"description":"The server is unknown, or another failure. The API's generic handler answers with a fixed message."}},"deprecated":false,"x-internal":true}},"/postmark/webhooks/{webhookId}/server/{serverId}":{"get":{"summary":"Retrieve a Postmark webhook","description":"Internal: backs the app's Postmark integration, not meant for direct use. Returns one ActiveCampaign webhook of the server. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"get-postmark-webhook","x-canonical-resource":"postmark","parameters":[{"name":"webhookId","in":"path","required":true,"description":"ID of the Postmark webhook.","schema":{"type":"integer"}},{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"The server is unknown, or another failure. The API's generic handler answers with a fixed message."}},"deprecated":false,"x-internal":true},"put":{"summary":"Update a Postmark webhook","description":"Internal: backs the app's Postmark integration, not meant for direct use. Replaces the webhook at Postmark with the body. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"update-postmark-webhook","x-canonical-resource":"postmark","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"webhookId","in":"path","required":true,"description":"ID of the Postmark webhook.","schema":{"type":"integer"}},{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook","description":"A Postmark webhook definition, sent to Postmark after ActiveCampaign overwrites `Url`, `Integration`, `IntegrationDescription` and `HttpAuth` with its own values."}}}},"responses":{"200":{"description":"Postmark's copy of the updated webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"400":{"description":"Postmark refused the update or the server is unknown. The body echoes the webhook as it was to be sent, credentials included.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkWebhook"}}}},"405":{"description":"The file routes this path for another verb."},"500":{"description":"The body is not a JSON object, or another failure. The API's generic handler answers with a fixed message."}},"deprecated":false,"x-internal":true}},"/postmark/webhooks/{webhookId}/server/{serverId}/action/{triggerType}":{"delete":{"summary":"Release a Postmark webhook for a trigger or action type","description":"Internal: backs the app's Postmark integration, not meant for direct use. Called when an automation stops using the webhook. Decrements the webhook's `X-Ref-<triggerType>-Cnt` header, dropping it at zero, and saves the webhook; when no `X-Ref-` header is left, deletes the webhook at Postmark instead. Served by api/3/postmark.php, which routes on its own: a path or verb it does not list answers 403 or 405. Postmark rejecting the stored credentials (401 or 403) answers 403, a Postmark 404 answers 404 and a Postmark 409 answers 409.","operationId":"remove-postmark-webhook-trigger","x-canonical-resource":"postmark","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"webhookId","in":"path","required":true,"description":"ID of the Postmark webhook.","schema":{"type":"integer"}},{"name":"serverId","in":"path","required":true,"description":"ID of the Postmark server.","schema":{"type":"integer"}},{"name":"triggerType","in":"path","required":true,"description":"The automation trigger or action type that no longer uses the webhook.","schema":{"type":"string"}}],"responses":{"200":{"description":"Postmark's copy of the saved webhook, or `{}` when the webhook was deleted.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/PostmarkWebhook"},{"type":"object","maxProperties":0,"description":"The webhook was deleted."}]}}}},"403":{"description":"Postmark rejected the stored credentials, the account has not connected Postmark, or the path is not one the file routes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"404":{"description":"Postmark answered 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmarkHttpError"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/preferenceCenterData":{"get":{"summary":"List email lists for a Preference Center","description":"Lists the account's email lists with their website URL, permission reminder and contact counts, in pages of 20 by default, by ascending ID. Only lists on the email channel are returned. Pass lists[] to read particular lists, and filters[name] to match on the list name. No permission beyond being signed in is checked. The body is JSON. Internal: backs the Preference Center form builder, which checks which of a form's lists still exist.","operationId":"list-preference-center-lists","parameters":[{"name":"lists[]","in":"query","description":"Return only these lists: repeat the parameter once per list ID. Every value must be an integer list ID.","required":false,"schema":{"type":"array","items":{"type":"integer"}},"example":[3,5]},{"name":"filters[name]","in":"query","description":"Return only lists whose name contains this text","required":false,"schema":{"type":"string"},"example":"news"},{"name":"limit","in":"query","description":"Number of lists to return, 20 when left out and at most 100","required":false,"schema":{"type":"integer","default":20},"example":20},{"name":"offset","in":"query","description":"Number of lists to skip before the first one returned","required":false,"schema":{"type":"integer","default":0},"example":0}],"responses":{"200":{"description":"A page of lists. lists is an empty array when none match.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferenceCentersListData"},"example":{"lists":[{"id":3,"name":"Newsletter","url":"https://www.example.com","description":"You signed up for our newsletter on our website.","subscriber_count":120,"total_contacts":134}],"meta":{"total":1}}}}}},"x-canonical-resource":"lists","x-internal":true}},"/prism/code":{"get":{"summary":"Retrieve Prism embed code","description":"Internal: returns the account's Prism (site tracking) script wrapped in a `<script>` tag, for the app's site-tracking settings page. The public equivalent is GET /siteTracking/code. Legacy endpoint with no method guard.","operationId":"retrieve-prism-embed-code","x-canonical-resource":"siteTracking","responses":{"200":{"description":"HTML `<script>` snippet","content":{"text/html":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/prism/urlWhitelistings":{"post":{"summary":"Add domain to whitelist","description":"Add a domain to the site tracking whitelist","operationId":"add-domain-to-whitelist","x-canonical-resource":"siteTrackingDomains","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"properties":{"attributes":{"type":"object","description":"","properties":{"whitelisted_domain":{"type":"string","default":"example.com","description":"The domain name to add to the whitelist"},"whitelisted_page":{"type":"string","default":"*","description":"The page to while list under the domain. `*` means all pages should be whitelisted. If only example.com/website needs to whitelisted, then the value should be `website`."},"conversations_enabled":{"type":"boolean","default":false,"description":"Whether to enable conversations"},"wp_enabled":{"type":"boolean","default":false,"description":"Whether to enable web personalization"},"tracking_enabled":{"type":"boolean","description":"Whether to enable site tracking","default":true}},"required":["whitelisted_domain","whitelisted_page","conversations_enabled","wp_enabled","tracking_enabled"]},"type":{"type":"string","default":"urlWhitelistings"}},"required":["attributes","type"],"type":"object"}},"required":["data"]},"examples":{"Request Example":{"value":{"data":{"type":"urlWhitelistings","attributes":{"whitelisted_domain":"example.com","whitelisted_page":"*","tracking_enabled":true,"conversations_enabled":false,"wp_enabled":false}}}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"examples":{"Result":{"value":{"data":{"type":"urlWhitelistings","id":"534756","attributes":{"whitelisted_domain":"example.com","whitelisted_page":"*","tracking_enabled":true,"conversations_enabled":false,"wp_enabled":false,"url_regex":"#^example\\.com(\\/.*)?$#","updated_at":"2025-07-29T05:40:11Z","created_at":"2025-07-29T05:40:11Z"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Bad Request":{"value":"{}","summary":"Bad Request"}},"schema":{"type":"object","properties":{}}}}},"409":{"description":"Conflict","content":{"application/json":{"examples":{"Conflict":{"value":"{}","summary":"Conflict"}}}}}},"deprecated":false},"get":{"summary":"List all whitelisted domains","description":"List of all whitelisted site tracking domains","operationId":"list-all-whitelisted-domains","x-canonical-resource":"siteTrackingDomains","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"OK":{"value":{"data":[{"type":"urlWhitelistings","id":"490469","attributes":{"whitelisted_domain":"example.com","whitelisted_page":"*","url_regex":"#^example\\.com(\\/.*)?$#","conversations_enabled":0,"tracking_enabled":1,"created_at":"2024-01-03T17:19:36Z","updated_at":"2025-04-24T19:11:32Z","wp_enabled":0}}]},"summary":"OK"}},"schema":{"type":"object","properties":{"siteTrackingDomains":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"example.com"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":1,"default":0}}}}}}}}},"deprecated":false}},"/prism/urlWhitelistings/{domainId}":{"delete":{"summary":"Remove domain from whitelist","description":"Remove a domain from the site tracking whitelist","operationId":"remove-domain-from-whitelist","x-canonical-resource":"siteTrackingDomains","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"domainId","in":"path","required":true,"description":"The id of the whitelisted domain. Can be retrieved using the GET /prism/urlWhitelistings endpoint","schema":{"type":"string","default":""}}],"responses":{"204":{"description":"204","content":{"application/json":{"examples":{"Result":{"value":""},"No Content":{"value":"{}","summary":"No Content"}}}}}},"deprecated":false}},"/pushUnregister":{"put":{"summary":"Unregister a device from push notifications","description":"Publishes an unregister-device command for the device token to the mobile push service, on the Kafka topic mobile.command.push-unregister-device.0. The service, not this endpoint, removes the registration, and does so after the call returns: 201 means the command was published, not that the device was registered. PUT /pushUnregister/{id} and PATCH /pushUnregister/{id} do the same and ignore the id. Internal: used by the mobile app to stop push notifications to a device.","operationId":"unregister-a-mobile-push-device","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterRequest"}}}},"responses":{"201":{"description":"The unregister command was published. The body is empty."},"400":{"description":"The body is not a JSON object."},"422":{"description":"The command could not be published: Kafka or the schema registry failed, or the body did not encode against the message schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterErrorResponse"}}}}},"x-canonical-resource":"push_registration","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/pushUnregister/{id}":{"put":{"summary":"Unregister a device from push notifications (with an unused id)","description":"Publishes an unregister-device command for the device token to the mobile push service, on the Kafka topic mobile.command.push-unregister-device.0. The service, not this endpoint, removes the registration, and does so after the call returns: 201 means the command was published, not that the device was registered. The id in the path is not read; this is PUT /pushUnregister with an extra path segment. Internal: used by the mobile app to stop push notifications to a device.","operationId":"unregister-a-mobile-push-device-by-id","parameters":[{"name":"id","in":"path","description":"Not read: any value is accepted and the device is named by push_token alone.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterRequest"}}}},"responses":{"201":{"description":"The unregister command was published. The body is empty."},"400":{"description":"The body is not a JSON object."},"422":{"description":"The command could not be published: Kafka or the schema registry failed, or the body did not encode against the message schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterErrorResponse"}}}}},"x-canonical-resource":"push_registration","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"patch":{"summary":"Unregister a device from push notifications (PATCH)","description":"Publishes an unregister-device command for the device token to the mobile push service, on the Kafka topic mobile.command.push-unregister-device.0. The service, not this endpoint, removes the registration, and does so after the call returns: 201 means the command was published, not that the device was registered. The id in the path is not read; this is PUT /pushUnregister with another verb and an extra path segment. Internal: used by the mobile app to stop push notifications to a device.","operationId":"patch-unregister-a-mobile-push-device","parameters":[{"name":"id","in":"path","description":"Not read: any value is accepted and the device is named by push_token alone.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterRequest"}}}},"responses":{"201":{"description":"The unregister command was published. The body is empty."},"400":{"description":"The body is not a JSON object."},"422":{"description":"The command could not be published: Kafka or the schema registry failed, or the body did not encode against the message schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnregisterErrorResponse"}}}}},"x-canonical-resource":"push_registration","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/salesforce/auth":{"post":{"summary":"Connect a Salesforce org","description":"Internal: part of connecting the ActiveCampaign Salesforce managed package to an account, not meant for direct use. Validates that the five required fields are present, forwards the whole request body to DeepData as the org's Salesforce credentials, then creates or updates the account's single Salesforce connection (external ID `orgId`, name `<namespace>.<orgInstance>`, both prefixed with `sandbox.` for a sandbox org, disconnect date cleared) and creates or updates the DeepData webhook for the `subscribe`, `unsubscribe`, `update` and `bounce` events. The router accepts only POST and DELETE on this path.","operationId":"connect-salesforce-org","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SalesforceConnectionParameters"},{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string","description":"Salesforce OAuth refresh token DeepData uses to call the org."}}}],"description":"Only the five listed fields are validated, but the raw body is forwarded to DeepData unchanged."}}}},"responses":{"201":{"description":"Connected.","content":{"application/json":{"schema":{"type":"object","properties":{"salesforceAuth":{"description":"DeepData's response to the connection request, decoded and passed through."},"account_id":{"type":["integer","string"],"description":"ID of the ActiveCampaign account that was connected."}}}}}},"405":{"description":"The request used a verb other than POST or DELETE. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"A required field is missing, or DeepData answered with a status other than 201 (its body is returned in `errors`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceRequiredFieldErrors"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true},"delete":{"summary":"Disconnect a Salesforce org","description":"Internal: called when the ActiveCampaign Salesforce managed package is uninstalled, by the package or by DeepData, not meant for direct use. Unless `isDeepdata` is set, first asks DeepData to delete its side of the connection. Then sets the disconnect date on the Salesforce connection matching the org (nothing happens when none matches) and deletes the DeepData webhook when the account has no Shopify integration, the other user of that webhook. The router accepts only POST and DELETE on this path.","operationId":"disconnect-salesforce-org","x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"isDeepdata","in":"query","required":false,"description":"Set when DeepData itself sends the request, so the endpoint does not call DeepData back. Any non-empty value other than `0` counts as set.","schema":{"type":"string"},"example":"1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceConnectionParameters"}}}},"responses":{"200":{"description":"Disconnected, or no matching connection existed.","content":{"application/json":{"schema":{"type":"array","maxItems":0,"description":"Always an empty JSON array: the success body carries no data.","items":{"description":"Never present."}}}}},"405":{"description":"The request used a verb other than POST or DELETE. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"A required field is missing, or DeepData answered with a status other than 200 (its body is returned in `errors`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceRequiredFieldErrors"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/salesforce/contactFieldData":{"post":{"summary":"Look up contact field values for Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package to read the current values of mapped fields for a batch of contacts, not meant for direct use. Reads only; POST because the lookup is sent as a body. Contacts are matched by ID, email or phone (any match), at most 1000 are returned, and lookups that matched no contact are listed separately. Legacy endpoint; its method guard accepts only POST.","operationId":"list-salesforce-contact-field-data","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"At least one of `idLookups`, `emailLookups` and `phoneLookups` must be non-empty.","properties":{"mappings":{"type":"array","description":"Fields to return. `first_name`, `last_name`, `email`, `phone` and `id` are contact fields, `orgname` is the contact's account name, and any other entry is read as a contact custom field ID. `id`, `email` and `phone` are always returned.","items":{"type":"string","description":"A contact field name or custom field ID."},"example":["first_name","last_name","orgname","1","2"]},"idLookups":{"type":"array","description":"Contacts to find by ID.","items":{"type":"object","properties":{"acId":{"type":["integer","string"],"description":"The contact ID."},"email":{"type":"string","description":"The contact's email, echoed back in `subscribersNotFound` when the ID matches no contact."}}}},"emailLookups":{"type":"array","description":"Contacts to find by email.","items":{"type":"object","properties":{"email":{"type":"string","description":"The email address."}}}},"phoneLookups":{"type":"array","description":"Contacts to find by phone number.","items":{"type":"object","properties":{"phone":{"type":"string","description":"The phone number, matched exactly."}}}}}}}}},"responses":{"200":{"description":"The matched contacts and the lookups that matched none.","content":{"application/json":{"schema":{"type":"object","properties":{"subscribers":{"type":"array","description":"Matched contacts, ordered by ID. Each carries `id`, `email`, `phone`, the requested contact fields (`orgname` for the account name) and one property per requested custom field, keyed by its ID, for the fields that have a value.","items":{"type":"object","properties":{"id":{"type":"string","description":"The contact ID."},"email":{"type":"string","description":"The contact's email."},"phone":{"type":"string","description":"The contact's phone number."},"first_name":{"type":"string","description":"Present when requested."},"last_name":{"type":"string","description":"Present when requested."},"orgname":{"type":"string","description":"The contact's account name. Present when requested."}},"additionalProperties":{"type":"string","description":"A custom field value, keyed by custom field ID."}}},"subscribersNotFound":{"type":"array","description":"One entry per lookup that matched no contact: `id` and `email` for an ID lookup, an empty `id` with the `email` or `phone` for the others.","items":{"type":"object","properties":{"id":{"type":["integer","string"],"description":"The looked-up ID, or an empty string."},"email":{"type":"string","description":"The looked-up email."},"phone":{"type":"string","description":"The looked-up phone number."}}}}}}}}},"400":{"description":"The body is empty.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Always `Request body is empty`."}}}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"No ID, email or phone lookup was provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}},"500":{"description":"The lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/accountContacts":{"post":{"summary":"List account-contact associations for Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package, not meant for direct use. Reads only; POST because the contact IDs are sent as a body. Returns the associations as a map from account ID to contact IDs, which is cheaper for Salesforce to deserialize. Legacy endpoint; its method guard accepts only POST and PUT.","operationId":"list-salesforce-account-contacts","x-canonical-resource":"accountContacts","x-destructive":false,"x-bulk-operation":true,"parameters":[{"name":"limit","in":"query","required":false,"description":"Number of records to return. Defaults to 100.","schema":{"type":"integer","default":100}},{"name":"offset","in":"query","required":false,"description":"Number of records to skip. Defaults to 0.","schema":{"type":"integer","default":0}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"contactIds":{"type":"array","description":"Contacts whose associations to return. Without it every association is returned, a page at a time.","items":{"type":["integer","string"],"description":"A contact ID."},"example":[1,2,3]}}}}}},"responses":{"200":{"description":"The associations on this page.","content":{"application/json":{"schema":{"type":"object","properties":{"accountContacts":{"type":["object","array"],"description":"Keyed by account ID; an empty array when nothing matched.","additionalProperties":{"type":"object","properties":{"contactIds":{"type":"array","description":"IDs of the contacts associated with the account.","items":{"type":"string","description":"A contact ID."}}}}},"meta":{"$ref":"#/components/schemas/SalesforceSyncAccountMeta"}}}}}},"405":{"description":"The request used a verb other than POST or PUT. The response carries an `Allow` header naming the accepted verbs."},"500":{"description":"The lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Upsert account-contact associations from Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package, not meant for direct use. For each pair, moves the contact's existing account association to the given account or creates one, and updates the contact's account ID and name to match. Pairs that fail validation are reported in `failed`. Legacy endpoint; its method guard accepts only POST and PUT.","operationId":"upsert-salesforce-account-contacts","x-canonical-resource":"accountContacts","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","description":"Contact-account pairs. A contact listed twice keeps the last pair.","items":{"type":"object","required":["contactId","accountId"],"properties":{"contactId":{"type":["integer","string"],"description":"ID of the contact."},"accountId":{"type":["integer","string"],"description":"ID of the account to associate the contact with."}}}}}}},"responses":{"200":{"description":"What was saved and what was not. Each key is present only when it has entries, so the body is `{}` when nothing was processed.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"array","description":"Pairs that were saved.","items":{"type":"object","properties":{"contactId":{"type":["integer","string"],"description":"ID of the contact."},"accountId":{"type":["integer","string"],"description":"ID of the account."}}}},"failed":{"type":"array","description":"Pairs that failed validation or could not be saved.","items":{"type":"object","properties":{"contactId":{"type":["integer","string"],"description":"ID of the contact."},"accountId":{"type":["integer","string"],"description":"ID of the account."},"reason(s)":{"description":"The validation errors, when validation failed."}}}}}}}}},"405":{"description":"The request used a verb other than POST or PUT. The response carries an `Allow` header naming the accepted verbs."},"500":{"description":"The upsert failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/accounts":{"get":{"summary":"List accounts for Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package to pull accounts, not meant for direct use. Each account comes with its custom field values and the IDs of its contacts, ordered by last update, oldest first. Legacy endpoint; its method guard accepts only GET, POST and PUT.","operationId":"list-salesforce-sync-accounts","x-canonical-resource":"crm_account","parameters":[{"name":"limit","in":"query","required":false,"description":"Number of records to return. Defaults to 100.","schema":{"type":"integer","default":100}},{"name":"offset","in":"query","required":false,"description":"Number of records to skip. Defaults to 0.","schema":{"type":"integer","default":0}},{"name":"filters[updated_after]","in":"query","required":false,"description":"Only accounts updated after this time. Any date-time PHP can parse; it is converted to US Central time before comparing.","schema":{"type":"string"},"example":"2020-06-23T14:31:30"},{"name":"filters[accountId]","in":"query","required":false,"description":"Only the account with this ID.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The accounts on this page.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/SalesforceSyncAccount"},"description":"The accounts."},"meta":{"$ref":"#/components/schemas/SalesforceSyncAccountMeta"}}}}}},"405":{"description":"The request used a verb other than GET, POST or PUT. The response carries an `Allow` header naming the accepted verbs."},"500":{"description":"The lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Upsert an account from Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package, not meant for direct use. Updates the account with `account.id`; when that is empty or names no account, updates the account with the same name, and creates one when none has it. Before updating a same-name account with `meta.source` `salesforce`, the Salesforce account ID in the custom field named by `meta.salesforceIdLocation` must match the one already stored there, when one is stored. Missing required account custom fields are filled with their defaults unless `useDefaults` is false. Legacy endpoint; its method guard accepts only GET, POST and PUT.","operationId":"upsert-salesforce-sync-account","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["account"],"properties":{"account":{"type":"object","required":["name"],"properties":{"id":{"type":["integer","string","null"],"description":"ID of the account to update. Empty to match by name or create."},"name":{"type":"string","description":"Name of the account.","example":"Acme Inc"},"accountUrl":{"type":"string","description":"The account's website URL. URL-encoded values are decoded before saving.","example":"https://www.example.com"},"owner":{"type":["integer","string"],"description":"ID of the user who owns the account."},"useDefaults":{"type":"boolean","default":true,"description":"Whether missing required account custom fields are filled with their default values."},"accountCustomFieldData":{"type":"array","description":"Custom field values to save with the account.","items":{"$ref":"#/components/schemas/SalesforceAccountCustomFieldValue"}}}},"meta":{"type":"object","description":"How to recognise the Salesforce account when matching by name.","properties":{"salesforceIdLocation":{"type":["integer","string"],"description":"ID of the account custom field that holds the Salesforce account ID; compared with the `id` of the entries in `accountCustomFieldData`, so send it the same way.","example":"7"},"source":{"type":"string","description":"`salesforce` turns on the Salesforce account ID check when an account is matched by name.","example":"salesforce"}}}}}}}},"responses":{"200":{"description":"The saved account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceSavedAccount"}}}},"403":{"description":"The plan does not include the Accounts feature (`Upgrade your account to enable the Accounts Feature`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}},"404":{"description":"A not-found error escaped the save; the endpoint attributes it to an unmapped field in the payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}},"405":{"description":"The request used a verb other than GET, POST or PUT. The response carries an `Allow` header naming the accepted verbs."},"409":{"description":"An account with this name exists and is already linked to a different Salesforce account ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}},"422":{"description":"The account or its custom field values failed validation, the Salesforce account ID was missing while matching by name with `meta.source` `salesforce`, or the save failed unexpectedly. Validation errors carry `error`, `stackTrace` and `line`; a custom field save failure carries only `error`; an unexpected failure carries `error`, `exceptionType` and `detail` (the exception message with URLs redacted).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"What failed."},"stackTrace":{"type":"string","description":"The PHP stack trace, on validation errors."},"line":{"type":"integer","description":"The source line, on validation errors."},"exceptionType":{"type":"string","description":"Short class name of the exception, on unexpected failures."},"detail":{"type":"string","description":"The exception message with URLs replaced by `[url redacted]`, on unexpected failures."}}}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update an account from Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package, not meant for direct use. Updates the account with `account.id` and creates or updates the custom field values sent with it; it never creates an account. Legacy endpoint; its method guard accepts only GET, POST and PUT.","operationId":"update-salesforce-sync-account","x-canonical-resource":"crm_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["account"],"properties":{"account":{"type":"object","required":["id","accountCustomFieldData"],"properties":{"id":{"type":["integer","string"],"description":"ID of the account to update."},"name":{"type":"string","description":"Name of the account. Must stay unique."},"accountUrl":{"type":"string","description":"The account's website URL. URL-encoded values are decoded before saving."},"owner":{"type":["integer","string"],"description":"ID of the user who owns the account."},"accountCustomFieldData":{"type":"array","description":"Custom field values to create or update. Send an empty array when there are none.","items":{"$ref":"#/components/schemas/SalesforceAccountCustomFieldValue"}}}}}}}}},"responses":{"200":{"description":"The updated account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceSavedAccount"}}}},"404":{"description":"No account has this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"`Account not found for Id: <id>`."}}}}}},"405":{"description":"The request used a verb other than GET, POST or PUT. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"An input value failed validation, or a custom field value could not be saved (that body carries only `error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}},"500":{"description":"Any other failure, including a name another account already has.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceExceptionError"}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/callback":{"post":{"summary":"Report Salesforce contact sync results","description":"Internal: called by the ActiveCampaign Salesforce managed package after it synced contacts sent by an automation, not meant for direct use. Which Salesforce ID a record carries says whether the contact became a lead, contact or person account. For each record in `ids` the contact's pending sync is marked successful with the Salesforce ID, the contact is tagged with the matching Salesforce tag and the automations waiting on the sync resume. For each record in `errors` the pending sync is marked failed and the automations resume on their failure path. Records missing an ID are skipped. The router accepts only POST on this path.","operationId":"complete-salesforce-contact-sync","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","description":"Contacts that synced.","items":{"type":"object","properties":{"SalesforceLeadId":{"type":"string","description":"ID of the Salesforce lead the contact was synced to. Send exactly one of the three Salesforce IDs.","example":"00Q1U000006pXTaUAM"},"SalesforceContactId":{"type":"string","description":"ID of the Salesforce contact the contact was synced to."},"SalesforcePersonAccountId":{"type":"string","description":"ID of the Salesforce person account the contact was synced to."},"ActiveCampaignContactId":{"type":["integer","string"],"description":"ID of the ActiveCampaign contact.","example":"898989"}}}},"errors":{"type":"array","description":"Contacts that failed to sync. Send an empty array when there are none.","items":{"type":"object","properties":{"SalesforceLeadId":{"type":"string","description":"ID of the Salesforce lead the contact was synced to. Send exactly one of the three Salesforce IDs.","example":"00Q1U000006pXTaUAM"},"SalesforceContactId":{"type":"string","description":"ID of the Salesforce contact the contact was synced to."},"SalesforcePersonAccountId":{"type":"string","description":"ID of the Salesforce person account the contact was synced to."},"ActiveCampaignContactId":{"type":["integer","string"],"description":"ID of the ActiveCampaign contact.","example":"898989"},"message":{"type":"string","description":"Why the sync failed. Records without one are skipped."},"type":{"type":"string","description":"Salesforce's label for the failed step, only logged.","example":"Contact Sync"}}}}}}}}},"responses":{"200":{"description":"Processed.","content":{"application/json":{"schema":{"type":"array","maxItems":0,"description":"Always an empty JSON array: the success body carries no data.","items":{"description":"Never present."}}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`ids` is missing or not an array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceSyncCallbackInvalid"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/callback/campaignMemberAdd":{"post":{"summary":"Report Salesforce campaign member add results","description":"Internal: called by the ActiveCampaign Salesforce managed package after it added contacts to Salesforce campaigns for an automation's add-to-campaign action, not meant for direct use. Each record moves the automation run that queued the add past that action: on its success path for `ids`, on its failure path for `errors`, except that Salesforce's duplicate-value error (the contact is already a member) counts as success. Records missing a field are skipped. Legacy endpoint; its method guard accepts only POST.","operationId":"complete-salesforce-campaign-member-add","x-canonical-resource":"contactAutomations","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","description":"Contacts that were added to the campaign.","items":{"type":"object","required":["SalesforceCampaignId","subscriberSeriesId"],"properties":{"SalesforceCampaignId":{"type":"string","description":"ID of the Salesforce campaign (15 or 18 characters).","example":"701Q000000pXTaXYZ"},"ActiveCampaignContactId":{"type":["integer","string"],"description":"ID of the ActiveCampaign contact.","example":"898783"},"subscriberSeriesId":{"type":["integer","string"],"description":"ID of the contact's automation run that queued the add. When the same contact appears more than once in a batch the run is resolved from the contact and campaign as well.","example":"22"}}}},"errors":{"type":"array","description":"Contacts that could not be added. Send an empty array when there are none.","items":{"type":"object","required":["SalesforceCampaignId","subscriberSeriesId"],"properties":{"SalesforceCampaignId":{"type":"string","description":"ID of the Salesforce campaign."},"ActiveCampaignContactId":{"type":["integer","string"],"description":"ID of the ActiveCampaign contact."},"subscriberSeriesId":{"type":["integer","string"],"description":"ID of the contact's automation run that queued the add."},"message":{"type":"string","description":"Why the add failed."},"type":{"type":"string","description":"Salesforce's error type, only logged."}}}}}}}}},"responses":{"200":{"description":"Processed.","content":{"application/json":{"schema":{"type":"array","maxItems":0,"description":"Always an empty JSON array: the success body carries no data.","items":{"description":"Never present."}}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`ids` is missing or not an array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceSyncCallbackInvalid"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/campaigns":{"get":{"summary":"List active Salesforce campaigns","description":"Internal: backs the automation builder's add-to-Salesforce-campaign action, not meant for direct use. Asks DeepData for the campaigns that are active in the connected Salesforce org and returns DeepData's response body unchanged. A failure is still answered with status 200, with `success` false and the error message. Legacy endpoint; its method guard accepts only GET.","operationId":"list-salesforce-campaigns","x-canonical-resource":"connections","parameters":[{"name":"orgId","in":"query","required":true,"description":"The Salesforce org ID of the account's Salesforce connection.","schema":{"type":"string"},"example":"00D2E0000013vPH"}],"responses":{"200":{"description":"DeepData's campaign list, passed through without reshaping, or the failure body.","content":{"application/json":{"schema":{"oneOf":[{"description":"DeepData's response body, unchanged."},{"type":"object","description":"The DeepData call failed.","required":["success","message"],"properties":{"success":{"type":"boolean","const":false,"description":"Always false."},"message":{"type":"string","description":"The exception message."}}}]}}}},"405":{"description":"The request used a verb other than GET. The response carries an `Allow` header naming the accepted verbs."}},"deprecated":false,"x-internal":true}},"/salesforce/sync/convertContact":{"post":{"summary":"Convert Salesforce leads on contacts","description":"Internal: called by the ActiveCampaign Salesforce managed package after leads were converted in Salesforce, not meant for direct use. Creates any Salesforce tag missing from the account, swaps each contact's lead and legacy Salesforce tags for the matching contact or person account tags, adds the converted tag, and returns the contacts' standard and custom field values so Salesforce can update its records. Send `contactIds` with `personAccountIds`, or the older `activecampaign_ids` alone, which treats every contact as a Salesforce contact. Legacy endpoint; its method guard accepts only POST.","operationId":"convert-salesforce-leads","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactIds":{"type":"array","description":"Contacts whose lead became a Salesforce contact. Sent together with `personAccountIds`. IDs of contacts that do not exist are ignored.","items":{"type":["integer","string"],"description":"A contact ID."},"example":["1","10","11"]},"personAccountIds":{"type":"array","description":"Contacts whose lead became a Salesforce person account. Sent together with `contactIds`; may be empty.","items":{"type":["integer","string"],"description":"A contact ID."},"example":["100","101"]},"activecampaign_ids":{"type":"array","description":"Older managed package versions: contacts whose lead became a Salesforce contact. Takes precedence over the other two.","items":{"type":["integer","string"],"description":"A contact ID."}}}}}}},"responses":{"200":{"description":"Every outcome answers 200: the file writes the controller's body without applying its status code or a Content-Type header. The body is the converted contacts, or an `errors` string when neither `activecampaign_ids` nor both `contactIds` and `personAccountIds` were sent, when the conversion failed, or when it matched no contact.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"The conversion succeeded.","required":["contacts"],"properties":{"contacts":{"type":"array","description":"One entry per converted contact.","items":{"type":"object","properties":{"id":{"type":"string","description":"The contact ID."},"first_name":{"type":"string","description":"First name."},"last_name":{"type":"string","description":"Last name."},"email":{"type":"string","description":"Email address."},"phone":{"type":"string","description":"Phone number."},"fields":{"type":["object","array"],"description":"Custom field values keyed by custom field ID; an empty array when the contact has none.","additionalProperties":{"type":"string","description":"A custom field value."}}}}}}},{"type":"object","description":"The request was invalid or the conversion failed.","required":["errors"],"properties":{"errors":{"type":"string","description":"What was missing, or the exception message."}}}]}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."}},"deprecated":false,"x-internal":true}},"/salesforce/sync/deletetags":{"post":{"summary":"Remove Salesforce tags from contacts","description":"Internal: called by the ActiveCampaign Salesforce managed package after records were deleted in Salesforce, not meant for direct use. Removes every Salesforce tag from the contacts and deletes their Salesforce sync records, which stops further updates flowing to Salesforce. Contacts with no Salesforce tag are left alone. Legacy endpoint; its method guard accepts only POST.","operationId":"delete-salesforce-contact-tags","x-canonical-resource":"contactTags","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceContactIds"}}}},"responses":{"200":{"description":"Removed.","content":{"application/json":{"schema":{"type":"array","maxItems":0,"description":"Always an empty JSON array: the success body carries no data.","items":{"description":"Never present."}}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`activecampaign_ids` is missing or not an array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceContactIdsInvalid"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/salesforce/sync/unsubscribe":{"post":{"summary":"Unsubscribe contacts who opted out in Salesforce","description":"Internal: called by the ActiveCampaign Salesforce managed package after contacts opted out of email in Salesforce, not meant for direct use. Unsubscribes each contact from every list it is actively subscribed to, with the reason `Has opted out of emails in Salesforce.`. Legacy endpoint; its method guard accepts only POST.","operationId":"unsubscribe-salesforce-opted-out-contacts","x-canonical-resource":"contactLists","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceContactIds"}}}},"responses":{"200":{"description":"Processed. Contacts whose unsubscribe failed on at least one list are listed in `errors`.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"Contacts with a failed unsubscribe; empty when all succeeded.","items":{"type":"object","properties":{"id":{"type":["integer","string"],"description":"The contact ID as sent."},"message:":{"type":"string","description":"Always `Failed to unsubscribe`. The key really ends in a colon."}}}}}}}}},"405":{"description":"The request used a verb other than POST. The response carries an `Allow` header naming the accepted verbs."},"422":{"description":"`activecampaign_ids` is missing or not an array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesforceContactIdsInvalid"}}}},"500":{"description":"An exception the endpoint does not catch. The API's generic handler answers `{\"message\": \"Something went wrong on our end. Please try again later\"}`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Fixed text; the cause is only logged."}}}}}}},"deprecated":false,"x-internal":true}},"/savedResponse/bulk_delete":{"delete":{"summary":"Bulk delete saved responses","description":"Internal: backs bulk delete on the saved responses settings page. Deletes every saved response whose ID is listed, along with its category assignment. IDs that match no saved response are skipped without an error, and the response is the same whether or not anything was deleted. Requires permission to manage saved responses. Only DELETE is answered; other methods get 405.","operationId":"bulk-delete-saved-responses","x-canonical-resource":"savedResponses","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"description":"IDs of the saved responses to delete.","items":{"type":"integer"},"example":[3,7]}}}}}},"responses":{"200":{"description":"The listed saved responses that existed are deleted. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"meta":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true.","example":true}}}}}}}},"403":{"description":"The user may not manage saved responses. The body is JSON text, but it is sent without a JSON Content-Type header.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One entry describing the failure.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code, as a number.","example":403},"title":{"type":"string","description":"Translated name of the error class."},"detail":{"type":"string","description":"Why the request failed (translated)."}}}}}}}}},"422":{"description":"`ids` is missing or empty, or the body is not JSON. The body is the plain-text message, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/savedResponses":{"post":{"summary":"Create a saved response","description":"","operationId":"saved-responses","x-canonical-resource":"savedResponses","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"savedResponse":{"properties":{"title":{"type":"string","description":"Title of the saved response being created"},"subject":{"type":"string","description":"Subject of the saved response being created"},"body":{"type":"string","description":"Body of the saved response being created"},"ldate":{"type":["string","null"]},"last_sent_user_id":{"type":["integer","null"]},"user":{"type":["integer","null"]}},"required":["title","subject","body"],"type":"object"}}},"examples":{"Request Example":{"value":{"savedResponse":{"title":"Response Title","subject":"Response Subject","body":"Response Body"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"savedResponse\": {\n        \"title\": \"Response title\",\n        \"subject\": \"Response subject\",\n        \"body\": \"Response body\",\n        \"cdate\": \"2018-11-16T02:50:54-06:00\",\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/:version/savedResponses/1/user\",\n            \"savedResponseCategorySavedResponse\": \"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"savedResponse":{"type":"object","properties":{"title":{"type":"string","example":"Response title"},"subject":{"type":"string","example":"Response subject"},"body":{"type":"string","example":"Response body"},"cdate":{"type":"string","example":"2018-11-16T02:50:54-06:00"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/:version/savedResponses/1/user"},"savedResponseCategorySavedResponse":{"type":"string","example":"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse"}}},"id":{"type":"string","example":"1"}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"This field is required.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Either a subject or a body needs to be provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/subject\"\n            }\n        },\n        {\n            \"title\": \"Either a subject or a body needs to be provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/body\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"This field is required."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}}}}},"deprecated":false},"get":{"summary":"List all saved responses","description":"","operationId":"list-all-saved-responses","x-canonical-resource":"savedResponses","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"savedResponses\": [\n        {\n            \"title\": \"Response title\",\n            \"subject\": \"Response subject\",\n            \"body\": \"Response body\",\n            \"ldate\": null,\n            \"last_sent_user_id\": null,\n            \"cdate\": \"2018-11-16T02:50:54-06:00\",\n            \"mdate\": null,\n            \"links\": {\n                \"user\": \"https://:account.api-us1.com/api/:version/savedResponses/1/user\",\n                \"savedResponseCategorySavedResponse\": \"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse\"\n            },\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"savedResponses":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","examples":["Response title"]},"subject":{"type":"string","examples":["Response subject"]},"body":{"type":"string","examples":["Response body"]},"ldate":{},"last_sent_user_id":{},"cdate":{"type":"string","examples":["2018-11-16T02:50:54-06:00"]},"mdate":{},"links":{"type":"object","properties":{"user":{"type":"string","examples":["https://:account.api-us1.com/api/:version/savedResponses/1/user"]},"savedResponseCategorySavedResponse":{"type":"string","examples":["https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse"]}}},"id":{"type":"string","examples":["1"]}}}},"meta":{"type":"object","properties":{"total":{"type":"string","examples":["1"]}}}}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_saved_responses","title":"List Saved Responses","description":"List the account's saved responses (reusable phrases for 1:1 emails and Conversations) with their titles, subjects and bodies, to start a 1:1 email draft from.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/savedResponses/{id}":{"get":{"summary":"Retrieve a saved response","description":"","operationId":"get-a-savedresponse","x-canonical-resource":"savedResponses","parameters":[{"name":"id","in":"path","description":"ID of the saved Response to receive","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"savedResponse\": {\n        \"title\": \"Response title\",\n        \"subject\": \"Response subject\",\n        \"body\": \"Response body\",\n        \"ldate\": null,\n        \"last_sent_user_id\": null,\n        \"cdate\": \"2018-11-16T02:50:54-06:00\",\n        \"mdate\": null,\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/:version/savedResponses/1/user\",\n            \"savedResponseCategorySavedResponse\": \"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"savedResponse":{"type":"object","properties":{"title":{"type":"string","examples":["Response title"]},"subject":{"type":"string","examples":["Response subject"]},"body":{"type":"string","examples":["Response body"]},"ldate":{},"last_sent_user_id":{},"cdate":{"type":"string","examples":["2018-11-16T02:50:54-06:00"]},"mdate":{},"links":{"type":"object","properties":{"user":{"type":"string","examples":["https://:account.api-us1.com/api/:version/savedResponses/1/user"]},"savedResponseCategorySavedResponse":{"type":"string","examples":["https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse"]}}},"id":{"type":"string","examples":["1"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"get_saved_response","title":"Get Saved Response","description":"Get one saved response by its id: title, subject and body.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}},"put":{"summary":"Update a saved response","description":"","operationId":"update-a-saved-response","x-canonical-resource":"savedResponses","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the saved response to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"savedResponse":{"properties":{"title":{"type":"string","description":"Title of the saved response being updated"},"subject":{"type":"string","description":"Subject of the saved response being updated"},"body":{"type":"string","description":"Body of the saved response being updated"},"ldate":{"type":["string","null"]},"last_sent_user_id":{"type":["integer","null"]},"user":{"type":["integer","null"]}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"savedResponse":{"title":"Response title","subject":"Response subject","body":"Response body"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"savedResponse\": {\n        \"title\": \"New Response Title\",\n        \"subject\": \"New Response Subject\",\n        \"body\": \"New Response Body\",\n        \"ldate\": null,\n        \"last_sent_user_id\": null,\n        \"cdate\": \"2018-11-16T02:50:54-06:00\",\n        \"mdate\": \"2018-11-16T11:19:30-06:00\",\n        \"links\": {\n            \"user\": \"https://:account.api-us1.com/api/:version/savedResponses/1/user\",\n            \"savedResponseCategorySavedResponse\": \"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"savedResponse":{"type":"object","properties":{"title":{"type":"string","example":"New Response Title"},"subject":{"type":"string","example":"New Response Subject"},"body":{"type":"string","example":"New Response Body"},"ldate":{},"last_sent_user_id":{},"cdate":{"type":"string","example":"2018-11-16T02:50:54-06:00"},"mdate":{"type":"string","example":"2018-11-16T11:19:30-06:00"},"links":{"type":"object","properties":{"user":{"type":"string","example":"https://:account.api-us1.com/api/:version/savedResponses/1/user"},"savedResponseCategorySavedResponse":{"type":"string","example":"https://:account.api-us1.com/api/:version/savedResponses/1/savedResponseCategorySavedResponse"}}},"id":{"type":"string","example":"1"}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SavedResponse with id 0\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SavedResponse with id 0"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a saved response","description":"","operationId":"retrieve-a-savedresponse","x-canonical-resource":"savedResponses","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the saved response to remove","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for SavedResponse with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for SavedResponse with id 1"}}}}}}},"deprecated":false}},"/scores":{"get":{"summary":"List all scores","description":"","operationId":"list-all-scores","x-canonical-resource":"scores","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"scores\": [\n        {\n            \"reltype\": \"contact\",\n            \"name\": \"Link Engagement Score\",\n            \"descript\": \"+50 points when user clicks any link sent\",\n            \"status\": \"1\",\n            \"cdate\": \"2018-12-13T15:05:42-06:00\",\n            \"mdate\": \"2018-12-13T16:23:07-06:00\",\n            \"links\": [],\n            \"id\": \"2\"\n        },\n        {\n            \"reltype\": \"contact\",\n            \"name\": \"Easy Targets\",\n            \"descript\": \"+10 for replying to any campaign email\",\n            \"status\": \"1\",\n            \"cdate\": \"2018-12-18T19:00:13-06:00\",\n            \"mdate\": \"2018-12-18T19:01:15-06:00\",\n            \"links\": [],\n            \"id\": \"6\"\n        },\n        {\n            \"reltype\": \"deal\",\n            \"name\": \"Is John Smith\",\n            \"descript\": \"+10 If contacts first name is John and the last name is Smith\",\n            \"status\": \"1\",\n            \"cdate\": \"2018-12-18T19:15:02-06:00\",\n            \"mdate\": \"2018-12-18T19:15:10-06:00\",\n            \"links\": [],\n            \"id\": \"7\"\n        },\n        {\n            \"reltype\": \"deal\",\n            \"name\": \"Country Is USA\",\n            \"descript\": \"+20 if contact resides in the United States\",\n            \"status\": \"1\",\n            \"cdate\": \"2018-12-19T00:37:38-06:00\",\n            \"mdate\": \"2018-12-19T00:37:42-06:00\",\n            \"links\": [],\n            \"id\": \"9\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"4\"\n    }\n}"}},"schema":{"type":"object","properties":{"scores":{"type":"array","items":{"type":"object","properties":{"reltype":{"type":"string","example":"contact"},"name":{"type":"string","example":"Link Engagement Score"},"descript":{"type":"string","example":"+50 points when user clicks any link sent"},"status":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2018-12-13T15:05:42-06:00"},"mdate":{"type":"string","example":"2018-12-13T16:23:07-06:00"},"links":{"type":"array"},"id":{"type":"string","example":"2"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"4"}}}}}}}}},"deprecated":false},"post":{"summary":"Create a score","description":"Creates an empty contact or deal score. The new score is a draft (status 0) with no rules and an empty description; add rules with POST /scores/{scoreId}/scoreRules (create-a-score-rule). HTML tags are stripped from the name, and a missing or empty name becomes \"Score N\", N being one more than the number of scores on the account. The body is checked before anything else: 422 when it has no score object, or score.type is missing, blank, not a string or neither contact nor deal, or score.name is not a string. Then 403 when the account does not include contact scoring, the API user may not manage contact custom fields, or the score is a deal score and the account has no deals or the user may not manage deals.","operationId":"create-a-score","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["score"],"properties":{"score":{"description":"The score to create.","required":["type"],"properties":{"type":{"description":"What the score rates: contact or deal. PUT /scores/{id} does not change it; copy the score to get one of the other type.","type":"string","enum":["contact","deal"]},"name":{"description":"Name of the score. HTML tags are stripped; missing or empty gives \"Score N\".","type":"string"}},"type":"object"}},"type":"object"},"example":{"score":{"type":"contact","name":"Link Engagement Score"}}}}},"responses":{"201":{"description":"The created score, under score.","content":{"application/json":{"schema":{"properties":{"score":{"description":"The score.","properties":{"reltype":{"description":"What the score rates: contact or deal. Stored as type; the API names it reltype.","type":"string","example":"contact"},"name":{"description":"Name of the score.","type":"string","example":"Link Engagement Score"},"descript":{"description":"Description of the score. Empty on a new score.","type":"string","example":"+50 points when user clicks any link sent"},"status":{"description":"0 while the score is a draft, 1 when it is active, 2 when it is inactive. A score with no rules is always 0.","type":"string","example":"1"},"cdate":{"description":"When the score was created, as a date and time with UTC offset.","type":"string","example":"2018-12-13T15:05:42-06:00"},"mdate":{"description":"When the score was last changed, as a date and time with UTC offset.","type":"string","example":"2018-12-13T16:23:07-06:00"},"links":{"description":"URLs of the records related to the score.","properties":{"scoreCalcHistory":{"description":"URL of the score's last recalculation record.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreCalcHistory"},"scoreRules":{"description":"URL of the score's rules.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreRules"}},"type":"object"},"id":{"description":"ID of the score.","type":"string","example":"2"}},"type":"object"}},"type":"object"}}}},"403":{"description":"The account does not include contact scoring or the API user may not manage contact custom fields; or, for a deal score, the account has no deals or the user may not manage deals. Body: errors, a list with one item carrying status and detail (Forbidden)."},"422":{"description":"The body has no score object, or score.type or score.name is invalid. Body: errors, a list with one item per failed check carrying status, title, detail and source.pointer (for example /data/attributes/[score][type])."}},"x-canonical-resource":"scores","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/scores/{id}":{"get":{"summary":"Retrieve a score","description":"","operationId":"retrieve-a-score","x-canonical-resource":"scores","parameters":[{"name":"id","in":"path","description":"ID of the score to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"score\": {\n        \"reltype\": \"contact\",\n        \"name\": \"Link Engagement Score\",\n        \"descript\": \"+50 points when user clicks any link sent\",\n        \"status\": \"1\",\n        \"cdate\": \"2018-12-13T15:05:42-06:00\",\n        \"mdate\": \"2018-12-13T16:23:07-06:00\",\n        \"links\": [],\n        \"id\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"score":{"type":"object","properties":{"reltype":{"type":"string","example":"contact"},"name":{"type":"string","example":"Link Engagement Score"},"descript":{"type":"string","example":"+50 points when user clicks any link sent"},"status":{"type":"string","example":"1"},"cdate":{"type":"string","example":"2018-12-13T15:05:42-06:00"},"mdate":{"type":"string","example":"2018-12-13T16:23:07-06:00"},"links":{"type":"array"},"id":{"type":"string","example":"2"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Score with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Score with id 1"}}}}}}},"deprecated":false},"put":{"summary":"Update a score","description":"Changes the name, description or status of a score; fields left out are left as they are. Every supplied field is checked before any is written, so a 400 means nothing was saved. The name has HTML tags stripped and every word capitalised, as the score editor does. Status 1 or active activates the score and schedules its recalculation; 2 or inactive deactivates it; a score with no rules is saved as a draft (0) whatever status is sent, so the response is re-read from the database rather than echoing the request. Renaming or changing the status republishes the account's scores to automations; a description change does not. A deal score needs no deals permission here, matching the legacy editor. The body is checked first: 422 when it has no score object, or name or descript is not a string, or status is neither a string nor an integer. Then 403 when the account does not include contact scoring or the API user may not manage contact custom fields, 404 when the score does not exist, and 400 when the name is empty after filtering or the status is not one of the accepted values.","operationId":"update-a-score","parameters":[{"name":"id","in":"path","description":"ID of the score to update","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["score"],"properties":{"score":{"description":"The fields to change. An empty object changes nothing and returns the score.","properties":{"name":{"description":"New name. HTML tags are stripped, surrounding spaces trimmed and every word capitalised; 400 when nothing is left.","type":"string"},"descript":{"description":"New description. Trimmed; may be empty.","type":"string"},"status":{"description":"1 or active to activate the score, 2 or inactive to deactivate it. The strings \"1\" and \"2\" are accepted too; any other value is a 400.","oneOf":[{"type":"string","enum":["active","inactive","1","2"]},{"type":"integer","enum":[1,2]}]}},"type":"object"}},"type":"object"},"example":{"score":{"name":"Link Engagement Score","descript":"+50 points when user clicks any link sent","status":"active"}}}}},"responses":{"200":{"description":"The score after the change, read back from the database.","content":{"application/json":{"schema":{"properties":{"score":{"description":"The score.","properties":{"reltype":{"description":"What the score rates: contact or deal. Stored as type; the API names it reltype.","type":"string","example":"contact"},"name":{"description":"Name of the score.","type":"string","example":"Link Engagement Score"},"descript":{"description":"Description of the score. Empty on a new score.","type":"string","example":"+50 points when user clicks any link sent"},"status":{"description":"0 while the score is a draft, 1 when it is active, 2 when it is inactive. A score with no rules is always 0.","type":"string","example":"1"},"cdate":{"description":"When the score was created, as a date and time with UTC offset.","type":"string","example":"2018-12-13T15:05:42-06:00"},"mdate":{"description":"When the score was last changed, as a date and time with UTC offset.","type":"string","example":"2018-12-13T16:23:07-06:00"},"links":{"description":"URLs of the records related to the score.","properties":{"scoreCalcHistory":{"description":"URL of the score's last recalculation record.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreCalcHistory"},"scoreRules":{"description":"URL of the score's rules.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreRules"}},"type":"object"},"id":{"description":"ID of the score.","type":"string","example":"2"}},"type":"object"}},"type":"object"}}}},"400":{"description":"score.name is empty after filtering, or score.status is not 1, 2, active or inactive. Nothing was saved. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account does not include contact scoring, or the API user may not manage contact custom fields. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No score with that id. Body: message, a sentence naming the id."},"422":{"description":"The body has no score object, or name or descript is not a string, or status is neither a string nor an integer. Body: errors, a list with one item per failed check carrying status, title, detail and source.pointer (for example /data/attributes/[score][type])."}},"x-canonical-resource":"scores","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/scores/{id}/copy":{"post":{"summary":"Copy a score","description":"Creates a copy of the score in the path, named \"<name> copy\", with every rule duplicated and each rule's segment copied, so the copy's conditions can be edited without touching the original; a rule whose segment no longer exists gets a new empty segment. The description and status are carried over. The copy keeps the source's type unless score.type in the body says otherwise; the body is optional. No deals permission is checked even when the copy is a deal score, matching the legacy score list. The account's scores are republished to automations afterwards. Returns 403 when the account does not include contact scoring or the API user may not manage contact custom fields, 404 when the source score does not exist, and 400 when score.type is given and is neither contact nor deal, or the copy could not be saved.","operationId":"copy-a-score","parameters":[{"name":"id","in":"path","description":"ID of the score to copy","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"properties":{"score":{"description":"Options for the copy.","properties":{"type":{"description":"Type of the copy. Leave out, or send an empty string, to keep the source score's type.","type":"string","enum":["contact","deal"]}},"type":"object"}},"type":"object"},"example":{"score":{"type":"deal"}}}}},"responses":{"201":{"description":"The new copy, under score.","content":{"application/json":{"schema":{"properties":{"score":{"description":"The score.","properties":{"reltype":{"description":"What the score rates: contact or deal. Stored as type; the API names it reltype.","type":"string","example":"contact"},"name":{"description":"Name of the score.","type":"string","example":"Link Engagement Score"},"descript":{"description":"Description of the score. Empty on a new score.","type":"string","example":"+50 points when user clicks any link sent"},"status":{"description":"0 while the score is a draft, 1 when it is active, 2 when it is inactive. A score with no rules is always 0.","type":"string","example":"1"},"cdate":{"description":"When the score was created, as a date and time with UTC offset.","type":"string","example":"2018-12-13T15:05:42-06:00"},"mdate":{"description":"When the score was last changed, as a date and time with UTC offset.","type":"string","example":"2018-12-13T16:23:07-06:00"},"links":{"description":"URLs of the records related to the score.","properties":{"scoreCalcHistory":{"description":"URL of the score's last recalculation record.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreCalcHistory"},"scoreRules":{"description":"URL of the score's rules.","type":"string","example":"https://:account.api-us1.com/api/3/scores/2/scoreRules"}},"type":"object"},"id":{"description":"ID of the score.","type":"string","example":"2"}},"type":"object"}},"type":"object"}}}},"400":{"description":"score.type is neither contact nor deal, or the copy could not be saved. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account does not include contact scoring, or the API user may not manage contact custom fields. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No score with that id. Body: message, a sentence naming the id."}},"x-canonical-resource":"scores","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/scores/{scoreId}/scoreRules":{"post":{"summary":"Add a rule to a score","description":"Appends a new rule to the score in the path. Any request body is ignored: the rule always starts worth 10 points, never expiring, with a new segment that has no conditions yet. Set the points, expiry and segment with PUT /scores/{scoreId}/scoreRules/{id} (update-a-score-rule). Adding a rule does not republish the scores to automations. Returns 403 when the account does not include contact scoring or the API user may not manage contact custom fields, 404 when the score does not exist, and 400 when the rule could not be created.","operationId":"create-a-score-rule","parameters":[{"name":"scoreId","in":"path","description":"ID of the score to add the rule to","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"responses":{"201":{"description":"The created rule, under scoreRule.","content":{"application/json":{"schema":{"properties":{"scoreRule":{"description":"The score rule.","properties":{"scoreid":{"description":"ID of the score the rule belongs to.","type":"string","example":"2"},"segmentid":{"description":"ID of the segment whose conditions a contact or deal must match for the rule to apply.","type":"string","example":"41"},"valchange":{"description":"Points the rule adds to the score when it applies; negative to subtract.","type":"string","example":"10"},"expire":{"description":"Hours after which the points the rule added expire; 0 means they never expire.","type":"string","example":"0"},"ordernum":{"description":"Position of the rule within its score, from 1.","type":"string","example":"1"},"cdate":{"description":"When the rule was created, as a date and time with UTC offset.","type":"string","example":"2026-10-15T09:12:44-05:00"},"mdate":{"description":"When the rule was last changed, as a date and time with UTC offset.","type":"string","example":"2026-10-15T09:12:44-05:00"},"links":{"description":"Always an empty list: a score rule has no related resources.","type":"array","items":{"type":"string"}},"id":{"description":"ID of the rule.","type":"string","example":"5"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The rule could not be created. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account does not include contact scoring, or the API user may not manage contact custom fields. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No score with that id. Body: message, a sentence naming the id."}},"x-canonical-resource":"scores","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/scores/{scoreId}/scoreRules/{id}":{"put":{"summary":"Update a score rule","description":"Changes the points, expiry or segment of one of the score's rules; fields left out are left as they are. Fields are checked and written one at a time, in the order valchange, expire, segmentid, so a 400 on a later field leaves the earlier ones saved. The rule must belong to the score in the path: a rule of another score is a 404, so this path cannot be used to probe for rule ids. Rule changes do not republish the scores to automations. Returns 403 when the account does not include contact scoring or the API user may not manage contact custom fields, 404 when the score or the rule does not exist or the rule belongs to another score, and 400 when the body has no scoreRule object or a field is invalid. A body that is not a JSON object counts as having no scoreRule.","operationId":"update-a-score-rule","parameters":[{"name":"scoreId","in":"path","description":"ID of the score the rule belongs to","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"id","in":"path","description":"ID of the rule to update","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["scoreRule"],"properties":{"scoreRule":{"description":"The fields to change.","properties":{"valchange":{"description":"Points the rule adds when it applies; negative to subtract. A number, which is truncated to a whole number; 400 when it is not numeric or is zero.","type":"integer"},"expire":{"description":"Hours after which the points expire; 0 means never. A number, which is truncated to a whole number; 400 when it is not numeric or is negative.","type":"integer"},"segmentid":{"description":"ID of an existing segment holding the conditions the rule applies to. 400 when it is not a positive number or no such segment exists.","type":"integer"}},"type":"object"}},"type":"object"},"example":{"scoreRule":{"valchange":25,"expire":72,"segmentid":41}}}}},"responses":{"200":{"description":"The rule after the change, under scoreRule.","content":{"application/json":{"schema":{"properties":{"scoreRule":{"description":"The score rule.","properties":{"scoreid":{"description":"ID of the score the rule belongs to.","type":"string","example":"2"},"segmentid":{"description":"ID of the segment whose conditions a contact or deal must match for the rule to apply.","type":"string","example":"41"},"valchange":{"description":"Points the rule adds to the score when it applies; negative to subtract.","type":"string","example":"10"},"expire":{"description":"Hours after which the points the rule added expire; 0 means they never expire.","type":"string","example":"0"},"ordernum":{"description":"Position of the rule within its score, from 1.","type":"string","example":"1"},"cdate":{"description":"When the rule was created, as a date and time with UTC offset.","type":"string","example":"2026-10-15T09:12:44-05:00"},"mdate":{"description":"When the rule was last changed, as a date and time with UTC offset.","type":"string","example":"2026-10-15T09:12:44-05:00"},"links":{"description":"Always an empty list: a score rule has no related resources.","type":"array","items":{"type":"string"}},"id":{"description":"ID of the rule.","type":"string","example":"5"}},"type":"object"}},"type":"object"}}}},"400":{"description":"The body has no scoreRule object, or valchange, expire or segmentid is invalid. Body: errors, a list with one item carrying status, title and detail."},"403":{"description":"The account does not include contact scoring, or the API user may not manage contact custom fields. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No score with that id, no rule with that id, or the rule belongs to another score. Body: message, a sentence naming the id."}},"x-canonical-resource":"scores","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete a score rule","description":"Deletes one of the score's rules together with the segment that held its conditions, and marks the score as changed. Deleting the score's last rule takes the score out of active: it becomes a draft (status 0) and the account's scores are republished to automations. The rule must belong to the score in the path: a rule of another score is a 404. Returns 403 when the account does not include contact scoring or the API user may not manage contact custom fields, and 404 when the score or the rule does not exist or the rule belongs to another score.","operationId":"delete-a-score-rule","parameters":[{"name":"scoreId","in":"path","description":"ID of the score the rule belongs to","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}},{"name":"id","in":"path","description":"ID of the rule to delete","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The rule was deleted. The body names it.","content":{"application/json":{"schema":{"properties":{"scoreRule":{"description":"The deleted rule.","properties":{"id":{"description":"ID of the deleted rule.","type":"integer","example":5}},"type":"object"}},"type":"object"},"example":{"scoreRule":{"id":5}}}}},"403":{"description":"The account does not include contact scoring, or the API user may not manage contact custom fields. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No score with that id, no rule with that id, or the rule belongs to another score. Body: message, a sentence naming the id."}},"x-canonical-resource":"scores","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/scribeConfig":{"get":{"tags":["CRM"],"summary":"Get the calling user's Scribe configuration","description":"Returns the stored Scribe configuration, or the default configuration when none was saved.","operationId":"get-scribe-config","responses":{"200":{"description":"The user's Scribe configuration."},"403":{"description":"The account or user does not have CRM."},"404":{"description":"The ai-crm-scribe flag is off."}},"x-canonical-resource":"agent_settings","x-internal":true},"put":{"tags":["CRM"],"summary":"Save the calling user's Scribe configuration","description":"Replaces the stored Scribe configuration, including the master enabled switch (creates it when missing).","operationId":"save-scribe-config","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScribeConfigRequest"}}}},"responses":{"200":{"description":"The saved configuration."},"403":{"description":"The account or user does not have CRM."},"404":{"description":"The ai-crm-scribe flag is off."},"422":{"description":"Invalid payload, or a dealConnectionId that is unknown or of the wrong provider."}},"x-canonical-resource":"agent_settings","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/segmentMatch/{segmentId}/{contactId}":{"get":{"x-canonical-resource":"segment_membership","operationId":"create_match_one_request","tags":["Match One"],"summary":"Create a Match One Request","parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"schema":{"type":"string"},"examples":{"UUID SegmentId":{"value":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195"},"Numeric SegmentId":{"value":"124"}}},{"name":"contactId","in":"path","description":"ContactId","required":true,"schema":{"type":"string"},"example":"1524"}],"responses":{"200":{"description":"Segment and Contact evaluation completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchResponseRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse400RootDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse404RootDO"}}}}},"deprecated":false}},"/segmentMatch/{segmentId}/{contactId}/{externalId}":{"get":{"x-canonical-resource":"segment_membership","operationId":"segment_match_check_by_external_id","tags":["Match One"],"summary":"Check to see if a Contact matches a Segment using the given externalId","parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","description":"ContactId","required":true,"schema":{"type":"number"}},{"name":"externalId","in":"path","description":"externalId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Segment, Contact & ExternalId evaluation completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchResponseRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseRootDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseRootDO"}}}}},"deprecated":false}},"/segmentMatchAll":{"post":{"operationId":"create_match_all_request","x-canonical-resource":"segment_match_requests","x-destructive":false,"x-bulk-operation":false,"tags":["Match All"],"summary":"Create a Match All Request for a new Segment","description":"Find all Contact Id's that match the given Segment. The provided segment will be saved with a 24 hour TTL. A new match-all request will be initiated. If results are not ready within 4 seconds, a response that lacks a result-set will be returned. Use the returned segmentId and runId to poll and check back later to see if the result-set is ready.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootDO"}}},"required":true},"parameters":[{"name":"sort","in":"query","description":"Comma delimited list of fields for which to sort the results. Optionally prepended with a dash sign to indicate descending order. Allowed fields: id, email, phone, first_name, last_name, full_name, cdate, udate, account_name, score, score<score-id>, field<custom-field-id>. The score<score-id> option will sort off of the value of a particular score. The field<custom-field-id> option will sort off of the value of a particular custom field.","required":false,"schema":{"type":"string","default":"id","enum":["id","-id","email","-email","phone","-phone","first_name","-first_name","last_name","-last_name","full_name","-full_name","cdate","-cdate","udate","-udate","account_name","-account_name","score","-score","score<score-id>","-score<score-id>","field<custom-field-id>","-field<custom-field-id>"]},"example":"score15"},{"name":"page","in":"query","description":"Page Number","required":false,"schema":{"type":"integer","default":1}},{"name":"page_size","in":"query","description":"Page Size. Maximum: 10,000","required":false,"schema":{"type":"integer","default":20,"maximum":10000}},{"name":"instant","in":"query","description":"If present, API will return instantly with a runId without waiting for up to 4 seconds for the results to be ready. Useful if you want to kick off a match-all request but don't need the results immediately","required":false,"schema":{"type":"enum","enum":[""]}},{"name":"x-account-id","in":"header","description":"x-account-id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"x-user-id","in":"header","description":"The id of the user making the request. This parameter is optional","schema":{"default":1,"type":"integer","format":"int32"}},{"name":"x-usergroup-id","in":"header","description":"The group id of the user making the request. This parameter ensures result-sets follows appropriate list permissions for that user","required":true,"schema":{"default":1,"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Segment match all request started and/or completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchAllResponseRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Endpoint not found"}},"deprecated":false}},"/segmentMatchAll/{segmentId}":{"get":{"operationId":"create_match_all_request_with_segment_id","x-canonical-resource":"segment_match_requests","tags":["Match All"],"summary":"Create a Match All Request","description":"A new match-all request will be initiated. If results are not ready within 4 seconds, a response that lacks a result-set will be returned and the response's `is_ready` attribute will be equal to `false`. Use the returned segmentId and runId to poll and check back later to see if the result-set is ready","parameters":[{"name":"segmentId","in":"path","description":"A segment id","required":true,"schema":{"type":"string"}},{"name":"sort","in":"query","description":"Comma delimited list of fields for which to sort the results. Optionally prepended with a dash sign to indicate descending order. Allowed fields: id, email, phone, first_name, last_name, full_name, cdate, udate, account_name, score, score<score-id>. The score<score-id> option will sort off of the value of a particular score.\n\nExamples: \"email\", \"-phone\", \"score2\", \"last_name,-first_name\"","required":false,"schema":{"type":"string","default":"id","enum":["id","-id","email","-email","phone","-phone","first_name","-first_name","last_name","-last_name","full_name","-full_name","cdate","-cdate","udate","-udate","account_name","-account_name","score","-score","score<score-id>","-score<score-id>","field<custom-field-id>","-field<custom-field-id>"]},"example":"-field9"},{"name":"page","in":"query","description":"Page Number","required":false,"schema":{"type":"integer","default":1}},{"name":"page_size","in":"query","description":"Page Size. Maximum: 10,000","required":false,"schema":{"type":"integer","default":20,"maximum":10000}},{"name":"instant","in":"query","description":"If present, API will return instantly with a runId without waiting for up to 4 seconds for the results to be ready. Useful if you want to kick off a match-all request but don't need the results immediately","required":false,"schema":{"type":"string","enum":[""]}},{"name":"x-account-id","in":"header","description":"x-account-id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"x-user-id","in":"header","description":"The id of the user making the request. This parameter is optional","schema":{"default":1,"type":"integer","format":"int32"}},{"name":"x-usergroup-id","in":"header","description":"The group id of the user making the request. This parameter ensures result-sets follows appropriate list permissions for that user","required":true,"schema":{"default":1,"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Segment match all request started and/or completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchAllResponseRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}}}}},"/segmentMatchAll/{segmentId}/{runId}":{"get":{"operationId":"get_result_set_by_id","x-canonical-resource":"segment_match_requests","tags":["Match All"],"summary":"Return Match All result-set","description":"If the result-set is not ready yet, the response's `is_ready` attribute will be equal to `false`. The match-all request has errored out if the `is_ready` attribute is false and the `run_id_end` attribute contains a valid timestamp`; when this occurs please try your request again or alert the support team. If either the RunId or the SegmentId have expired or otherwise do not exist, a 404 with error details will be returned.\n\nresult-sets are cached and returned in the same `sort` order that's requested. If the `sort` param is not provided it defaults to `id`. You can specify a different `sort` order than the original request, however this will break the result's cache for this `runId` and re-kick-off a new search for results using the same `runId`","parameters":[{"name":"segmentId","in":"path","description":"segmentId","required":true,"schema":{"type":"string"}},{"name":"runId","in":"path","description":"A run id","required":true,"schema":{"type":"string"}},{"name":"sort","in":"query","description":"Comma delimited list of fields for which to sort the results. Optionally prepended with a dash sign to indicate descending order. Allowed fields: id, email, phone, first_name, last_name, full_name, cdate, udate, account_name, score, score<score-id>. The score<score-id> option will sort off of the value of a particular score.\n\nExamples: \"email\", \"-phone\", \"score2\", \"last_name,-first_name\"","required":false,"schema":{"type":"string","default":"id","enum":["id","-id","email","-email","phone","-phone","first_name","-first_name","last_name","-last_name","full_name","-full_name","cdate","-cdate","udate","-udate","account_name","-account_name","score","-score","score<score-id>","-score<score-id>","field<custom-field-id>","-field<custom-field-id>"]},"example":"score15"},{"name":"page","in":"query","description":"Page Number","required":false,"schema":{"type":"integer","default":1}},{"name":"page_size","in":"query","description":"Page Size. Maximum: 10,000","required":false,"schema":{"type":"integer","default":20,"maximum":10000}},{"name":"x-account-id","in":"header","description":"x-account-id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"x-user-id","in":"header","description":"The id of the user making the request. This parameter is optional","schema":{"default":1,"type":"integer","format":"int32"}},{"name":"x-usergroup-id","in":"header","description":"The group id of the user making the request. This parameter ensures result-sets follows appropriate list permissions for that user","required":true,"schema":{"default":1,"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Segment match all request started and/or completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchAllResponseRootDO"},"examples":{"Match All Evaluation Still Running":{"value":{"data":[{"id":"744390a5-208e-4c3d-b709-b3c3ea6e5948-1","type":"matchAll","attributes":{"run_id":"744390a5-208e-4c3d-b709-b3c3ea6e5948","run_id_start":"2020-04-12T23:20:50.523Z","is_ready":false,"segment_id":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132","segment_timestamp":"2020-04-12T23:20:49.5523Z"}}]}},"Match All Evaluation Complete":{"value":{"data":[{"id":"744390a5-208e-4c3d-b709-b3c3ea6e5948-1","type":"matchAll","attributes":{"run_id":"744390a5-208e-4c3d-b709-b3c3ea6e5948","run_id_start":"2020-04-12T23:20:50.523Z","run_id_end":"2020-04-12T23:20:53.523Z","is_ready":true,"matches":[2345,12,234,9837,2317],"segment_id":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132","segment_timestamp":"2020-04-12T23:20:49.5523Z","page":{"current_page":1,"last_page":1,"per_page":20,"total":5}}}]}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment or RunId not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}}},"deprecated":false}},"/segmentMatchDetail/{segmentId}/{contactId}":{"get":{"x-canonical-resource":"segment_membership","operationId":"get_segment_match_detail","tags":["Match Detail"],"summary":"Explain whether a Contact matches a Segment","description":"Shows which of the segment's groups and conditions the contact matches, and describes each condition in plain language. A match is evaluated as the requesting user, so a contact that user cannot see is reported as not found. A field whose value could not be determined is left out: `translation` when the segment could not be translated, `contact_matches_group` when a condition whose result is unknown would decide the group.","parameters":[{"name":"segmentId","in":"path","description":"The segment to explain, by UUID or legacy numeric id","required":true,"schema":{"type":"string"},"examples":{"UUID SegmentId":{"value":"5d5a257a-b9c8-44c1-9709-724d3829a334"},"Numeric SegmentId":{"value":"124"}}},{"name":"contactId","in":"path","description":"The contact to evaluate","required":true,"schema":{"type":"string"},"example":"3"}],"responses":{"200":{"description":"Segment, groups and conditions evaluated for the contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailResponse"},"example":{"data":{"contact_id":3,"segment_id":"5d5a257a-b9c8-44c1-9709-724d3829a334","timestamp":"2026-10-09T16:11:19.239Z","contact_matches_segment":false,"groups":{"1":{"contact_matches_group":false,"operator":"And","conditions":{"1":{"translation":"Has opened any email","contact_matches":false},"2":{"translation":"First Name is not asdf","contact_matches":true}}},"2":{"contact_matches_group":false,"operator":"And","conditions":{"3":{"translation":"Tag has at least one of: tempor, a, ac","contact_matches":false},"4":{"translation":"List (Box) is List Option 3","contact_matches":false}}},"operator":"Or"}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"400 BAD_REQUEST","title":"The request could not be processed for this segment and contact"}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment or Contact Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"404 NOT_FOUND","title":"The contact was not found"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"500 INTERNAL_SERVER_ERROR","title":"The segment could not be debugged for this contact"}]}}}}},"deprecated":false}},"/segmentMatchDetail/{segmentId}/{contactId}/{externalId}":{"get":{"x-canonical-resource":"segment_membership","operationId":"get_segment_match_detail_by_external_id","tags":["Match Detail"],"summary":"Explain whether a Contact matches a Segment, using the given externalId","description":"Shows which of the segment's groups and conditions the contact matches, and describes each condition in plain language. A match is evaluated as the requesting user, so a contact that user cannot see is reported as not found. A field whose value could not be determined is left out: `translation` when the segment could not be translated, `contact_matches_group` when a condition whose result is unknown would decide the group.","parameters":[{"name":"segmentId","in":"path","description":"The segment to explain, by UUID or legacy numeric id","required":true,"schema":{"type":"string"},"examples":{"UUID SegmentId":{"value":"5d5a257a-b9c8-44c1-9709-724d3829a334"},"Numeric SegmentId":{"value":"124"}}},{"name":"contactId","in":"path","description":"The contact to evaluate","required":true,"schema":{"type":"string"},"example":"3"},{"name":"externalId","in":"path","description":"The external id that the segment's conditions are evaluated against. required when a condition refers to \"this\" such as: \"this deal\" or \"this custom object\" (in which case the external id would be a Deal's ID or a Custom Object's ID). This type of condition is generally only utilized in Automation blocks.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Segment, groups and conditions evaluated for the contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailResponse"},"example":{"data":{"contact_id":3,"segment_id":"5d5a257a-b9c8-44c1-9709-724d3829a334","timestamp":"2026-10-09T16:11:19.239Z","contact_matches_segment":false,"groups":{"1":{"contact_matches_group":false,"operator":"And","conditions":{"1":{"translation":"this deal's value is greater than $100","contact_matches":false},"2":{"translation":"First Name is not asdf","contact_matches":true}}},"2":{"contact_matches_group":false,"operator":"And","conditions":{"3":{"translation":"Tag has at least one of: tempor, a, ac","contact_matches":false},"4":{"translation":"List (Box) is List Option 3","contact_matches":false}}},"operator":"Or"}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"400 BAD_REQUEST","title":"The request could not be processed for this segment and contact"}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment or Contact Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"404 NOT_FOUND","title":"The contact was not found"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMatchDetailErrorResponse"},"example":{"errors":[{"status":"500 INTERNAL_SERVER_ERROR","title":"The segment could not be debugged for this contact"}]}}}}},"deprecated":false}},"/segmentMatchSome/{segmentId}":{"post":{"operationId":"find_contact_id_by_ac_playload","x-canonical-resource":"segment_match_requests","x-destructive":false,"x-bulk-operation":false,"tags":["Match All"],"summary":"Create a Match Some Request","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdditionalCriteriaRootDO"}}},"required":true},"parameters":[{"name":"segmentId","in":"path","description":"segmentId","required":true,"schema":{"type":"string"}},{"name":"sort","in":"query","description":"Comma delimited list of fields for which to sort the results. Optionally prepended with a dash sign to indicate descending order. Allowed fields: id, email, phone, first_name, last_name, full_name, cdate, udate, account_name, score, score<score-id>. The score<score-id> option will sort off of the value of a particular score.\n\nExamples: \"email\", \"-phone\", \"score2\", \"last_name,-first_name\"","required":false,"schema":{"type":"string","default":"id","enum":["id","-id","email","-email","phone","-phone","first_name","-first_name","last_name","-last_name","full_name","-full_name","cdate","-cdate","udate","-udate","account_name","-account_name","score","-score","score<score-id>","-score<score-id>","field<custom-field-id>","-field<custom-field-id>"]},"example":"-field41"},{"name":"page","in":"query","description":"Page Number","required":false,"schema":{"type":"integer","default":1}},{"name":"page_size","in":"query","description":"Page Size. Maximum: 10,000","required":false,"schema":{"type":"integer","default":20,"maximum":10000}},{"name":"instant","in":"query","description":"If present, response will return instantly without waiting for the results to be ready","required":false,"schema":{"type":"string","enum":[""]}},{"name":"x-account-id","in":"header","description":"x-account-id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"x-user-id","in":"header","description":"The id of the user making the request. This parameter is optinal","schema":{"default":1,"type":"integer","format":"int32"}},{"name":"x-usergroup-id","in":"header","description":"The group id of the user making the request. This parameter ensures result-sets follows appropriate list permissions for that user","required":true,"schema":{"default":1,"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Segment and contact evaluation completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchAllResponseRootDO"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}},"401":{"description":"Unauthorized","content":{}},"403":{"description":"Forbidden","content":{}},"404":{"description":"Segment Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}}},"deprecated":false}},"/segmentMatchSome/{segmentId}/{runId}":{"get":{"operationId":"get_result_set_by_run_id","x-canonical-resource":"segment_match_requests","tags":["Match All"],"summary":"Return a Match Some result-set","description":"If the result-set is not ready yet, the response's `is_ready` attribute will be equal to `false`. The match-all request has errored out if the `is_ready` attribute is false and the `run_id_end` attribute contains a valid timestamp`; when this occurs please try your request again or alert the support team. If either the RunId or the SegmentId have expired or otherwise do not exist, a 404 with error details will be returned.\n\nSorting is not supported for this endpoint. This endpoint can be used to pull results from a Match All or a Match Some request. The original sort value will be preserved and there is no risk kicking off a new request","parameters":[{"name":"segmentId","in":"path","description":"segmentId","required":true,"schema":{"type":"string"}},{"name":"runId","in":"path","description":"A run id","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page Number","required":false,"schema":{"type":"integer","default":1}},{"name":"page_size","in":"query","description":"Page Size. Maximum: 10,000","required":false,"schema":{"type":"integer","default":20,"maximum":10000}},{"name":"x-account-id","in":"header","description":"x-account-id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"x-user-id","in":"header","description":"The id of the user making the request. This parameter is optional","schema":{"default":1,"type":"integer","format":"int32"}},{"name":"x-usergroup-id","in":"header","description":"The group id of the user making the request. This parameter ensures result-sets follows appropriate list permissions for that user","required":true,"schema":{"default":1,"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Segment match all request started and/or completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchAllResponseRootDO"},"examples":{"Match All Evaluation Still Running":{"value":{"data":[{"id":"744390a5-208e-4c3d-b709-b3c3ea6e5948-1","type":"matchAll","attributes":{"run_id":"744390a5-208e-4c3d-b709-b3c3ea6e5948","run_id_start":"2020-04-12T23:20:50.523Z","is_ready":false,"segment_id":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132","segment_timestamp":"2020-04-12T23:20:49.5523Z"}}]}},"Match All Evaluation Complete":{"value":{"data":[{"id":"744390a5-208e-4c3d-b709-b3c3ea6e5948-1","type":"matchAll","attributes":{"run_id":"744390a5-208e-4c3d-b709-b3c3ea6e5948","run_id_start":"2020-04-12T23:20:50.523Z","run_id_end":"2020-04-12T23:20:53.523Z","is_ready":true,"matches":[2345,12,234,9837,2317],"segment_id":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132","segment_timestamp":"2020-04-12T23:20:49.5523Z","page":{"current_page":1,"last_page":1,"per_page":20,"total":5}}}]}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment or RunId not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}}}}},"deprecated":false}},"/segmentcom/contact":{"post":{"summary":"Create or update a contact from a Segment event","description":"Takes an event from the Segment (segment.com) integration and creates or updates the contact it is about, with its traits, list subscriptions and tags. The contact is looked up by user_id against the Segment id stored on contacts, then by anonymous_id against the stored Segment id or the email address, then by email; each of user_id, anonymous_id and email is read from the top level of the body, then from traits, then from properties, and a user_id or anonymous_id that contains @ is used as the email instead. No match creates the contact through contact sync; a match updates it. The user_id, or else the anonymous_id, is then stored as the contact's Segment id. For track and page events with no email to use, nothing is saved and the answer is a 200 whose contact is the list [\"email is required\"]. Internal: called by the Segment integration. Legacy endpoint: other methods are answered with 405 and Allow: POST.","operationId":"upsert-a-segmentcom-contact","x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentcomContactEvent"}}}},"responses":{"200":{"description":"The contact that was created or updated, or, for a track or page event with no email, the list [\"email is required\"] and nothing saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentcomContactResult"}}}},"422":{"description":"Nothing or only part was saved. JSON when neither user_id nor anonymous_id is at the top level of the body (errors.message), or when a required contact field is missing (errors, the list the contact save produced). Plain text, the error message, when the save failed in another way or the body is not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentcomContactError"}},"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/segmentcom/outbound-context":{"post":{"summary":"Resolve the Segment identities of contacts for outbound events","description":"For the service that sends events from this account to Segment (segment.com): returns the account's outgoing Segment write key and, for each item, the Segment identity of its contact. The body is one item, or items, a list of them; the first item's account_id must be this account's id. Each contact is looked up by contact.id. A contact with a stored Segment id gets it as user_id, or as anonymous_id when it contains a hyphen; otherwise anonymous_id is the item's contact.email, or the contact's email address when the item has none. Nothing is written. Legacy endpoint: other methods are answered with 405 and Allow: POST.","operationId":"retrieve-segmentcom-outbound-context","x-canonical-resource":"contact","x-destructive":false,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentcomOutboundContextRequest"}}}},"responses":{"200":{"description":"The write key and one resolved identity per item, in the order of the items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentcomOutboundContext"}}}},"401":{"description":"The first item has no account_id or another account's id (message: Account not found or domain mismatch), or the account has no outgoing Segment write key (message names the account).","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Why the request was refused.","example":"Account not found or domain mismatch"}}}}}},"422":{"description":"An item is not an object, or the lookup failed. The body is the error message as plain text.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/segments":{"get":{"summary":"List all segments","description":"Segments are the saved condition sets used to target contacts, either from an automation (`seriesid`) or from a list. This endpoint returns the segment records themselves, not the contacts that match them.\n\nThe collection is read-only and currently supports pagination only: `filters[...]` and `orders[...]` are accepted but have no effect, the segment conditions are not included, and the lists a segment is associated with cannot be requested or sideloaded with `include`. Segment conditions are managed in the application only.","operationId":"list-all-segments","x-canonical-resource":"legacy_segment","parameters":[{"name":"ids","in":"query","description":"Return only the segments with the given IDs. Accepts a comma-separated list or an array, and overrides `limit`. Example: ids=4,7","schema":{"type":"string"}},{"name":"limit","in":"query","description":"The number of records to return per request. Defaults to 20 and is capped at 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"segments\": [\n        {\n            \"name\": \"Engaged contacts\",\n            \"logic\": \"and\",\n            \"hidden\": \"0\",\n            \"seriesid\": \"0\",\n            \"created_timestamp\": \"2026-01-14 09:12:44\",\n            \"updated_timestamp\": \"2026-02-03 15:41:02\",\n            \"created_by\": \"1\",\n            \"updated_by\": \"1\",\n            \"segmentid_v2\": null,\n            \"id\": \"4\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"segments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Engaged contacts","description":"Name of the segment."},"logic":{"type":"string","example":"and","description":"How the segment conditions are combined: `and` or `or`."},"hidden":{"type":"string","example":"0","description":"Whether the segment is hidden from the segment list. `1` = hidden, `0` = visible."},"seriesid":{"type":"string","example":"0","description":"ID of the automation the segment belongs to, or `0` for a standalone segment saved against lists."},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44","description":"Date the segment was created, in `YYYY-MM-DD HH:MM:SS`."},"updated_timestamp":{"type":"string","example":"2026-02-03 15:41:02","description":"Date the segment was last updated, in `YYYY-MM-DD HH:MM:SS`."},"created_by":{"type":"string","example":"1","description":"ID of the user who created the segment."},"updated_by":{"type":"string","example":"1","description":"ID of the user who last updated the segment."},"segmentid_v2":{"description":"Identifier of the corresponding segment in the newer segment service, when one exists. `null` otherwise."},"id":{"type":"string","example":"4","description":"ID of the segment."}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}}},"deprecated":false,"x-internal":true}},"/segments/{id}":{"get":{"summary":"Retrieve a segment","description":"Retrieve a single segment by its ID. The segment conditions are not included; only the segment record is returned.","operationId":"retrieve-a-segment","x-canonical-resource":"legacy_segment","parameters":[{"name":"id","in":"path","description":"ID of the segment to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"segment\": {\n        \"name\": \"Engaged contacts\",\n        \"logic\": \"and\",\n        \"hidden\": \"0\",\n        \"seriesid\": \"0\",\n        \"created_timestamp\": \"2026-01-14 09:12:44\",\n        \"updated_timestamp\": \"2026-02-03 15:41:02\",\n        \"created_by\": \"1\",\n        \"updated_by\": \"1\",\n        \"segmentid_v2\": null,\n        \"id\": \"4\"\n    }\n}"}},"schema":{"type":"object","properties":{"segment":{"type":"object","properties":{"name":{"type":"string","example":"Engaged contacts","description":"Name of the segment."},"logic":{"type":"string","example":"and","description":"How the segment conditions are combined: `and` or `or`."},"hidden":{"type":"string","example":"0","description":"Whether the segment is hidden from the segment list. `1` = hidden, `0` = visible."},"seriesid":{"type":"string","example":"0","description":"ID of the automation the segment belongs to, or `0` for a standalone segment saved against lists."},"created_timestamp":{"type":"string","example":"2026-01-14 09:12:44","description":"Date the segment was created, in `YYYY-MM-DD HH:MM:SS`."},"updated_timestamp":{"type":"string","example":"2026-02-03 15:41:02","description":"Date the segment was last updated, in `YYYY-MM-DD HH:MM:SS`."},"created_by":{"type":"string","example":"1","description":"ID of the user who created the segment."},"updated_by":{"type":"string","example":"1","description":"ID of the user who last updated the segment."},"segmentid_v2":{"description":"Identifier of the corresponding segment in the newer segment service, when one exists. `null` otherwise."},"id":{"type":"string","example":"4","description":"ID of the segment."}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Segment with id 19\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Segment with id 19"}}}}}}},"deprecated":false,"x-internal":true}},"/segmentsV2":{"post":{"tags":["Segments"],"summary":"Create a Segment","description":"The Segment JSON structure is extremely flexible; Only segments that are supported by the segment-builder are guaranteed to work as expected. Specific Condition types only support a subset of FieldDO and AggregateDO options. Please refer to your account's /app/segments/segment-builder page to verify what Segment JSON configurations are possible.","operationId":"create_segment","x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"parameters":[],"requestBody":{"$ref":"#/components/requestBodies/RootDO"},"responses":{"200":{"description":"Successfully saved the segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"400":{"description":"Bad Request. See error details in response body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootErrorDO"}},"segmentId already exists":{"examples":{"response":{"value":{"errors":[{"status":"400","detail":"Segment with the following id's already exist. Please use a PUT request to update a segment"}]}}}},"SourceSystem is a required field":{"examples":{"response":{"value":{"errors":[{"status":"400","detail":"SourceSystem is a required field."}]}}}},"Condition Group Required":{"examples":{"response":{"value":{"errors":[{"status":"400","detail":"These conditions must be included in a condition group for the segment to be valid: [1, 2]"}]}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"deprecated":false}},"/segmentsV2/{segmentId}":{"get":{"tags":["Segments"],"summary":"Retrieve a Segment","description":"Retrieves a V2 segment definition (conditions and condition groups) by its ID. Works for any segment, Saved Segment or otherwise.\n\nIf the response has a `name` and `category` is `audience`, the segment is a Saved Segment and its summary (name, contact counts, dates) is available from `GET /api/3/audiences/{segmentId}`.","operationId":"retrieve_segment","x-canonical-resource":"segments","parameters":[{"name":"segmentId","in":"path","description":"The segment's ID","required":true,"style":"simple","schema":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132"}}],"responses":{"200":{"description":"Retrieved most recent version of the requested segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment Not Found"}},"deprecated":false},"put":{"tags":["Segments"],"summary":"Update a Segment","operationId":"update_segment","x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"style":"simple","explode":false,"schema":{"type":"string"}}],"requestBody":{"$ref":"#/components/requestBodies/RootDO"},"responses":{"200":{"description":"Successfully updated the Segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"400":{"description":"Bad Request. Payload did not pass validation"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found. For a GET, DELETE, or PUT request, if a body is present, no segments were found. If a body is not present, the path was not found"}},"deprecated":false},"delete":{"tags":["Segments"],"summary":"Delete a Segment by SegmentId including its historic versions","operationId":"delete_segment","x-canonical-resource":"segments","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"style":"simple","explode":false,"schema":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195132"}}],"responses":{"200":{"description":"Deleted the Segment. Response body is what the segment looked like prior to deletion","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"deprecated":false}},"/segmentsV2/{segmentId}/createdDate/{timestamp}":{"get":{"tags":["Segments"],"summary":"Retrieve a Segment's Historic Definition","description":"Retrieve a Segment as it existed at the given point in time. Only segments with non-numeric SegmentIds are supported","operationId":"get_segment_historic","x-canonical-resource":"segments","parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"style":"simple","schema":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195"}},{"name":"timestamp","in":"path","description":"UTC milliseconds from the epoch","required":true,"style":"simple","schema":{"type":"integer","format":"int64","example":1752701788081}}],"responses":{"200":{"description":"Retrieved Segment as it existed at the given point in time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment was Not Found at the timestamp provided"}},"deprecated":false},"put":{"tags":["Segments"],"summary":"Revert a Segment to a Historic Definition","description":"Revert a segment to how it looked at a specific point in time. Only segments with non-numeric SegmentIds are supported","operationId":"segment_revert_to_history","x-canonical-resource":"segments","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"segmentId","in":"path","description":"SegmentId","required":true,"style":"simple","schema":{"type":"string","example":"1ab85f0e-3b5c-4a35-bc07-242c68a7d195"}},{"name":"timestamp","in":"path","description":"UTC milliseconds from the epoch","required":true,"style":"simple","schema":{"type":"integer","format":"int64","example":1752701788081}}],"responses":{"200":{"description":"Segment successfully reverted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootSuccessDO"}}}},"400":{"description":"Bad Request. See error details in response body"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Segment was Not Found at the timestamp provided"}},"deprecated":false}},"/segmentsV2/{segmentId}/translate":{"get":{"x-canonical-resource":"segments","tags":["Segments"],"summary":"Translate a segment into human-readable text","description":"Converts a segment's conditions into natural language text","operationId":"translateSegment","parameters":[{"name":"segmentId","in":"path","description":"Segment ID","required":true,"schema":{"type":"string"}},{"name":"locale","in":"query","description":"Language locale code (e.g., 'en', 'es', 'fr'). if not provided, defaults to the User's locale","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Segment translated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentTranslationResponseDO"}}}},"400":{"description":"Bad Request - Invalid segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentTranslationResponseDO"}}}},"404":{"description":"Segment not found"},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentTranslationResponseDO"}}}}}}},"/settings/account":{"post":{"summary":"Update account settings","description":"Update the settings of the user the API key belongs to, and the account wide date and time formats. This is the v3 replacement for the v1 `settings_edit` action, which wrote nothing but those formats.\n\nThe settings of the calling user (`firstName`, `lastName`, `loginEmail`, `timezone`, `language`) are required in every request: this endpoint writes the settings the request carries, so submit the values from [`GET /settings/account`](https://developers.activecampaign.com/reference/retrieve-account-information) for the fields that should keep their value. The three formats are optional, and only an administrator may change them.\n\nA successful request is a `202` reporting whether the update succeeded; it does not return the settings, so read them back with `GET /settings/account`. Invalid input is a `422`.\n\n> ❗️ Not `/configs`\n>\n> The [`/configs`](https://developers.activecampaign.com/reference/set-config) endpoints are an internal store of per-user interface preferences. They hold none of these settings, and are not the v3 replacement for v1 `settings_edit`.","operationId":"update-account-settings","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","description":"The first name of the calling user. Required, and may not contain quotes.","example":"John"},"lastName":{"type":"string","description":"The last name of the calling user. Required, and may not contain double quotes.","example":"Smith"},"loginEmail":{"type":"string","description":"The email address the calling user signs in with, returned as `email` by `GET /settings/account`. Required, and has to be an address whose domain can receive email. Changing it to an address on an unverified domain sends a verification email and leaves the settings unchanged, reported as a `422`; changing it is not allowed at all when the account signs in through SSO. When it changes, the user's other sessions are signed out.","example":"owner@example.com"},"notificationEmail":{"type":"string","description":"The address ActiveCampaign sends the calling user's notifications to. Optional, and has to be an address whose domain can receive email.","example":"alerts@example.com"},"phoneNumber":{"type":"string","description":"The phone number of the calling user, returned as `phone`. Optional, and has to be a valid number in international format; a bare national number is a `422`.","example":"+13125550123"},"signature":{"type":"string","description":"The email signature of the calling user, which may contain HTML. Optional.","example":"<p>John Smith, Example Inc.</p>"},"timezone":{"type":"string","description":"The timezone of the calling user. Required, and has to be a supported timezone.","example":"America/Chicago"},"language":{"type":"string","description":"The language the UI is shown in. Required, and has to be a full language name (e.g. `english`, `deutsch`) — not an ISO code like `en`.","example":"english"},"currentPassword":{"type":"string","description":"The calling user's current password, required only when `newPassword` is submitted.","example":"the-current-password"},"newPassword":{"type":"string","description":"A new password for the calling user. Optional; when it is submitted it has to differ from the current password and satisfy the account's password policy.","example":"a-new-password"},"dateFormat":{"type":"string","description":"The account wide date format, returned as `date_format`, as a `strftime` pattern. This is v1 `settings_edit`'s `dateformat`. Optional, and only an administrator may change it; an empty format, or one with no `strftime` conversion such as `%m`, is a `422`.","example":"%m/%d/%Y"},"timeFormat":{"type":"string","description":"The account wide time format, returned as `time_format`, as a `strftime` pattern. This is v1 `settings_edit`'s `timeformat`. Optional, administrator only.","example":"%H:%M"},"dateTimeFormat":{"type":"string","description":"The account wide combined date and time format, returned as `date_time_format`, as a `strftime` pattern. This is v1 `settings_edit`'s `datetimeformat`. Optional, administrator only.","example":"%m/%d/%Y %H:%M"}},"required":["firstName","lastName","loginEmail","timezone","language"]},"examples":{"Update the account wide date and time formats":{"value":{"firstName":"John","lastName":"Smith","loginEmail":"owner@example.com","timezone":"America/Chicago","language":"english","dateFormat":"%m/%d/%Y","timeFormat":"%H:%M","dateTimeFormat":"%m/%d/%Y %H:%M"}},"Update the calling user's own settings":{"value":{"firstName":"John","lastName":"Smith","loginEmail":"owner@example.com","notificationEmail":"alerts@example.com","phoneNumber":"+13125550123","signature":"<p>John Smith, Example Inc.</p>","timezone":"America/Chicago","language":"english"}}}}}},"responses":{"202":{"description":"202","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 1,\n    \"message\": \"Settings updated\"\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","description":"`1` when the settings were updated.","example":1},"message":{"type":"string","description":"A description of the outcome.","example":"Settings updated"}}}}}},"403":{"description":"403"},"422":{"description":"422"}}},"get":{"summary":"Retrieve account information","description":"Retrieve the hosted account and plan information for the account that owns the API key. This is the v3 replacement for the v1 `account_view` action.\n\nAuthenticate with your account's API key in the `Api-Token` request header. Only users in the **Admin** group may call this endpoint; requests authenticated as any other user return `403`, as do requests with a missing or invalid `Api-Token`.\n\n> ❗️ Not the same as `/accounts`\n>\n> This endpoint returns information about **your ActiveCampaign hosted account** (billing plan, contact limits, trial and credit status). It is unrelated to the [`/accounts`](https://developers.activecampaign.com/reference/list-all-accounts) endpoints, which manage CRM accounts (the organizations your contacts belong to).\n\n## Migrating from v1 `account_view`\n\n| v1 (`account_view`) | v3 (`GET /settings/account`) | Notes |\n| :--- | :--- | :--- |\n| `account` | `account` | Unchanged. |\n| `email` | `email` | Unchanged. |\n| `fname` | `first_name` | Renamed. |\n| `lname` | `last_name` | Renamed. |\n| `cname` | `cname` | Unchanged. An empty string when no CNAME is applied. |\n| `status` | `status` | Unchanged. |\n| `subscriber_limit` | `subscriber_limit` | Now an integer instead of a string. |\n| — | `subscriber_total` | New. The current number of contacts in the account. |\n| `trial` | `trial` | Always present in v3 as a boolean. In v1 the key was omitted entirely for non-trial accounts. |\n| `credits` | `credits` | Always present in v3. It is an integer for credit-based plans and `null` for every other plan. In v1 the key was omitted for non credit-based plans. |\n| — | `branding` | New. A boolean that is `true` when ActiveCampaign branding links are shown on the account's content. |\n| `result_code`, `result_message`, `result_output` | — | Removed. v3 uses HTTP status codes instead of a result envelope. |\n\nThe v3 response is a flat JSON object without the v1 result envelope, and the response is never cached (`Cache-Control: private`).\n\n## The v1 `settings_edit` formats\n\nThe response also carries the account wide date and time formats (`date_format`, `time_format`, `date_time_format`) the v1 `settings_edit` action wrote, and the settings of the calling user that `POST /settings/account` updates (`phone`, `signature`, `timezone`, `language`). `POST /settings/account` is the v3 replacement for `settings_edit`; the `/configs` endpoints are an internal store of per-user interface preferences and hold none of these settings.","operationId":"retrieve-account-information","responses":{"200":{"description":"200","content":{"application/json":{"schema":{"required":["account","email","first_name","last_name","cname","status","subscriber_limit","subscriber_total","trial","credits","branding","phone","signature","timezone","language","date_format","time_format","date_time_format"],"properties":{"account":{"description":"The account's ActiveCampaign URL.","type":"string","example":"example.activehosted.com"},"email":{"description":"The email address of the account owner.","type":"string","example":"owner@example.com"},"first_name":{"description":"The first name of the account owner. Replaces v1's `fname`.","type":"string","example":"John"},"last_name":{"description":"The last name of the account owner. Replaces v1's `lname`.","type":"string","example":"Smith"},"cname":{"description":"The CNAME applied to the account, or an empty string when none is applied.","type":"string","example":"mysite.com"},"status":{"description":"The status of the account: `nobody` (active), `maint`, `review`, or `suspend`.","type":"string","example":"nobody"},"subscriber_limit":{"description":"The total contact limit of the account's plan.","type":"integer","example":50000},"subscriber_total":{"description":"The number of contacts currently in the account.","type":"integer","example":1234},"trial":{"description":"Whether the account is on a trial plan. Always present, unlike v1 where the key existed only for trials.","type":"boolean","example":false},"credits":{"description":"The email credits remaining on credit-based plans, calculated as the account's credits minus the emails already sent. `null` for accounts that are not on a credit-based plan.","type":["integer","null"],"example":null},"branding":{"description":"Whether ActiveCampaign branding links are shown on the account's content.","type":"boolean","example":true},"phone":{"description":"The phone number of the calling user, or an empty string when they have none.","type":"string","example":"+13125550123"},"signature":{"description":"The email signature of the calling user, which may contain HTML, or an empty string when they have none.","type":"string","example":"<p>John Smith, Example Inc.</p>"},"timezone":{"description":"The timezone of the calling user.","type":"string","example":"America/Chicago"},"language":{"description":"The language the UI is shown to the calling user in.","type":"string","example":"en"},"date_format":{"description":"The account wide date format, as a PHP date format string. This is the value the v1 `settings_edit` action wrote as `dateformat`.","type":"string","example":"m/d/Y"},"time_format":{"description":"The account wide time format, as a PHP date format string. This is the value the v1 `settings_edit` action wrote as `timeformat`.","type":"string","example":"g:i a"},"date_time_format":{"description":"The account wide combined date and time format, as a PHP date format string. This is the value the v1 `settings_edit` action wrote as `datetimeformat`.","type":"string","example":"m/d/Y g:i a"}},"type":"object"},"examples":{"Result":{"summary":"The account details","value":"{\n    \"account\": \"example.activehosted.com\",\n    \"email\": \"owner@example.com\",\n    \"first_name\": \"John\",\n    \"last_name\": \"Smith\",\n    \"cname\": \"mysite.com\",\n    \"status\": \"nobody\",\n    \"subscriber_limit\": 50000,\n    \"subscriber_total\": 1234,\n    \"trial\": false,\n    \"credits\": null,\n    \"branding\": true,\n    \"phone\": \"+13125550123\",\n    \"signature\": \"<p>John Smith, Example Inc.</p>\",\n    \"timezone\": \"America/Chicago\",\n    \"language\": \"en\",\n    \"date_format\": \"m/d/Y\",\n    \"time_format\": \"g:i a\",\n    \"date_time_format\": \"m/d/Y g:i a\"\n}"},"Trial account on a credit-based plan":{"summary":"A trial account on a credit-based plan","value":"{\n    \"account\": \"example.activehosted.com\",\n    \"email\": \"owner@example.com\",\n    \"first_name\": \"John\",\n    \"last_name\": \"Smith\",\n    \"cname\": \"\",\n    \"status\": \"nobody\",\n    \"subscriber_limit\": 50000,\n    \"subscriber_total\": 1234,\n    \"trial\": true,\n    \"credits\": 60,\n    \"branding\": true,\n    \"phone\": \"+13125550123\",\n    \"signature\": \"<p>John Smith, Example Inc.</p>\",\n    \"timezone\": \"America/Chicago\",\n    \"language\": \"en\",\n    \"date_format\": \"m/d/Y\",\n    \"time_format\": \"g:i a\",\n    \"date_time_format\": \"m/d/Y g:i a\"\n}"}}}}},"403":{"description":"403","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"What went wrong.","type":"string","example":"Only admin users may view account information."}},"type":"object"}}},"type":"object"},"examples":{"User is not an admin":{"summary":"The user is not an admin","value":"{\n    \"errors\": [\n        {\n            \"status\": \"403\",\n            \"detail\": \"Only admin users may view account information.\"\n        }\n    ]\n}"}}}}},"500":{"description":"500","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"500"},"detail":{"description":"What went wrong.","type":"string","example":"Failed to retrieve account information."}},"type":"object"}}},"type":"object"},"examples":{"Result":{"summary":"The account information could not be retrieved","value":"{\n    \"errors\": [\n        {\n            \"status\": \"500\",\n            \"detail\": \"Failed to retrieve account information.\"\n        }\n    ]\n}"}}}}}},"deprecated":false,"x-canonical-resource":"activecampaign_account"}},"/settings/advanced":{"put":{"summary":"Update the advanced account settings","description":"Writes the account wide settings on the Advanced settings page: the date, time and combined date and time formats, whether email is DKIM signed on behalf of the From domain, and whether Google Analytics tracking is on. Internal: backs the Advanced settings page of the app.\n\nAll five fields are required and all five are written, so send the current value of every field you do not mean to change. Only a user in the Admin group may call it; any other caller is refused with a `422`, not a `403`. The formats are `strftime` patterns and are rejected unless they contain a conversion such as `%m`.\n\nSaving also moves an account still on the legacy `dk` DKIM selector to `acdkim1`, and clears the cached settings so the next page load reads the new values.","operationId":"update-advanced-settings","requestBody":{"description":"The five advanced settings, all required. A JSON body needs `Content-Type: application/json`; a form-encoded body works too.","required":true,"content":{"application/json":{"schema":{"required":["dateformat","timeformat","datetimeformat","onbehalfof","google_analytics_enabled"],"properties":{"dateformat":{"description":"Account wide date format, as a `strftime` pattern. An empty value or one with no conversion is a `422`.","type":"string","example":"%m/%d/%Y"},"timeformat":{"description":"Account wide time format, as a `strftime` pattern.","type":"string","example":"%H:%M"},"datetimeformat":{"description":"Account wide combined date and time format, as a `strftime` pattern.","type":"string","example":"%m/%d/%Y %H:%M"},"onbehalfof":{"description":"`1` signs outgoing email with the ActiveCampaign DKIM key and a `Sender` header, sending on behalf of the From domain; `0` signs with the From domain's own DKIM records. Send `0` as the integer: `\"0\"` and `false` count as empty and are a `422`.","type":"integer","enum":[0,1],"example":1},"google_analytics_enabled":{"description":"Only the integer `1` turns Google Analytics tracking on; any other non-empty value, `true` included, turns it off. As with `onbehalfof`, `0` must be the integer.","type":"integer","enum":[0,1],"example":0}},"type":"object"},"example":{"dateformat":"%m/%d/%Y","timeformat":"%H:%M","datetimeformat":"%m/%d/%Y %H:%M","onbehalfof":1,"google_analytics_enabled":0}}}},"responses":{"202":{"description":"The settings were saved. The body reports the outcome only and does not echo the settings.","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always `1`.","type":"integer","example":1},"message":{"description":"A translated confirmation message.","type":"string"}},"type":"object"}}}},"422":{"description":"Nothing was saved: the caller is not in the Admin group, a field is missing or empty, or a format has no `strftime` conversion. `detail` is a translated message naming the problem.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"A translated title for invalid input.","type":"string"},"detail":{"description":"A translated message naming the problem.","type":"string"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/settings/appearance":{"post":{"summary":"Update the appearance settings","description":"Writes the branding of the account shown on the Appearance settings page: the account name and logos, the favicon, the support widget toggle, the ActiveCampaign branding links and, on plans that include custom templates, the app and public page templates with their header and footer. Internal: backs the Appearance settings page of the app.\n\nEvery field the plan allows is written, so an omitted field is saved empty: send the current value of every field you do not mean to change. On a plan without custom templates the template, header and footer fields are not read: the templates fall back to the defaults and the header and footer are emptied. `links` is read only on plans that may remove the ActiveCampaign branding; elsewhere it is always saved as `1`. The change applies to the branding of every user group.\n\nOnly a user in the Admin group of an account that is not a reseller account may call it.","operationId":"update-appearance-settings","requestBody":{"description":"The appearance settings. No field is required, but every field the plan allows is overwritten. A JSON body needs `Content-Type: application/json`; a form-encoded body works too.","required":true,"content":{"application/json":{"schema":{"properties":{"site_name":{"description":"Name of the account shown in the app. HTML tags are removed.","type":"string","example":"Example Inc."},"site_logo":{"description":"URL of the logo shown in the app.","type":"string","example":"https://example.com/logo.png"},"site_logo_small":{"description":"URL of the small version of the logo.","type":"string","example":"https://example.com/logo-small.png"},"favicon":{"description":"URL of the favicon. A value that is not a URL removes the favicon.","type":"string","example":"https://example.com/favicon.ico"},"zendesk_widget_enabled":{"description":"Whether the support widget is shown in the app. Read as a boolean, so `\"1\"`, `\"on\"` and `\"yes\"` also mean on.","type":"boolean","example":true},"links":{"description":"Whether the ActiveCampaign branding is shown. Read only on plans that may remove it; the value is also sent to SMS link shortening, which allocates ActiveCampaign branded domains only to branded accounts.","type":"boolean","example":true},"admin_template_htm":{"description":"HTML template of the app. Custom template plans only. It must contain `%PAGECONTENT%`, and may contain each of `%HEADERNAV%`, `%PAGECONTENT%` and `%FOOTER%` once at most; empty restores the default template.","type":"string"},"admin_template_css":{"description":"CSS of the app template. Custom template plans only. HTML tags are removed.","type":"string"},"public_template_htm":{"description":"HTML template of the public pages. Custom template plans only. It must contain `%PAGECONTENT%`; empty restores the default template.","type":"string"},"public_template_css":{"description":"CSS of the public page template. Custom template plans only. HTML tags are removed.","type":"string"},"header_type":{"description":"Which header value is used. Custom template plans only.","type":"string","enum":["text","html"],"example":"text"},"header_text_value":{"description":"Plain text header, used when `header_type` is `text`. Custom template plans only.","type":"string"},"header_html_value":{"description":"HTML header, used when `header_type` is not `text`. Custom template plans only.","type":"string"},"footer_type":{"description":"Which footer value is used. Custom template plans only.","type":"string","enum":["text","html"],"example":"text"},"footer_text_value":{"description":"Plain text footer, used when `footer_type` is `text`. Custom template plans only.","type":"string"},"footer_html_value":{"description":"HTML footer, used when `footer_type` is not `text`. Custom template plans only.","type":"string"}},"type":"object"},"example":{"site_name":"Example Inc.","site_logo":"https://example.com/logo.png","site_logo_small":"https://example.com/logo-small.png","favicon":"https://example.com/favicon.ico","zendesk_widget_enabled":true,"links":true}}}},"responses":{"202":{"description":"The settings were saved. The body reports the outcome only and does not echo the settings.","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always `1`.","type":"integer","example":1},"message":{"description":"A translated confirmation message.","type":"string"}},"type":"object"}}}},"422":{"description":"Nothing was saved. A template that breaks the placeholder rules answers a JSON `errors` body with a translated `detail`. A caller who is not in the Admin group, a reseller account, or a failed write answers plain text instead of JSON.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"A translated title for invalid input.","type":"string"},"detail":{"description":"A translated message naming the placeholder rule the template breaks.","type":"string"}},"type":"object"}}},"type":"object"}},"text/plain":{"schema":{"description":"A translated message saying the caller may not change the appearance, or `Design Settings could not be updated.`","type":"string"}}}}},"x-canonical-resource":"brandings","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/settings/developer":{"post":{"summary":"Reset an API key","description":"Regenerate the API key of the authenticated user. The previous key stops working immediately, so this both revokes and reissues in one call.\n\n`user` must be the authenticated user's own id; any other value answers `403`, and an omitted value answers `400`.\n\nThe response reports only the outcome. Call [Retrieve API credentials](/reference/retrieve-api-credentials) afterwards to read the new key.","operationId":"reset-an-api-key","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"integer","format":"int32","description":"ID of the user whose key is reset. Must be the authenticated user's own id."}},"required":["user"],"additionalProperties":false},"examples":{"Request Example":{"value":{"user":1}}}}}},"responses":{"202":{"description":"202","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"succeeded\": 1,\n    \"message\": \"\",\n    \"deleted\": [],\n    \"failed\": []\n}"}},"schema":{"type":"object","properties":{"succeeded":{"type":"integer","format":"int32","description":"`1` when the key was reset."},"message":{"type":"string"},"deleted":{"type":"array"},"failed":{"type":"array"}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Invalid user\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"Forbidden\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}},"deprecated":false},"get":{"summary":"Retrieve API credentials","description":"Retrieve the API URL and API key of the authenticated user. These are the `apiurl` and `apikey` members the v1 `user_me` action returns.","operationId":"retrieve-api-credentials","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"url\": \"https://youraccountname.api-us1.com\",\n    \"key\": \"4f8b2c...\"\n}"}},"schema":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the account's API."},"key":{"type":"string","description":"API key of the authenticated user."}}}}}}},"deprecated":false}},"/settings/dkim":{"get":{"summary":"Check the DKIM records of a domain","description":"Looks up the DKIM DNS records of a sending domain and reports whether email from it can be DKIM signed. Internal.\n\nThe check looks first for both ActiveCampaign CNAME records (`acdkim1._domainkey` and `acdkim2._domainkey`), then for the legacy `dk` TXT record, then for a DKIM TXT record at the account's own selector. Only a user in the Admin group may call it; any other caller is refused with a `422`, not a `403`.\n\nLegacy endpoint: the file has no method guard, but the controller answers GET only and any other method is a `405`.","operationId":"retrieve-dkim-status","x-canonical-resource":"activecampaign_account","parameters":[{"name":"domain","in":"query","required":true,"description":"The sending domain to check, without a protocol.","schema":{"type":"string"},"example":"example.com"}],"responses":{"200":{"description":"The outcome of the DNS lookups.","content":{"application/json":{"schema":{"type":"object","properties":{"status_code":{"type":"string","enum":["success","warning","danger"],"description":"`success` when the domain is set up for DKIM, `warning` when only the legacy `dk` TXT record is found, `danger` when nothing usable is found."},"status_message":{"type":"string","enum":["success-both-cnames","error-only-one-cname","warn-legacy-dkim","success-custom-dkim","error-no-dns"],"description":"Which records were found: both ActiveCampaign CNAMEs, only one of them, the legacy `dk` TXT record, a DKIM TXT record at the account's custom selector, or none."}}},"example":{"status_code":"success","status_message":"success-both-cnames"}}}},"405":{"description":"The method is not GET. The `Allow` header is `GET`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"The caller is not in the Admin group, `domain` is missing or empty, or it is not a valid domain name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/domains":{"post":{"summary":"Set the account's custom domain","description":"Sets the custom domain (CNAME) the account is served from, or removes it. Internal: backs the Domains settings page of the app.\n\nBefore saving a domain the API checks that it has no protocol, is not an `activehosted.com` or `12all.com` host, is not in use by another account and that the plan includes custom domains, then looks up its DNS: it must be a CNAME record pointing to the account's own host, `activehosted.com`, `12all.com` or `managed-cname-fallback.activehosted.com`. Only a user in the Admin group may set a domain.\n\nAn empty `cname` removes the custom domain and skips every check, the Admin group check included.","operationId":"update-domain-settings","requestBody":{"description":"The domain to serve the account from. A JSON body needs `Content-Type: application/json`; a form-encoded body works too.","required":true,"content":{"application/json":{"schema":{"required":["cname"],"properties":{"cname":{"description":"Host name of the custom domain, without `http://` or `https://`. An empty string removes the custom domain.","type":"string","example":"marketing.example.com"}},"type":"object"},"example":{"cname":"marketing.example.com"}}}},"responses":{"202":{"description":"The domain was saved, or removed. The body reports the outcome only.","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always `1`.","type":"integer","example":1},"message":{"description":"A translated confirmation message.","type":"string"}},"type":"object"}}}},"403":{"description":"The caller is not in the Admin group and the request sets a domain.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":403},"title":{"description":"A translated title for the status.","type":"string"},"detail":{"description":"A translated message saying the caller is not authorized.","type":"string"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"The domain was not saved: it includes a protocol, is a reserved host, is used by another account, the plan does not include custom domains, or its DNS is not a CNAME record pointing to the account. `detail` says which.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"A translated title for the status.","type":"string"},"detail":{"description":"A translated message naming the check that failed.","type":"string"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/settings/notifications":{"put":{"summary":"Update the notification settings of the calling user","description":"Sets which deal events the calling user is notified about by email and how often those notifications are sent. Internal: backs the Notifications settings page of the app.\n\nAll four settings are written, so send the current value of every field you do not mean to change; an omitted `notifyOptions` turns every notification off. Any user may change their own settings.","operationId":"update-notification-settings","requestBody":{"description":"The notification settings. A JSON body needs `Content-Type: application/json`; a form-encoded body works too.","required":true,"content":{"application/json":{"schema":{"required":["notifyInterval","notifyIntervalDay","notifyIntervalHour"],"properties":{"notifyOptions":{"description":"Comma separated events to notify about, such as `deal_activity_add`, `deal_activity_add_mine`, `deal_activity_update`, `deal_activity_update_mine`, `comment` and `mention`; the `_mine` events are limited to deals the user owns. Omitted or empty means no notifications.","type":"string","example":"deal_activity_add_mine,comment,mention"},"notifyInterval":{"description":"How often notifications are sent: as they happen, or batched hourly, daily or weekly. Required and may not be empty.","type":"string","enum":["instant","hour","day","week"],"example":"day"},"notifyIntervalDay":{"description":"Day of the week a weekly batch is sent, `1` for Sunday through `7` for Saturday. Required for every interval and has to be numeric; a numeric string is accepted.","type":"integer","example":2},"notifyIntervalHour":{"description":"Time of day a daily or weekly batch is sent, as `HH:MM:SS`. Required and may not be empty.","type":"string","example":"09:00:00"}},"type":"object"},"example":{"notifyOptions":"deal_activity_add_mine,comment,mention","notifyInterval":"day","notifyIntervalDay":2,"notifyIntervalHour":"09:00:00"}}}},"responses":{"202":{"description":"The settings were saved. The body reports the outcome only and does not echo the settings.","content":{"application/json":{"schema":{"properties":{"succeeded":{"description":"Always `1`.","type":"integer","example":1},"message":{"description":"A translated confirmation message.","type":"string"}},"type":"object"}}}},"422":{"description":"Nothing was saved: `notifyInterval` or `notifyIntervalHour` is missing or empty, or `notifyIntervalDay` is not numeric.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, the same as the response status.","type":"integer","example":422},"title":{"description":"A translated title for invalid input.","type":"string"},"detail":{"description":"A translated message naming the field.","type":"string"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/settings/security/account_mfa":{"post":{"summary":"Require multi-factor authentication for every user","description":"Turns the account wide multi-factor authentication requirement on or off. Internal: backs the Security settings page of the app.\n\nThe caller needs the group permission to manage multi-factor authentication and has to have it set up on their own user. Turning the requirement off asks for the caller's password. Every change sends a notification email and is recorded in the security audit log; turning it on also signs out every user who has not set up multi-factor authentication.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"update-account-mfa-requirement","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"`true` requires multi-factor authentication for every user, `false` removes the requirement. Read as a boolean: an omitted or other falsy value means `false`."},"password":{"type":"string","description":"The calling user's current password. Required when `enable` is `false`."}},"required":["enable"]},"example":{"enable":true}}}},"responses":{"200":{"description":"The requirement was changed. The body is `null`.","content":{"application/json":{"schema":{"type":"null"}}}},"304":{"description":"The requirement is already in the requested state. Nothing changed."},"400":{"description":"The caller has not set up multi-factor authentication on their own user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller's group lacks the permission to manage multi-factor authentication. Also answered when turning the requirement off with a wrong password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"Turning the requirement off without a `password`, answered as JSON with `detail` `password is required`; or the change could not be saved, answered as a translated plain text message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}},"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/dns":{"get":{"summary":"Retrieve the Entri DNS setup session","description":"Returns what the app needs to start Entri, the third-party service that writes a domain's SPF, DKIM and DMARC DNS records for the customer: the Entri script and its integrity hash, the Entri application ID, a token requested from Entri for this session, and the free domain the account already claimed through Entri. Internal: used by the Entri DNS setup flow.\n\nWhen Entri does not answer with a token the request still succeeds and `token` is empty. Only an administrator may call it. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. GET is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"retrieve-dns-setup-session","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The Entri session.","content":{"application/json":{"schema":{"type":"object","properties":{"scriptUrl":{"type":"string","description":"URL of the Entri script.","example":"https://cdn.goentri.com/entri-latest.js"},"scriptSri":{"type":"string","description":"Subresource integrity hash of the Entri script.","example":"sha384-wnpzG3Yw9ogy4KIE2XZ/Cn9/fqwjb53eR5Te9a3cjud6UZF5wbmQrfWFKfBwZfaI"},"appId":{"type":"string","description":"ActiveCampaign's Entri application ID."},"token":{"type":"string","description":"Token from Entri for this session. Empty when Entri could not be reached."},"freeDomain":{"type":"string","description":"The free domain the account claimed through Entri, or empty when it has not claimed one; Entri offers the free domain only while this is empty."}}}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller is not an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Record the free domain claimed through Entri","description":"Stores the free domain the customer bought through Entri, so that later sessions do not offer it again. An account has one free domain: once one is stored it is never replaced. Internal: used by the Entri DNS setup flow.\n\nOnly an administrator may call it. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"create-free-domain-record","x-canonical-resource":"activecampaign_account","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","description":"The domain bought through Entri.","example":"example-shop.com"}},"required":["domain"]},"example":{"domain":"example-shop.com"}}}},"responses":{"200":{"description":"The request was processed. `status` says whether the domain was stored.","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","description":"The `domain` that was sent, or empty."},"status":{"type":"boolean","description":"`true` when the domain was stored; `false` when the account already has a free domain or `domain` is empty."}}},"example":{"domain":"example-shop.com","status":true}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller is not an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/download_recovery_codes":{"post":{"summary":"Retrieve the recovery codes file","description":"Returns the name and the text of the file the app offers for saving multi-factor authentication recovery codes: instructions in the calling user's language with today's date, followed by the account URL. The codes themselves are stored hashed and are not in the text; the app appends the codes it was shown when they were generated. Nothing is changed. Internal: backs the recovery codes download of the app.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"retrieve-mfa-recovery-codes-file","x-canonical-resource":"account_user","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"The file name and text.","content":{"application/json":{"schema":{"type":"object","properties":{"file_name":{"type":"string","enum":["ActiveCampaign_MFA_Recovery_Code.txt","MFA_Recovery_Code.txt"],"description":"File name. The ActiveCampaign name is used when the account shows ActiveCampaign branding."},"file_content":{"type":"string","description":"Text of the file, without the codes."}}}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/ip-allowlist":{"get":{"summary":"Retrieve the IP allowlist","description":"The IP allowlist limits signing in to, and using, the app to the listed addresses. It is enforced only for a fixed set of internal ActiveCampaign accounts; for any other account the list is stored but has no effect. Internal: used to manage the allowlist of internal accounts.\n\nThe controller checks no permission of its own. Legacy endpoint: the file has no method guard, but the controller answers GET and PUT only and any other method is a `405`.","operationId":"retrieve-ip-allowlist","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The stored allowlist.","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether a list is stored, which is what turns the allowlist on."},"value":{"type":"string","description":"The allowed IP addresses, one per line. Empty when the allowlist is off."}}},"example":{"enabled":true,"value":"203.0.113.10\n203.0.113.11"}}}},"405":{"description":"The method is not GET or PUT. The `Allow` header is `GET, PUT`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Replace the IP allowlist","description":"The IP allowlist limits signing in to, and using, the app to the listed addresses. It is enforced only for a fixed set of internal ActiveCampaign accounts; for any other account the list is stored but has no effect. Internal: used to manage the allowlist of internal accounts.\n\nThe list sent replaces the stored one. A non-empty list turns the allowlist on and an empty one turns it off; the `enabled` flag is required but does not decide this. The allowlist does not apply to this endpoint, so a mis-configured list can always be corrected. The controller checks no permission of its own.\n\nLegacy endpoint: the file has no method guard, but the controller answers GET and PUT only and any other method is a `405`.","operationId":"update-ip-allowlist","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Required, and has to be a JSON boolean. Not used otherwise: whether the allowlist is on follows from `value`."},"value":{"type":"string","description":"IP addresses, one per line; blank lines are ignored. Omitted or empty turns the allowlist off."}},"required":["enabled"]},"example":{"enabled":true,"value":"203.0.113.10\n203.0.113.11"}}}},"responses":{"200":{"description":"The allowlist was saved. The body is the saved state, with the addresses normalised one per line.","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether a list is stored, which is what turns the allowlist on."},"value":{"type":"string","description":"The allowed IP addresses, one per line. Empty when the allowlist is off."}}},"example":{"enabled":true,"value":"203.0.113.10\n203.0.113.11"}}}},"400":{"description":"The body is not JSON, `enabled` is missing or not a boolean, or `value` is not a string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"405":{"description":"The method is not GET or PUT. The `Allow` header is `GET, PUT`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"500":{"description":"A line of `value` is not a valid IP address. Nothing was saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsServerErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/mfa":{"post":{"summary":"Set up or turn off multi-factor authentication for the calling user","description":"Starts setting up multi-factor authentication for the calling user, or turns it off. Internal: backs the Security settings page of the app.\n\n- `{\"enable\": true}` starts an authenticator app setup and returns the QR code URL and new recovery codes.\n- `{\"enable\": true, \"delivery_type\": \"SMS\", \"phone_number\": \"1-3125550123\"}` sends a code to the phone and returns new recovery codes. An existing setup is replaced only after the code is sent.\n- `{\"enable\": false, \"password\": \"...\"}` turns it off, unless the account requires it for every user.\n\nA setup is complete only after the code from the app or the SMS is confirmed with `POST /settings/security/validate_mfa`. An ActiveCampaign support session skips the input and password checks.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"update-mfa-setup","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"`true` starts a setup, `false` turns multi-factor authentication off. Read as a boolean: an omitted or other falsy value means `false`. An SMS setup also needs `true`, or the request is treated as turning off."},"delivery_type":{"type":"string","enum":["SMS"],"description":"`SMS` sets up codes by text message. Any other value, or none, sets up an authenticator app."},"phone_number":{"type":"string","description":"SMS setup only, and then required: the country dial code and the number joined by a hyphen, as listed in `country_codes` of `GET /settings/security/mfa-info`.","example":"1-3125550123"},"password":{"type":"string","description":"The calling user's current password. Required when turning off."}},"required":["enable"]},"example":{"enable":true}}}},"responses":{"200":{"description":"Setup started, or multi-factor authentication turned off.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Authenticator app setup only: URL of a QR code image encoding the `otpauth://` registration. Empty when the session has no multi-factor authentication context."},"provider":{"type":"string","description":"Authenticator app setup only: code of the provider, `GA` for an authenticator app."},"recovery_codes":{"type":"string","description":"Setup only: ten new recovery codes, comma separated. Earlier codes stop working. They are not shown again."},"message":{"type":"string","description":"Turning off only: `MFA has been disabled.`"}}},"example":{"url":"https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=otpauth%3A%2F%2Ftotp%2F...&ecc=M","provider":"GA","recovery_codes":"3f9c1a27b0,8e4d2c91fa,..."}}}},"304":{"description":"Turning off: multi-factor authentication is not on for the calling user."},"400":{"description":"An authenticator app setup was requested but one is already set up and on, or the SMS phone number is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session. Also answered when turning off with a wrong password, or while the account requires multi-factor authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"Answered as JSON when turning off without a `password` (`password is required`), or for an SMS setup without a `phone_number` (`phone_number is required`) or with one not in `<dial code>-<number>` form; answered as a translated plain text message when the SMS could not be sent or too many codes were requested.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}},"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/mfa-info":{"get":{"summary":"Retrieve the multi-factor authentication setup of the calling user","description":"Returns how the calling user receives multi-factor authentication codes and the country dial codes the SMS setup accepts. Internal: backs the Security settings page of the app.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. GET is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"retrieve-mfa-setup","x-canonical-resource":"account_user","responses":{"200":{"description":"The setup. `delivery_type` and `phone_number` are left out when the user has never set up multi-factor authentication.","content":{"application/json":{"schema":{"type":"object","properties":{"country_codes":{"type":"object","description":"Every supported country, keyed by its code and dial code (e.g. `US (+1)`), with the dial code as the value.","additionalProperties":{"type":"string"}},"delivery_type":{"type":"string","enum":["APP","SMS",""],"description":"How codes are delivered once the setup is confirmed; empty while it is not confirmed yet."},"phone_number":{"type":"string","description":"SMS setups only: the phone number codes are sent to, as `<dial code>-<number>`."}}},"example":{"country_codes":{"US (+1)":"1","GB (+44)":"44"},"delivery_type":"SMS","phone_number":"1-3125550123"}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/recovery_codes":{"post":{"summary":"Replace the multi-factor authentication recovery codes","description":"Generates new recovery codes for the calling user; the earlier ones stop working. The change is recorded in the security audit log. Internal: backs the Security settings page of the app.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"update-mfa-recovery-codes","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","description":"The calling user's current password."}},"required":["password"]},"example":{"password":"the-current-password"}}}},"responses":{"200":{"description":"The new codes. They are not shown again.","content":{"application/json":{"schema":{"type":"object","properties":{"recovery_codes":{"type":"string","description":"Ten recovery codes of ten hexadecimal characters each, comma separated."}}},"example":{"recovery_codes":"3f9c1a27b0,8e4d2c91fa,..."}}}},"403":{"description":"The request is not from a signed-in browser session. Also answered when the password is wrong.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"`password` is missing, answered as JSON with `detail` `Invalid input`; or the user has never set up multi-factor authentication or the codes could not be saved, answered as a translated plain text message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}},"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/resend-otp":{"post":{"summary":"Resend the SMS code of a multi-factor authentication setup","description":"Sends the setup code again to the phone number given to `POST /settings/security/mfa`, while that SMS setup is not confirmed yet. No body is read. Internal: backs the Security settings page of the app.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"resend-mfa-sms-code","x-canonical-resource":"account_user","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"The code was sent again.","content":{"application/json":{"schema":{"type":"boolean","description":"Always `true`."},"example":true}}},"400":{"description":"The phone number is blocked from receiving codes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"Nothing was sent: there is no unconfirmed SMS setup, too many codes were requested, or the SMS could not be sent. The body is a translated plain text message, not JSON, although the response is labelled `application/json`.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/reset_mfa/{id}":{"post":{"summary":"Reset another user's multi-factor authentication","description":"Deletes another user's multi-factor authentication setup and turns it back on, so the user has to set it up again at the next sign-in. The user is signed out and notified by email. Internal: backs user management in the Security settings page of the app.\n\nThe caller needs the group permission to manage multi-factor authentication and may not reset their own user. The caller's password is checked only when the body sends `enable` as `false`, which is what the app does.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses.","operationId":"reset-user-mfa","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the user.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"Send `false` to have the password checked."},"password":{"type":"string","description":"The calling user's current password."}}},"example":{"enable":false,"password":"the-current-password"}}}},"responses":{"200":{"description":"The setup was reset.","content":{"application/json":{"schema":{"type":"boolean","description":"Always `true`."},"example":true}}},"400":{"description":"No user has this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller's group lacks the permission to manage multi-factor authentication. Also answered for the caller's own ID, or for a wrong password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"The user could not be updated. The body is a translated plain text message, not JSON, although the response is labelled `application/json`.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/security-center":{"get":{"summary":"Retrieve the security center report","description":"Reports whether every user of the account has verified the phone number on their user, which the security center of the app shows as a checklist item. Internal: backs the security center of the app.\n\nWhile the security center rollout is off for the account only `valid` and `message` are returned. Only an administrator may call it. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. GET is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"retrieve-security-center-report","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The report.","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","description":"`true` when the account has users and every one has a verified phone number."},"message":{"type":"string","enum":["complete","incomplete","not-enabled"],"description":"`complete` or `incomplete` following `valid`; `not-enabled` while the security center is off for the account."},"usersTotal":{"type":"integer","description":"Number of users in the account."},"usersPhoneVerified":{"type":"integer","description":"Number of users whose phone number matches the number they verified."}}},"example":{"valid":false,"message":"incomplete","usersTotal":5,"usersPhoneVerified":3}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller is not an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/session_keep":{"post":{"summary":"Keep the calling user's session alive","description":"Records activity on the calling user's session so it does not time out, and returns the account's session timeout. When the account has no custom session timeout the session is always extended. No body is read. Internal: called by the app while the user is active.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: GET is answered `404`, and POST is the verb this action uses.","operationId":"update-session-activity","x-canonical-resource":"account_user","x-destructive":false,"x-bulk-operation":false,"responses":{"200":{"description":"The session state.","content":{"application/json":{"schema":{"type":"object","properties":{"sessionExtended":{"type":"boolean","description":"Whether the session was extended. Always `true` when `sessionTimeoutEnabled` is `false`."},"sessionTimeoutValue":{"type":"string","description":"Inactivity timeout of the account, in seconds."},"sessionTimeoutEnabled":{"type":"boolean","description":"Whether the account has a custom session timeout."}}},"example":{"sessionExtended":true,"sessionTimeoutValue":"28800","sessionTimeoutEnabled":false}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/session_settings":{"get":{"summary":"Retrieve the session timeout settings","description":"Returns the account's custom session timeout settings and the bounds an inactivity timeout has to stay within. Internal: backs the Security settings page of the app.\n\nThe controller checks no permission for this read, so any authenticated caller, API key included, may call it.\n\nLegacy endpoint with no method guard in the file: the controller acts on GET, POST and DELETE; any other method answers `200` with a `null` body.","operationId":"retrieve-session-settings","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The settings.","content":{"application/json":{"schema":{"type":"object","properties":{"sessionSettings":{"type":"object","properties":{"sessionTimeoutEnabled":{"type":"boolean","description":"Whether the account has a custom session timeout."},"sessionInactiveTimeout":{"type":"string","description":"Inactivity timeout, in seconds. `28800` (8 hours) unless one is stored."},"sessionTimeoutLimit":{"type":"object","description":"Bounds for `sessionInactiveTimeout`, in seconds. A stored bound is a numeric string, a default one an integer.","properties":{"sessionTimeoutMin":{"type":["integer","string"],"description":"Lower bound; 900 (15 minutes) unless one is stored."},"sessionTimeoutMax":{"type":["integer","string"],"description":"Upper bound; unless one is stored, 28800 (8 hours) while the session enhancements rollout is on for the account and 86400 (24 hours) otherwise."}}}}}}},"example":{"sessionSettings":{"sessionTimeoutEnabled":true,"sessionInactiveTimeout":"3600","sessionTimeoutLimit":{"sessionTimeoutMin":900,"sessionTimeoutMax":28800}}}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Update a session timeout setting","description":"Saves one session timeout setting of the account. Internal: backs the Security settings page of the app.\n\n`sessionSettings` holds the setting to save; only its first key is saved. `sessionInactiveTimeout` has to be a multiple of 900 seconds within the bounds `GET /settings/security/session_settings` returns. `sessionTimeoutEnabled` is accepted only while the session enhancements rollout is off for the account. Saving also records activity on the caller's session.\n\nThe caller needs the group permission to manage multi-factor authentication. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: the controller acts on GET, POST and DELETE; any other method answers `200` with a `null` body.","operationId":"update-session-settings","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionSettings":{"type":"object","description":"The setting to save, as its only key.","properties":{"sessionInactiveTimeout":{"type":"integer","description":"Inactivity timeout in seconds, a multiple of 900.","example":3600},"sessionTimeoutEnabled":{"type":"boolean","description":"Whether the account uses a custom session timeout. Refused while the session enhancements rollout is on."}}}},"required":["sessionSettings"]},"example":{"sessionSettings":{"sessionInactiveTimeout":3600}}}}},"responses":{"200":{"description":"The setting was saved. The body is `null`.","content":{"application/json":{"schema":{"type":"null"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller's group lacks the permission to manage multi-factor authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"`sessionSettings` is missing or empty, holds a key that is not accepted, or the timeout is out of bounds or not a multiple of 900, answered as JSON with `detail` `Invalid input`; or the setting could not be saved, answered as a translated plain text message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}},"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/session_settings/{id}":{"delete":{"summary":"Sign a user out of every session","description":"Ends every session of a user. Internal: backs user session management in the Security settings page of the app.\n\nIt acts only while the account has a custom session timeout; otherwise nothing changes and the body is `false`. When it acts, the response also deletes the `ac` and `acr` token cookies of the caller's browser. The caller has to be that user or an administrator; no other permission is checked, so an API key may call it.\n\nLegacy endpoint with no method guard in the file: the controller acts on GET, POST and DELETE; any other method answers `200` with a `null` body.","operationId":"delete-user-sessions","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the user.","schema":{"type":"integer"}}],"responses":{"200":{"description":"`true` when the user has no active session left; `false` when the account has no custom session timeout, no user has this ID, or a session is still active.","content":{"application/json":{"schema":{"type":"boolean"},"example":true}}},"403":{"description":"The caller is neither this user nor an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/sms":{"post":{"summary":"Verify the calling user's phone number by SMS","description":"One endpoint for every step of verifying the phone number on the calling user, chosen by `action`. Internal: backs phone verification in the app.\n\n- `verification`: looks up `phone` and returns it formatted.\n- `validation`: sends a code to `phone` and returns the `requestid` of the attempt.\n- `resend`: sends the code of attempt `requestid` again.\n- `otp`: checks `code` for `phone`; with `enroll` the phone is stored as the user's verified number.\n- `settings`: returns whether SMS verification is on and the verified number.\n- `check` (also any other or no `action`): says whether `phone` is the user's verified number.\n\nEvery outcome, a refused one included, is a `200`: read `valid` and `message`. While SMS verification is off for the account, every action but `settings` answers `valid` `false` with `message` `sms-not-enabled`.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"verify-user-phone-number","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["verification","validation","resend","otp","settings","check"],"description":"The step to run. Any other value, or none, runs `check`."},"phone":{"type":"string","description":"The phone number, in international form.","example":"+13125550123"},"requestid":{"type":"string","description":"`resend` and `otp`: the `requestid` returned by `validation`."},"code":{"type":"string","description":"`otp`: the code the user received."},"enroll":{"type":"boolean","description":"`otp`: store the phone as the user's verified number when the code is correct."}}},"example":{"action":"validation","phone":"+13125550123"}}}},"responses":{"200":{"description":"The outcome of the action. Which members are present depends on `action`.","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","description":"Every action but `settings`: whether the step succeeded."},"message":{"type":"string","description":"Every action but `settings`: a code for the outcome, such as `verified-code`, `sms-code-sent`, `invalid-phone`, `invalid-code`, `expired-code`, `max-retries`, `verified-phone`, `unverified-phone`, `ait-blocked-phone` or `sms-not-enabled`; empty after a successful lookup. A rate limited send answers a translated sentence instead."},"formattedPhoneNumber":{"type":"string","description":"`verification`: the number in E.164 form."},"countryCode":{"type":"string","description":"`verification`: the country of the number."},"nationalNumber":{"type":"string","description":"`verification`: the number without the dial code."},"phone":{"type":"string","description":"`settings`: the user's verified number. `validation`: the number sent, only when the attempt could not be started."},"requestid":{"type":["string","null"],"description":"`validation`: ID of the attempt, to send with `resend` and `otp`."},"expires":{"type":"integer","description":"`validation` and `settings`: seconds a code stays valid."},"enabled":{"type":"boolean","description":"`settings`: whether SMS verification is on for the account."}}},"example":{"valid":true,"message":"sms-code-sent","requestid":"0d3c2f6e-9a41-4c5e-8f2b-7c1d9e6a4b20","expires":600}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/sso":{"get":{"summary":"Retrieve the single sign-on settings","description":"Returns the account's SAML single sign-on settings. Internal: backs the Security settings page of the app.\n\nOnly an administrator may call it. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. GET is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"retrieve-sso-settings","x-canonical-resource":"activecampaign_account","responses":{"200":{"description":"The settings, as stored. Values that were never saved are empty.","content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"Whether single sign-on is on."},"name":{"type":"string","description":"Name of the identity provider shown on the sign-in page."},"method":{"type":"string","enum":["0","1"],"description":"`0` lets users sign in with SSO or a password, `1` requires SSO."},"provision":{"type":"string","enum":["0","1"],"description":"`0` creates users automatically at their first SSO sign-in, `1` requires users to be added by hand."},"group":{"type":"string","description":"ID of the user group automatically created users join. The app sends an empty string for the default group."},"metadata":{"type":"string","description":"SAML metadata of the identity provider."}}},"example":{"enable":true,"name":"Okta","method":"0","provision":"0","group":"","metadata":"<md:EntityDescriptor ...>"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller is not an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Update the single sign-on settings","description":"Turns SAML single sign-on on with the settings sent, or turns it off. Turning it off keeps the other settings. Every change emails the account's administrators and is recorded in the security audit log. Internal: backs the Security settings page of the app.\n\nThe response is the same whether or not the settings were saved: a failure is only logged.\n\nOnly an administrator may call it. Only a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"update-sso-settings","x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"`true` turns single sign-on on and saves the other fields, `false` turns it off. Required; a string such as `\"1\"` or `\"0\"` is read as a boolean."},"name":{"type":"string","description":"Name of the identity provider shown on the sign-in page. Required when `enable` is `true`."},"method":{"type":"string","enum":["0","1"],"description":"`0` lets users sign in with SSO or a password, `1` requires SSO. Defaults to `0`."},"provision":{"type":"string","enum":["0","1"],"description":"`0` creates users automatically at their first SSO sign-in, `1` requires users to be added by hand. Defaults to `0`."},"group":{"type":"string","description":"ID of the user group automatically created users join. The app sends an empty string for the default group."},"metadata":{"type":"string","description":"SAML metadata of the identity provider."}},"required":["enable"]},"example":{"enable":true,"name":"Okta","method":"0","provision":"0","group":"","metadata":"<md:EntityDescriptor ...>"}}}},"responses":{"200":{"description":"The request was processed.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always `OK`."}}},"example":{"message":"OK"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller is not an administrator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"`enable` is missing or not a scalar (`enable is required and must be a boolean`), or single sign-on is turned on without a `name` (`Name of Secure Login Provider is required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/user_mfa/{id}":{"post":{"summary":"Turn multi-factor authentication on or off for another user","description":"Turns multi-factor authentication on or off for another user of the account. Turning it on makes the user set it up at the next sign-in and signs them out; turning it off deletes their setup and asks for the caller's password. The user is notified by email. Internal: backs user management in the Security settings page of the app.\n\nThe caller needs the group permission to manage multi-factor authentication, may not change their own user, and may not be an ActiveCampaign support session.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses.","operationId":"update-user-mfa","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the user.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enable":{"type":"boolean","description":"`true` turns it on, `false` turns it off. Read as a boolean: an omitted or other falsy value means `false`."},"password":{"type":"string","description":"The calling user's current password. Required when turning off."}},"required":["enable"]},"example":{"enable":false,"password":"the-current-password"}}}},"responses":{"200":{"description":"The user was updated.","content":{"application/json":{"schema":{"type":"boolean","description":"Always `true`."},"example":true}}},"400":{"description":"No user has this ID, or turning on a user who has already set it up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session, or the caller's group lacks the permission to manage multi-factor authentication. Also answered for the caller's own ID, a support session, or turning off with a missing or wrong password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"The user could not be updated. The body is a translated plain text message, not JSON, although the response is labelled `application/json`.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true}},"/settings/security/validate_mfa":{"post":{"summary":"Confirm the multi-factor authentication setup of the calling user","description":"Completes a setup started with `POST /settings/security/mfa` by checking a code from the authenticator app or the SMS, or a recovery code. On success the user's sessions that were not verified with multi-factor authentication are signed out and the user is notified by email. Internal: backs the Security settings page of the app.\n\nOnly a signed-in browser session may call it: a request authenticated with an API key is refused with `403`.\n\nLegacy endpoint with no method guard in the file: every method reaches the controller, which acts on GET and POST only. POST is the verb this action uses; any other method does nothing useful and answers an error or a `null` body.","operationId":"update-mfa-setup-confirmation","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"validation_code":{"type":"string","description":"The code to check.","example":"123456"},"delivery_type":{"type":"string","enum":["APP","SMS","recovery"],"description":"Where the code came from. Another value counts as a wrong code."}},"required":["validation_code","delivery_type"]},"example":{"validation_code":"123456","delivery_type":"APP"}}}},"responses":{"200":{"description":"The setup is confirmed. The body is `null`.","content":{"application/json":{"schema":{"type":"null"}}}},"400":{"description":"The calling user has no setup to confirm, or it is already confirmed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"403":{"description":"The request is not from a signed-in browser session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsHttpErrorResponse"}}}},"422":{"description":"The code is wrong. The body is a translated plain text message, not JSON, although the response is labelled `application/json`.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The session has no multi-factor authentication context, or it is already verified.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsServerErrorResponse"}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/attributes":{"get":{"summary":"List site message personalization attributes","description":"Internal: backs the site message editor in the app, not a customer API. The personalization tags a site message can insert, grouped for the editor's picker. Group names and tag titles are translated into the user's language. The Accounts group is present only when the account has the Accounts feature. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses.","operationId":"list-site-message-attributes","x-canonical-resource":"personalizations","responses":{"200":{"description":"The attribute groups, in display order","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SiteMessageAttributeGroup"}}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/compile_and_save":{"post":{"summary":"Compile a site message","description":"Internal: job callback, not a customer API. When a site message is saved, Hosted queues a job on the `site_messages` SQS queue and the queue-http-service posts it back here, authenticated with the primary admin's API key in the `api_key` query parameter. Compiles the message's HTML, CSS and JavaScript into the site message store, recompiles the wrapper every site message renders in, and records the personalization tags the message uses: tags it no longer uses are dropped, and contacts who were already sent the message get values stored for the tags it newly uses. The body is either the job fields themselves or the queue message with them under `data`; when `data` is present only `data` is read.","operationId":"compile-site-message","x-canonical-resource":"site_message","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SiteMessageCompileJob"},{"type":"object","description":"The SQS message body as the queue-http-service forwards it.","required":["data"],"properties":{"acctid":{"type":"integer","description":"ID of the account that queued the job. Not read."},"type":{"type":"string","description":"The job type, `compile_and_save`. Not read."},"data":{"$ref":"#/components/schemas/SiteMessageCompileJob"}}}]}}}},"responses":{"200":{"description":"No site message has this ID; nothing was done. The body is empty."},"202":{"description":"Compiled. The body is empty."},"400":{"description":"`messageid` is missing. The body is empty."},"500":{"description":"The body is not a JSON object","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always `Something went wrong on our end. Please try again later`."}}}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/emoji":{"get":{"summary":"List the site message emoji","description":"Internal: backs the emoji picker in the site message editor, not a customer API. A fixed list of 1,008 emoji, the same for every account. Legacy endpoint with no method guard: any HTTP method is answered the same way; GET is the documented verb and the one the app uses.","operationId":"list-site-message-emoji","x-canonical-resource":"site_message","responses":{"200":{"description":"The emoji","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SiteMessageEmoji"}}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/emojiList":{"get":{"summary":"Retrieve the raw site message emoji file","description":"Internal, not a customer API, and not called by the app: `api/3/siteMessage/emojiList.php` is the data file GET /siteMessage/emoji reads, and it answers on its own path only because every file under `api/3` is routable. The body is the same JSON array as GET /siteMessage/emoji, sent without a JSON Content-Type, so it arrives as `text/html`. Legacy endpoint with no method guard: any HTTP method is answered the same way.","operationId":"retrieve-site-message-emoji-file","x-canonical-resource":"site_message","responses":{"200":{"description":"The emoji list as JSON text","content":{"text/html":{"schema":{"type":"string","description":"JSON text of the array GET /siteMessage/emoji returns."}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/position":{"get":{"summary":"Retrieve the site message position","description":"Internal: backs the site message settings page in the app, not a customer API. Where on the page the account's site messages appear: one setting for the whole account, `bottom-right` when it has never been set. The endpoint answers GET and POST; any other method gets an empty 200.","operationId":"retrieve-site-message-position","x-canonical-resource":"site_message","responses":{"200":{"description":"The position","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteMessagePosition"}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Set the site message position","description":"Internal: backs the site message settings page in the app, not a customer API. Saves where on the page the account's site messages appear, one setting for the whole account, then recompiles every site message in the site message store, and the wrapper they render in, for the new position. `position` is read from a form-encoded body or the query string (the query string wins); a JSON body is not read, so it saves `bottom-right`. The value is not validated: any string is stored as given, and an empty or missing one saves `bottom-right`.","operationId":"update-site-message-position","x-canonical-resource":"site_message","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"position":{"type":"string","description":"Where site messages appear. The app sends `top-left`, `top-right`, `bottom-left` or `bottom-right`.","example":"top-right"}}}}}},"responses":{"200":{"description":"Saved. The body is empty."}},"deprecated":false,"x-internal":true}},"/siteMessage/queue_message":{"post":{"summary":"Queue a site message for a contact","description":"Internal: job callback, not a customer API. When a contact reaches a site message action in an automation, Hosted queues a job on the `site_messages` SQS queue and the queue-http-service posts it back here, authenticated with the primary admin's API key in the `api_key` query parameter. Queues the message for the contact in the site message store, with the current values of the personalization tags it uses, sets the message's last-sent date and records a `sent` site message event. Nothing is queued, and the answer is still 202, when the account does not have site messages, the contact has no email address or the message is already queued for them. The body is either the job fields themselves or the queue message with them under `data`; when `data` is present only `data` is read.","operationId":"queue-site-message","x-canonical-resource":"site_message","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SiteMessageQueueJob"},{"type":"object","description":"The SQS message body as the queue-http-service forwards it.","required":["data"],"properties":{"acctid":{"type":"integer","description":"ID of the account that queued the job. Not read."},"type":{"type":"string","description":"The job type, `queue_message`. Not read."},"data":{"$ref":"#/components/schemas/SiteMessageQueueJob"}}}]}}}},"responses":{"200":{"description":"No site message or no contact has the given ID, or `blockid` is 0 or not numeric; nothing was done. The body is empty."},"202":{"description":"Processed; the message is queued unless one of the cases above applies. The body is empty."},"400":{"description":"`subscriberid`, `messageid` or `blockid` is missing. The body is empty."},"500":{"description":"The body is not a JSON object","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always `Something went wrong on our end. Please try again later`."}}}}}}},"deprecated":false,"x-internal":true}},"/siteMessage/save_field_changes":{"post":{"summary":"Save a contact's changed fields for site messages","description":"Internal: job callback, not a customer API. When fields change on a contact who has been sent a site message, Hosted queues a job on the `site_messages` SQS queue and the queue-http-service posts it back here, authenticated with the primary admin's API key in the `api_key` query parameter. For each listed field that a site message uses, writes the contact's current value into the contact's stored data for that site message (the first one found that uses the field). Fields no site message uses, custom field IDs that do not exist, and contacts with no email address are skipped. The body is either the job fields themselves or the queue message with them under `data`; when `data` is present only `data` is read.","operationId":"save-site-message-field-changes","x-canonical-resource":"site_message","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SiteMessageFieldChangesJob"},{"type":"object","description":"The SQS message body as the queue-http-service forwards it.","required":["data"],"properties":{"acctid":{"type":"integer","description":"ID of the account that queued the job. Not read."},"type":{"type":"string","description":"The job type, `save_field_changes`. Not read."},"data":{"$ref":"#/components/schemas/SiteMessageFieldChangesJob"}}}]}}}},"responses":{"200":{"description":"No contact has this ID; nothing was done. The body is empty."},"202":{"description":"Saved. The body is empty."},"400":{"description":"`fields` or `subscriberid` is missing. The body is empty."},"500":{"description":"The body is not a JSON object","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Always `Something went wrong on our end. Please try again later`."}}}}}}},"deprecated":false,"x-internal":true}},"/siteTracking":{"get":{"summary":"Retrieve status","description":"Get site tracking status (enabled or disabled)","operationId":"retrieve-site-tracking-status","x-canonical-resource":"siteTracking","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"siteTracking\": {\n    \"enabled\": true\n  }\n}"}},"schema":{"type":"object","properties":{"siteTracking":{"type":"object","properties":{"enabled":{"type":"boolean","example":true,"default":true}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Enable/disable","description":"Enable or disable site tracking","operationId":"enable-disable-site-tracking","x-canonical-resource":"siteTracking","x-destructive":true,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"siteTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether site tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"siteTracking":{"enabled":true}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"siteTracking\": {\n    \"enabled\": true\n  }\n}"}},"schema":{"type":"object","properties":{"siteTracking":{"type":"object","properties":{"enabled":{"type":"boolean","example":true,"default":true}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-readme":{"code-samples":[{"language":"text","code":"{\n  \"siteTracking\": {\n    \"enabled\": false\n  }\n}","name":"Disable"}],"samples-languages":["text"]}}},"/siteTracking/code":{"get":{"summary":"Retrieve site tracking code","description":"Get site tracking code","operationId":"retrieve-site-tracking-code","x-canonical-resource":"siteTracking","responses":{"200":{"description":"200","content":{"text/plain":{"examples":{"Result":{"value":"<script type=\"text/javascript\">\n    (function(e,t,o,n,p,r,i){e.prismGlobalObjectAlias=n;e.pgo=e.pgo||function(){(e.pgo.q=e.pgo.q||[]).push(arguments)};e.pgo.l=(new Date).getTime();r=t.createElement(\"script\");r.src=o;r.async=true;i=t.getElementsByTagName(\"script\")[0];i.parentNode.insertBefore(r,i)})(window,document,\"https://prism.app-us1.com/prism.js\",\"pgo\");\n\n    pgo('setAccount', YOUR_ACCOUNT_ID);\n    pgo('setTrackByDefault', true);\n\n    pgo('process');\n</script>"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/siteTracking/{id}":{"put":{"summary":"Update site tracking by id","description":"Enables or disables site tracking, exactly like PUT /siteTracking: the id in the path is ignored. The body must carry siteTracking.enabled as a boolean. PATCH on this path does the same. Internal: an alias of PUT /siteTracking that is not part of the public API.","operationId":"update-site-tracking-by-id","x-canonical-resource":"siteTracking","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Ignored. The controller never reads it, so any value gives the same result as the same request without an id.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"siteTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether site tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"siteTracking":{"enabled":true}}},"Disable":{"value":{"siteTracking":{"enabled":false}}}}}}},"responses":{"200":{"description":"Site tracking was enabled or disabled. The body repeats the setting as siteTracking.enabled.","content":{"application/json":{"example":{"siteTracking":{"enabled":true}}}}},"422":{"description":"siteTracking.enabled is missing or is not a boolean. Nothing is changed."}}},"patch":{"summary":"Update site tracking by id (PATCH)","description":"Enables or disables site tracking, exactly like PUT /siteTracking: the id in the path is ignored. The body must carry siteTracking.enabled as a boolean. PUT on this path does the same. Internal: an alias of PUT /siteTracking that is not part of the public API.","operationId":"patch-site-tracking-by-id","x-canonical-resource":"siteTracking","x-internal":true,"x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Ignored. The controller never reads it, so any value gives the same result as the same request without an id.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"siteTracking":{"properties":{"enabled":{"type":"boolean","description":"Whether site tracking should be enabled"}},"required":["enabled"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Enable":{"value":{"siteTracking":{"enabled":true}}},"Disable":{"value":{"siteTracking":{"enabled":false}}}}}}},"responses":{"200":{"description":"Site tracking was enabled or disabled. The body repeats the setting as siteTracking.enabled.","content":{"application/json":{"example":{"siteTracking":{"enabled":true}}}}},"422":{"description":"siteTracking.enabled is missing or is not a boolean. Nothing is changed."}}}},"/siteTrackingDomains":{"post":{"summary":"Add a site tracking domain","description":"Add a domain to the site tracking whitelist by name. Site tracking must be enabled first (`PUT /api/3/siteTracking`) - adding a domain while it is disabled returns `403`.\n\nA name may begin with `*` to whitelist subdomains (for example `*.example.com`), and must otherwise match `/^\\*?[a-zA-Z0-9-.]*[a-zA-Z0-9]$/`: no scheme, no port, no path. Supply the bare domain, not a URL.\n\nThe response echoes the submitted object with `201`. This is the v3 equivalent of the API v2 `tracking/whitelist` action, which took a `domain` parameter and answered `{\"domain\": ..., \"success\": 1}`; v3 reports the outcome with the status code instead of a `success` flag. Use `POST /api/3/prism/urlWhitelistings` when you need to set the page pattern or the web personalization and conversations flags at the same time.","operationId":"add-a-site-tracking-domain","x-canonical-resource":"siteTrackingDomains","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"siteTrackingDomain":{"type":"object","properties":{"name":{"type":"string","description":"The domain to whitelist, optionally prefixed with `*` to include subdomains","default":"example.com"}},"required":["name"]}},"required":["siteTrackingDomain"]},"examples":{"Domain":{"value":{"siteTrackingDomain":{"name":"example.com"}}},"Domain and subdomains":{"value":{"siteTrackingDomain":{"name":"*.example.com"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"siteTrackingDomain\": {\n        \"name\": \"example.com\"\n    }\n}"}},"schema":{"type":"object","properties":{"siteTrackingDomain":{"type":"object","properties":{"name":{"type":"string","example":"example.com"}}}}}}}},"403":{"description":"Forbidden - site tracking is disabled","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The request could not be processed.\",\n            \"detail\": \"Site tracking is disabled.\",\n            \"code\": \"attribute-invalid\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"},"source":{"type":"object","properties":{"pointer":{"type":"string"}}}}}}}}}}},"422":{"description":"Unprocessable entity - name missing, invalid, or already whitelisted","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The request could not be processed.\",\n            \"detail\": \"The domain name is invalid.\",\n            \"code\": \"attribute-invalid\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"},"source":{"type":"object","properties":{"pointer":{"type":"string"}}}}}}}}}}}},"deprecated":false},"get":{"summary":"List all site tracking domains","description":"List every domain on the site tracking whitelist. Each entry is identified by its name; whitelisted domains have no id in this representation.\n\nThe collection is **empty when site tracking is disabled** rather than an error, so check `GET /api/3/siteTracking` before treating an empty list as \"no domains whitelisted\". Filtering, ordering and pagination are not supported.\n\nThis is the `whitelist` half of the API v2 `tracking/site/list` response - v3 splits the tracking status (`GET /api/3/siteTracking`) from the whitelist it applies to. For the underlying Prism whitelisting resources, including per-page rules, web personalization and conversations flags, use `GET /api/3/prism/urlWhitelistings` instead.","operationId":"list-all-site-tracking-domains","x-canonical-resource":"siteTrackingDomains","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"siteTrackingDomains\": [\n        {\n            \"name\": \"activecampaign.com\"\n        },\n        {\n            \"name\": \"example.com\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}},"schema":{"type":"object","properties":{"siteTrackingDomains":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"example.com"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":2}}}}}}}}},"deprecated":false}},"/siteTrackingDomains/{name}":{"delete":{"summary":"Remove a site tracking domain","description":"Remove a domain from the site tracking whitelist by name. The path segment is the domain itself, URL-encoded - no lookup step is needed, unlike `DELETE /api/3/prism/urlWhitelistings/{domainId}`, which requires the whitelisting id.\n\nSite tracking must be enabled; the request returns `403` while it is disabled, even for a domain that is on the whitelist. A domain that is not whitelisted returns `404` (API v2 `tracking/whitelist/remove` answered `200` with `success: 0`).\n\nReading or updating a single domain is not supported: `GET` and `PUT` on this path return `405` with `Allow: DELETE`.","operationId":"remove-a-site-tracking-domain","x-canonical-resource":"siteTrackingDomains","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"name","in":"path","required":true,"description":"The whitelisted domain to remove, URL-encoded (for example `%2A.example.com` for `*.example.com`)","schema":{"type":"string","default":"example.com"}}],"responses":{"204":{"description":"204 - no content"},"403":{"description":"Forbidden - site tracking is disabled","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The request could not be processed.\",\n            \"detail\": \"Site tracking is disabled.\",\n            \"code\": \"attribute-invalid\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"},"source":{"type":"object","properties":{"pointer":{"type":"string"}}}}}}}}}}},"404":{"description":"Not found - the domain is not on the whitelist","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The request could not be processed.\",\n            \"detail\": \"The domain name is not found on the whitelist.\",\n            \"code\": \"attribute-invalid\"\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"},"source":{"type":"object","properties":{"pointer":{"type":"string"}}}}}}}}}}}},"deprecated":false}},"/sms/10dlc/areacode":{"get":{"tags":["Areacodes"],"summary":"Get the account's saved or suggested 10DLC area code","description":"The area code chosen for the phone number of the account's 10DLC registration. When the account has saved one, during the registration wizard, the saved area code and its state are returned. When it has not, one is suggested from the address on the account's brand form: the first available area code for its state and postal code, then for its state alone, then for its country. A brand form whose country is anything other than exactly `US` or `CA`, including none, gets an Illinois area code instead: 312, then 773, then any Illinois area code. Takes no parameters. Requires the SMS registration permission.","operationId":"getSms10dlcAreacode","responses":{"200":{"description":"The saved area code, or the one suggested from the brand form","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedAreacodeResponse"},"example":{"areacode":{"state":"TX","areacode":512}}}}},"403":{"description":"The user may not manage SMS registration."},"404":{"description":"Nothing is saved and no area code was found: for a `US` or `CA` brand form, none for its address; for any other country, none in Illinois","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedAreacodeErrorResponse"},"examples":{"noneForBrandLocation":{"summary":"A brand in the United States or Canada","value":{"error":"Area code not found based on brand location data"}},"noneForIllinoisFallback":{"summary":"A brand with any other country","value":{"error":"Area code not found based on brand location data or Illinois fallback"}}}}}},"422":{"description":"Nothing is saved and the account has no brand form to suggest an area code from","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedAreacodeErrorResponse"},"example":{"error":"Brand location data not found"}}}},"500":{"description":"Nothing is saved and looking up the area codes available for the brand form's address failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedAreacodeErrorResponse"},"example":{"error":"Internal server error when looking up area codes"}}}}},"x-canonical-resource":"sms_registration"}},"/sms/10dlc/areacodes":{"get":{"tags":["Areacodes"],"summary":"List available 10DLC area codes","description":"The area codes that have local phone numbers available to buy for the account's 10DLC registration, narrowed by the optional `region`, `areacode` and `zipcode` filters. The query string is applied to the search unchanged and the list is returned as `{\"areacodes\": [...]}`. Requires the SMS registration permission.","operationId":"listSms10dlcAreacodes","parameters":[{"name":"region","in":"query","description":"Two-letter US state code to search in, such as `IL`, or a country code such as `US` to search the whole country. Left out, `US` is searched.","required":false,"schema":{"type":"string"},"example":"IL"},{"name":"areacode","in":"query","description":"Three-digit area code to search for, to check that it still has numbers available.","required":false,"schema":{"type":"string"},"example":"312"},{"name":"zipcode","in":"query","description":"US postal code to search near. A ZIP+4 is reduced to its first five digits.","required":false,"schema":{"type":"string"},"example":"62701"}],"responses":{"200":{"description":"The available area codes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreacodeListResponse"},"example":{"areacodes":[217,618,815,708,447]}}}},"403":{"description":"The user may not manage SMS registration."},"404":{"description":"No numbers are available for the search","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreacodeListErrorResponse"},"example":{"error":"Area code or endpoint not found"}}}},"500":{"description":"The area code lookup failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreacodeListErrorResponse"},"example":{"error":"SMS 10DLC get area codes failure: Server error"}}}}},"x-canonical-resource":"sms_registration"}},"/sms/broadcasts":{"post":{"tags":["Broadcasts"],"summary":"Create a new broadcast message","description":"Creates a new SMS broadcast message","operationId":"createBroadcast","x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastCreateRequest"}}}},"responses":{"201":{"description":"Broadcast created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastMessage"}}}},"400":{"description":"Invalid request data"},"403":{"description":"Insufficient permissions"}}},"get":{"tags":["Broadcasts"],"summary":"Get all broadcast messages","description":"Gets a paged list of all of a customer's broadcast messages with optional filtering","operationId":"listBroadcasts","x-canonical-resource":"sms_broadcast","parameters":[{"name":"offset","in":"query","description":"Offset for pagination","schema":{"type":"integer","default":0}},{"name":"limit","in":"query","description":"Number of items to return","schema":{"type":"integer","default":20}},{"name":"filters[name]","in":"query","description":"Filter by broadcast name","schema":{"type":"string"}},{"name":"filters[status]","in":"query","description":"Filter by broadcast status","schema":{"type":"string","enum":["draft","scheduled","sent","pending_review","sending"]}},{"name":"filters[type]","in":"query","description":"Filter by broadcast type (future feature)","schema":{"type":"string"}},{"name":"orders[field]","in":"query","description":"Order results by field (ASC or DESC)","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"start_date","in":"query","description":"Filter by start date (YYYY-MM-DD)","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Filter by end date (YYYY-MM-DD)","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastListResponse"}}}},"403":{"description":"Insufficient permissions"}}}},"/sms/broadcasts/ai":{"post":{"tags":["Broadcasts"],"summary":"Create broadcast with AI","description":"Generates a new SMS broadcast message using AI from a prompt and desired tone","operationId":"createAIBroadcast","x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIBroadcastCreateRequest"}}}},"responses":{"200":{"description":"AI broadcast generation request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIBroadcastRequestResponse"}}}}}},"put":{"tags":["Broadcasts"],"summary":"Update broadcast with AI","description":"Modifies an existing SMS broadcast message using AI from a prompt and desired tone","operationId":"updateAIBroadcast","x-canonical-resource":"sms_broadcast","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIBroadcastUpdateRequest"}}}},"responses":{"200":{"description":"AI broadcast update request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIBroadcastRequestResponse"}}}}}}},"/sms/broadcasts/ai/{Id}":{"get":{"tags":["Broadcasts"],"summary":"Get AI broadcast request status","description":"Retrieves the current execution status of an AI broadcast generation or update request","operationId":"getAIBroadcastStatus","x-canonical-resource":"sms_broadcast","parameters":[{"name":"Id","in":"path","required":true,"description":"Request ID from AI broadcast creation","schema":{"type":"string"}}],"responses":{"200":{"description":"AI broadcast status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIBroadcastStatus"}}}}}}},"/sms/broadcasts/export":{"post":{"tags":["Metrics","Exports","Broadcasts"],"summary":"Export broadcast metrics","description":"Export broadcast performance metrics as CSV","operationId":"exportBroadcastMetrics","x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"200":{"description":"Export generated successfully","content":{"text/csv":{"schema":{"type":"string"}}}}}}},"/sms/broadcasts/metrics":{"post":{"tags":["Metrics","Broadcasts"],"summary":"Get all broadcast metrics","description":"Returns sends, deliveries, replies, failures, opt-outs and clicks for each of the given broadcasts, plus revenue when SMS attribution is enabled. Needs one of the SMS reporting permissions.","operationId":"getBroadcastMetrics","parameters":[{"name":"start_date","in":"query","description":"Metrics range start, as Y-m-d in Central time (America/Chicago). Counted from the start of that day. Without it the range has no lower bound.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Metrics range end, as Y-m-d in Central time (America/Chicago). Counted to the end of that day. Without it the range has no upper bound.","schema":{"type":"string","format":"date"}},{"name":"currency","in":"query","description":"Three-letter ISO 4217 code to report revenue in. Without it revenue is 0. Used, and revenue returned, only when SMS attribution is enabled for the account.","schema":{"type":"string","example":"USD"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["ids"],"properties":{"ids":{"description":"IDs of the broadcasts to report on.","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false}}}},"responses":{"200":{"description":"Metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastMetricsResponse"}}}},"400":{"description":"The ids are not an array, the dates are malformed or inverted, or the currency is not a three-letter code.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What was wrong with the request.","type":"string"}},"type":"object"},"examples":{"Bad request":{"summary":"ids is not an array","value":{"message":"Invalid input: ids must be an array"}}}}}},"403":{"description":"The user holds none of the SMS permissions that allow viewing reports.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"The permissions the user lacks.","type":"string","example":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}},"type":"object"}}},"type":"object"},"examples":{"No permission":{"summary":"The user lacks every reporting permission","value":{"errors":[{"status":"403","detail":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}]}}}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false}},"/sms/broadcasts/metrics/snapshot":{"get":{"tags":["Metrics","Snapshots","Broadcasts"],"summary":"Get broadcast snapshot","description":"Returns totals across all broadcasts of the account in the date range. Needs one of the SMS reporting permissions.","operationId":"getBroadcastSnapshot","parameters":[{"name":"start_date","in":"query","description":"Snapshot range start, as Y-m-d in Central time (America/Chicago). Counted from the start of that day. Without it the range has no lower bound.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Snapshot range end, as Y-m-d in Central time (America/Chicago). Counted to the end of that day. Without it the range has no upper bound.","schema":{"type":"string","format":"date"}},{"name":"currency","in":"query","description":"Three-letter ISO 4217 code to report revenue in. Without it revenue is 0. Used, and revenue returned, only when SMS attribution is enabled for the account.","schema":{"type":"string","example":"USD"}}],"responses":{"200":{"description":"Snapshot retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"}}}},"400":{"description":"The currency is not a three-letter code.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What was wrong with the request.","type":"string"}},"type":"object"},"examples":{"Bad request":{"summary":"Bad currency","value":{"message":"Currency must be a 3-letter ISO code"}}}}}},"403":{"description":"The user holds none of the SMS permissions that allow viewing reports.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"The permissions the user lacks.","type":"string","example":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}},"type":"object"}}},"type":"object"},"examples":{"No permission":{"summary":"The user lacks every reporting permission","value":{"errors":[{"status":"403","detail":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}]}}}}}},"500":{"description":"The snapshot could not be computed.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed, in a fixed sentence.","type":"string"},"msg":{"description":"The message of the underlying error.","type":"string"}},"type":"object"},"examples":{"Server error":{"summary":"The request could not be processed","value":{"error":"An error occurred while processing the snapshot request","msg":"Connection refused"}}}}}}},"x-canonical-resource":"sms_broadcast"},"post":{"tags":["Metrics","Snapshots","Broadcasts"],"summary":"Get broadcast snapshot","description":"Returns totals across the given broadcasts. When the body has no ids, the broadcasts are the ones found from the query string filters through the broadcast ids lookup; when that finds none, every total is 0. The dates are checked only in that case. Needs one of the SMS reporting permissions.","operationId":"getBroadcastSnapshotByIds","parameters":[{"name":"start_date","in":"query","description":"Snapshot range start, as Y-m-d in Central time (America/Chicago). Counted from the start of that day. Without it the range has no lower bound.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Snapshot range end, as Y-m-d in Central time (America/Chicago). Counted to the end of that day. Without it the range has no upper bound.","schema":{"type":"string","format":"date"}},{"name":"currency","in":"query","description":"Three-letter ISO 4217 code to report revenue in. Without it revenue is 0. Used, and revenue returned, only when SMS attribution is enabled for the account.","schema":{"type":"string","example":"USD"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"properties":{"ids":{"description":"IDs of the broadcasts to total. Leave it out to select broadcasts with the query string filters.","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false}}}},"responses":{"200":{"description":"Snapshot retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"}}}},"400":{"description":"The currency is not a three-letter code ({\"message\"}), or, when the body has no ids, the dates are malformed or inverted ({\"error\"}). The ids lookup can also answer with its own status, or 500, in the {\"error\"} shape.","content":{"application/json":{"schema":{"oneOf":[{"required":["message"],"properties":{"message":{"description":"What was wrong with the currency.","type":"string"}},"type":"object"},{"required":["error"],"properties":{"error":{"description":"What was wrong with the dates, or why the broadcast ids could not be found.","type":"string"}},"type":"object"}]},"examples":{"Bad currency":{"summary":"The currency is not a three-letter code","value":{"message":"Currency must be a 3-letter ISO code"}},"Bad dates":{"summary":"The dates are inverted and the body has no ids","value":{"error":"End date must be after start date"}}}}}},"403":{"description":"The user holds none of the SMS permissions that allow viewing reports.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"The permissions the user lacks.","type":"string","example":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}},"type":"object"}}},"type":"object"},"examples":{"No permission":{"summary":"The user lacks every reporting permission","value":{"errors":[{"status":"403","detail":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}]}}}}}},"500":{"description":"The snapshot could not be computed.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed, in a fixed sentence.","type":"string"},"msg":{"description":"The message of the underlying error.","type":"string"}},"type":"object"},"examples":{"Server error":{"summary":"The request could not be processed","value":{"error":"An error occurred while processing the snapshot request","msg":"Connection refused"}}}}}}},"x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false}},"/sms/broadcasts/metrics/{broadcastId}/failures":{"get":{"tags":["Failures","Broadcasts","Metrics"],"summary":"Get broadcast failure details","description":"Returns the failed messages of one broadcast grouped by error code, with the number of messages for each. Needs one of the SMS reporting permissions.","operationId":"getBroadcastFailures","parameters":[{"name":"broadcastId","in":"path","description":"ID of the broadcast","required":true,"schema":{"type":"integer"}},{"name":"start_date","in":"query","description":"Failure range start, as Y-m-d in Central time (America/Chicago). Counted from the start of that day. Without it the range has no lower bound.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Failure range end, as Y-m-d in Central time (America/Chicago). Counted to the end of that day. Without it the range has no upper bound.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Failure details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailureDetailsResponse"}}}},"400":{"description":"The dates are malformed or inverted.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What was wrong with the request.","type":"string"}},"type":"object"},"examples":{"Bad request":{"summary":"End before start","value":{"message":"End date must be after start date"}}}}}},"403":{"description":"The user holds none of the SMS permissions that allow viewing reports.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"The permissions the user lacks.","type":"string","example":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}},"type":"object"}}},"type":"object"},"examples":{"No permission":{"summary":"The user lacks every reporting permission","value":{"errors":[{"status":"403","detail":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}]}}}}}}},"x-canonical-resource":"sms_broadcast"}},"/sms/broadcasts/{broadcastId}/recipients":{"get":{"tags":["Recipients","Broadcasts"],"summary":"Get broadcast recipients","description":"Returns the contacts who were sent a broadcast, one page at a time, with their delivery, clicks, replies and opt-out. Needs one of the SMS reporting permissions.","operationId":"getBroadcastRecipients","parameters":[{"name":"broadcastId","in":"path","description":"ID of the broadcast","required":true,"schema":{"type":"integer"}},{"name":"start_date","in":"query","description":"Send range start, as Y-m-d in Central time (America/Chicago). Counted from the start of that day. Without it the range has no lower bound.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","description":"Send range end, as Y-m-d in Central time (America/Chicago). Counted to the end of that day. Without it the range has no upper bound.","schema":{"type":"string","format":"date"}},{"name":"filters[deliverability][]","in":"query","description":"Only recipients whose message was delivered or failed. Passing both applies no filter.","schema":{"type":"array","items":{"type":"string","enum":["deliveries","failures"]}}},{"name":"filters[engagement][]","in":"query","description":"Only recipients who clicked, replied or opted out.","schema":{"type":"array","items":{"type":"string","enum":["clicks","replies","optOuts"]}}},{"name":"search","in":"query","description":"Only recipients whose contact data contains this text.","schema":{"type":"string"}},{"name":"order","in":"query","description":"Sort order, as order[field]=asc or order[field]=desc, with the direction in lowercase. Fields: name, phone, sentDate, clicks, deliverability, optOut, replies. Several fields sort in the order given, and a pair with an unknown field or direction is skipped. A request whose pairs are all skipped fails with a 500.","style":"deepObject","explode":true,"schema":{"type":"object","example":{"sentDate":"desc"}}},{"name":"offset","in":"query","description":"Number of recipients to skip","schema":{"type":"integer","default":0}},{"name":"limit","in":"query","description":"Number of recipients to return, at most 100","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Recipients retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipientsResponse"}}}},"400":{"description":"The dates are malformed or inverted.","content":{"application/json":{"schema":{"properties":{"message":{"description":"What was wrong with the request.","type":"string"}},"type":"object"},"examples":{"Bad request":{"summary":"End before start","value":{"message":"End date must be after start date"}}}}}},"403":{"description":"The user holds none of the SMS permissions that allow viewing reports.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"The errors that refused the request.","type":"array","items":{"properties":{"status":{"description":"HTTP status of the error.","type":"string","example":"403"},"detail":{"description":"The permissions the user lacks.","type":"string","example":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}},"type":"object"}}},"type":"object"},"examples":{"No permission":{"summary":"The user lacks every reporting permission","value":{"errors":[{"status":"403","detail":"Missing SMS permission: one of management.reporting, campaigns.view, campaigns.manage, campaigns.send"}]}}}}}},"500":{"description":"The recipients could not be read.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What failed, in a fixed sentence.","type":"string"},"msg":{"description":"The message of the underlying error.","type":"string"}},"type":"object"},"examples":{"Server error":{"summary":"The request could not be processed","value":{"error":"An error occurred while processing the request.","msg":"Connection refused"}}}}}}},"x-canonical-resource":"sms_broadcast"}},"/sms/broadcasts/{broadcastId}/recipients/export":{"post":{"tags":["Recipients","Exports","Broadcasts","Metrics"],"summary":"Export broadcast recipients","description":"Export recipient data as CSV including full contact records","operationId":"exportBroadcastRecipients","x-canonical-resource":"sms_broadcast","x-destructive":false,"x-bulk-operation":false,"parameters":[{"name":"broadcastId","in":"path","required":true,"description":"Broadcast ID","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"engagement":{"type":"array","items":{"type":"string"}},"deliverability":{"type":"array","items":{"type":"string"}},"search":{"type":"string"},"order":{"type":"object"}}}}}},"responses":{"200":{"description":"Export generated successfully","content":{"text/csv":{"schema":{"type":"string"}}}}}}},"/sms/broadcasts/{id}":{"delete":{"tags":["Broadcasts"],"summary":"Delete broadcast message","description":"Performs a soft-delete on the requested message","operationId":"deleteBroadcast","x-canonical-resource":"sms_broadcast","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Broadcast ID","schema":{"type":"integer"}}],"responses":{"200":{"description":"Broadcast deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastMessage"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Broadcast not found"}}},"get":{"tags":["Broadcasts"],"summary":"Get broadcast message","description":"Retrieves the full details for one broadcast message","operationId":"getBroadcast","x-canonical-resource":"sms_broadcast","parameters":[{"name":"id","in":"path","required":true,"description":"Broadcast ID","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastMessage"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Broadcast not found"}}},"put":{"tags":["Broadcasts"],"summary":"Update broadcast message","description":"Updates an existing broadcast message","operationId":"updateBroadcast","x-canonical-resource":"sms_broadcast","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"Broadcast ID","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastUpdateRequest"}}}},"responses":{"200":{"description":"Broadcast updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastMessage"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Broadcast not found"}}}},"/sms/credits":{"get":{"tags":["Credits"],"summary":"Get current sms credit use data","description":"Retrieve the current period's sms credit usage and remaining balance","operationId":"getSmsCreditData","x-canonical-resource":"sms_credits","responses":{"200":{"description":"Sms Credits for this period","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}}}}},"/sms/help-auto-response":{"get":{"summary":"Retrieve the SMS HELP auto-response settings","description":"Every SMS registration the account can configure a HELP auto-response for (US, AU, DK, GB and toll-free, once approved), with its saved reply, its status, the sender names and languages it can use and the reply templates, plus the support number a new reply starts from and the segment limit. Internal: written for the SMS Sending options page.","operationId":"retrieve-sms-help-auto-response-settings","responses":{"200":{"description":"The settings of every registration the account can configure."},"403":{"description":"The user may not manage SMS sending options."},"404":{"description":"The feature is not enabled for the account."}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/sms/help-auto-response/{registration}":{"put":{"summary":"Save the SMS HELP auto-response of one registration","description":"Validates the values against the options the settings list for the registration, renders the reply (it must fit one SMS segment) and stores it, replacing the registration's previous reply. Internal: written for the SMS Sending options page.","operationId":"update-sms-help-auto-response","parameters":[{"name":"registration","in":"path","description":"The registration: US, AU, DK, GB or TOLL_FREE.","required":true,"schema":{"type":"string","enum":["US","AU","DK","GB","TOLL_FREE"]},"example":"US"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"language":{"description":"A reply language the registration offers.","type":"string","example":"en"},"sender_name_address_id":{"description":"The address whose SMS sender name starts the reply.","type":"integer","example":1},"support_number":{"description":"The support phone number, with its country code.","type":"string","example":"+1 229 441 2401"}},"type":"object"}}}},"responses":{"200":{"description":"The saved registration, as the settings list it."},"403":{"description":"The user may not manage SMS sending options."},"404":{"description":"The feature is not enabled for the account."},"422":{"description":"A value breaks a rule; errors lists each field and its message."}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/sms/lists":{"get":{"tags":["Broadcasts"],"summary":"Get all broadcast lists","description":"Gets a paged list of all broadcast lists (SMS channel)","operationId":"listBroadcastLists","parameters":[{"name":"offset","in":"query","description":"Offset for pagination","schema":{"type":"integer","default":0}},{"name":"limit","in":"query","description":"Number of items to return","schema":{"type":"integer","default":20}},{"name":"filters[name]","in":"query","description":"Filter by list name","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastListsResponse"}}}}},"x-canonical-resource":"lists"}},"/statsActivityItem/get":{"get":{"summary":"List recent activity items","description":"Up to 25 recent contact activities of the requested types, one per contact, contacts with an avatar first, then newest first.","operationId":"list-stats-activity-items","x-canonical-resource":"activity","parameters":[{"name":"types[]","in":"query","required":true,"style":"form","explode":true,"description":"Activity types to include.","schema":{"type":"array","items":{"type":"string","enum":["subscribe","twitter","facebook","unsubscribe","open","click","forward","update","reply","read"]}}},{"name":"timeFormat","in":"query","description":"Date format template applied to the activity timestamp.","schema":{"type":"string"}},{"name":"list","in":"query","description":"Restrict to this list.","schema":{"type":"integer","format":"int32"}},{"name":"campaign","in":"query","description":"Restrict to this campaign.","schema":{"type":"integer","format":"int32"}},{"name":"onlyFaces","in":"query","description":"Set to a truthy value to return only contacts with an avatar.","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"statsActivityItems":{"type":"array","items":{"$ref":"#/components/schemas/StatsActivityItem"}}}}}}},"400":{"description":"`types` missing or contains an unknown type"},"404":{"description":"`list` or `campaign` does not exist"},"405":{"description":"Method other than GET; the response carries `Allow: GET`"}},"deprecated":false}},"/statsActivityItem/get_series":{"get":{"summary":"List recent automation entries","description":"Up to 25 contacts who most recently entered the automation, contacts with an avatar first.","operationId":"list-automation-stats-activity-items","x-canonical-resource":"automation","parameters":[{"name":"seriesId","in":"query","description":"ID of the automation.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"statsActivityItems":{"type":"array","items":{"$ref":"#/components/schemas/StatsActivityItem"}}}}}}},"404":{"description":"No automation with this ID"},"405":{"description":"Method other than GET; the response carries `Allow: GET`"}},"deprecated":false}},"/stripo/config":{"get":{"summary":"Stripo config","description":"The settings the campaign editor (Stripo) needs to start: the plugin API base URL, the editor language and the account's brand kits for the colour picker. While the campaign-editor-migration flag is on, the response also carries the settings of the UIEditor v2 editor: its API and co-editing URLs, the link actions saved on the campaign, the conditional-content fields and operators, and whether the abandoned-cart and browse-abandonment blocks are offered. With the flag off those keys are left out entirely. Internal: read by the campaign editor in the app.","operationId":"stripo-config","parameters":[{"name":"campaignId","in":"query","description":"ID of the campaign the editor is opened for. It must exist and be a campaign the user can access. Left out, the settings that depend on a campaign (link actions and automation-only blocks) come back empty.","schema":{"type":"integer"},"example":174}],"responses":{"200":{"description":"The editor settings","content":{"application/json":{"schema":{"required":["stripoApiBaseUrl","localeCode","colorPickerBrandKits"],"properties":{"stripoApiBaseUrl":{"description":"Base URL of the Stripo plugin API: the configured Stripo host followed by its path prefix.","type":"string","example":"https://plugins.stripo.email/stripo-plugin-api-gateway/api/v1"},"localeCode":{"description":"Editor language: the account language mapped to one of the languages the editor ships, en when there is none.","type":"string","example":"en"},"colorPickerBrandKits":{"description":"The account's brand kits, offered in the colour picker. Empty when the account has none.","type":"array","items":{"description":"One brand kit, as the brand-kit service returns it.","type":"object"}},"stripoV2ApiBaseUrl":{"description":"Base URL of the UIEditor v2 API. Null when the v2 host is not configured. Present only while the campaign-editor-migration flag is on.","type":["string","null"],"example":"https://stripo-v2.example.com/api/v1"},"stripoCoeditingBasePath":{"description":"Base URL of the v2 co-editing service. Null when the v2 host is not configured. Present only while the campaign-editor-migration flag is on.","type":["string","null"],"example":"https://stripo-v2.example.com/coediting"},"stripoCoeditingWsUrl":{"description":"WebSocket URL of the v2 co-editing service. Null when the v2 host is not configured. Present only while the campaign-editor-migration flag is on.","type":["string","null"],"example":"wss://stripo-v2.example.com/coediting/ws/coediting"},"linkActions":{"description":"The link actions saved on the campaign, keyed by link, each a list of actions. Empty when campaignId is left out. Present only while the campaign-editor-migration flag is on.","type":"object","additionalProperties":{"type":"array","items":{"properties":{"action":{"description":"The action type.","type":["string","null"]},"value":{"description":"The value the action carries.","type":["string","null"]}},"type":"object"}}},"conditionalFields":{"description":"The fields the conditional-content block can test, as field value to display name. Includes custom-object fields when campaignId belongs to an automation. Present only while the campaign-editor-migration flag is on.","type":"object","additionalProperties":{"type":"string"}},"conditionalOperators":{"description":"The comparison operators the conditional-content block offers, as operator value to display name. Present only while the campaign-editor-migration flag is on.","type":"object","additionalProperties":{"type":"string"}},"abandonedCartBlockOption":{"description":"How the abandoned-cart block is offered. All three are false when campaignId does not belong to an automation. Present only while the campaign-editor-migration flag is on.","properties":{"show_widget":{"description":"Whether the block is offered in the editor sidebar.","type":"boolean"},"show_upsell":{"description":"Whether an upgrade prompt is shown in place of the block.","type":"boolean"},"show_trigger_warning":{"description":"Whether to warn that the automation's trigger does not suit the block.","type":"boolean"}},"type":"object"},"browseAbandonmentBlockOption":{"description":"How the browse-abandonment block is offered. All three are false when campaignId does not belong to an automation. Present only while the campaign-editor-migration flag is on.","properties":{"show_widget":{"description":"Whether the block is offered in the editor sidebar.","type":"boolean"},"show_upsell":{"description":"Whether an upgrade prompt is shown in place of the block.","type":"boolean"},"show_trigger_warning":{"description":"Whether to warn that the automation's trigger does not suit the block.","type":"boolean"}},"type":"object"}},"type":"object"}}}},"422":{"description":"campaignId was refused: it is not positive, not a campaign, or not one the user can access.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error per refused parameter.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the parameter was refused.","type":"string","example":"Provided campaign ID \"177\" does not exist"},"source":{"description":"Which parameter was refused.","properties":{"pointer":{"description":"The parameter, as /data/attributes/ followed by its name.","type":"string","example":"/data/attributes/campaignId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/stripo/personalizationTags":{"get":{"summary":"Personalization Tags","description":"The personalization tags the campaign editor offers, grouped by category (contacts, message, accounts, deals, social, e-commerce and so on). Which groups are returned depends on the tags the user is entitled to and on feature flags. scope narrows the list to the named groups, and campaignId lets tags that depend on the campaign, such as custom-object tags, resolve against it. Internal: backs the personalization menu of the campaign editor in the app.","operationId":"personalization-tags","parameters":[{"name":"scope","in":"query","description":"Comma-separated group ids to return: contacts, accounts, deals, customobjects, message, messageVariables, social, surveymonkey, dropbox, ecom. Left out, every group is returned.","schema":{"type":"string"},"example":"contacts,message"},{"name":"campaignId","in":"query","description":"ID of the campaign the tags are for, so tags that depend on the campaign resolve against it. It must exist.","schema":{"type":"integer"},"example":174}],"responses":{"200":{"description":"The tag groups, in the order the editor shows them","content":{"application/json":{"schema":{"type":"array","items":{"properties":{"type":{"description":"Kind of group: standard, app or customobjects.","type":"string","example":"standard"},"id":{"description":"Identifier of the group. It is the value scope matches against.","type":"string","example":"contacts"},"category":{"description":"Display name of the group.","type":"string","example":"Contacts"},"entries":{"description":"The tags in the group.","type":"array","items":{"properties":{"value":{"description":"The tag as written into the email.","type":"string","example":"%EMAIL%"},"label":{"description":"Display name of the tag.","type":"string","example":"Email Address"},"resolves":{"description":"What the tag becomes at send time: a link, plain text or HTML.","type":"string","enum":["url","text","html"],"example":"text"}},"type":"object"}}},"type":"object"}}}}},"422":{"description":"A query parameter was refused: scope names a group that does not exist, or campaignId is not positive or not a campaign.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error per refused parameter.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the parameter was refused.","type":"string","example":"Invalid scope value: foo. Allowed values are: contacts, accounts, deals, customobjects, message, messageVariables, social, surveymonkey, dropbox, ecom"},"source":{"description":"Which parameter was refused.","properties":{"pointer":{"description":"The parameter, as /data/attributes/ followed by its name.","type":"string","example":"/data/attributes/campaignId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"personalizations","x-internal":true}},"/stripo/stripoAuth":{"get":{"summary":"Retrieve a Stripo editor auth token","description":"Mints a token for the Stripo email editor plugin by calling the Stripo plugin authentication endpoint with the plugin id and secret key Hosted is configured with, and returns it for the editor in the browser to start with. The token has the default Stripo role, not the privileged api role Hosted keeps server-side for version history. Takes no parameters. Internal: backs the drag-and-drop email editor in the app.","operationId":"retrieve-stripo-auth-token","responses":{"200":{"description":"The token.","content":{"application/json":{"schema":{"required":["token"],"properties":{"token":{"description":"Stripo plugin auth token, passed to the editor as it is.","type":"string"}},"type":"object"}}}},"500":{"description":"The Stripo authentication endpoint could not be reached or answered without a token. The body is the generic API error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Fixed text; the cause is logged, not returned.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/stripo/stripoAuthV2":{"get":{"summary":"Retrieve an auth token for version 2 of the Stripo editor","description":"Mints a token for version 2 of the Stripo email editor (UIEditor v2) by calling the stripo-plugin-api-gateway server-side, so the browser never calls the gateway itself. The token has the user role and names the current user as <accountId>_<userId>, so co-editing tells apart users of different accounts. Answers 404, as if the endpoint did not exist, while the campaign-editor-migration feature flag is off for the account. Takes no parameters. Internal: backs the version 2 campaign editor in the app.","operationId":"retrieve-stripo-v2-auth-token","responses":{"200":{"description":"The token.","content":{"application/json":{"schema":{"required":["token"],"properties":{"token":{"description":"UIEditor v2 auth token, passed to the editor as it is.","type":"string"}},"type":"object"}}}},"404":{"description":"The campaign-editor-migration feature flag is off for the account.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string.","type":"string","example":"404"},"detail":{"description":"Always empty.","type":"string","example":""}},"type":"object"}}},"type":"object"}}}},"503":{"description":"The gateway is not configured on this host, could not be reached, or answered without a token.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string.","type":"string","example":"503"},"detail":{"description":"Names the missing configuration, or is a fixed failure message. The gateway error itself is never returned.","type":"string","example":"Failed to obtain UIEditor v2 auth token"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/stripo/versions":{"get":{"summary":"List versions of the editor content of a campaign message","description":"Lists entries from the Stripo draft version history of one campaign message. Stripo keeps the history under the account, campaign and message; Hosted reads it server-side with a privileged Stripo token and returns the entries as Stripo sends them. Hosted adds entries itself when it changes the content, for example after an AI edit or a restore. The id of an entry is the patchId that GET /stripo/versions/markup and POST /stripo/versions/restore take. A failure talking to Stripo is answered with HTTP 200 and an error body whose meta.status is 502, not with a 5xx, so check for error. Internal: backs the version history of the campaign editor in the app.","operationId":"list-stripo-message-versions","parameters":[{"name":"campaignId","in":"query","description":"ID of the campaign. It must exist and be a campaign the user can access.","required":true,"schema":{"type":"integer"},"example":174},{"name":"messageId","in":"query","description":"ID of the message of the campaign whose versions to read. Left out, the first message of the campaign is used. It must be a message of campaignId.","schema":{"type":"integer"},"example":180},{"name":"limit","in":"query","description":"Most entries to return, 1 to 100. Left out, 5.","schema":{"type":"integer"},"example":5},{"name":"offset","in":"query","description":"Entries to skip before the first one returned, for paging. Left out, 0.","schema":{"type":"integer"},"example":5}],"responses":{"200":{"description":"The versions, or an error body when Stripo could not be read.","content":{"application/json":{"schema":{"oneOf":[{"description":"The versions.","required":["versions"],"properties":{"versions":{"description":"Version-history entries in the order Stripo returns them; empty when Stripo returns none.","type":"array","items":{"description":"One version-history entry, passed through from Stripo unchanged.","properties":{"id":{"description":"Id Stripo gives the version. Pass it as patchId to read or restore the version."}},"type":"object"}}},"type":"object"},{"description":"Stripo could not be reached or did not answer 200.","required":["error","meta"],"properties":{"error":{"description":"What failed.","type":"string","example":"Error calling Stripo versionhistory list endpoint"},"meta":{"description":"The status the failure stands for; the HTTP status itself is 200.","required":["status"],"properties":{"status":{"description":"Always 502.","type":"integer","enum":[502],"example":502}},"type":"object"}},"type":"object"}]}}}},"404":{"description":"messageId was left out and the campaign has no message.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string.","type":"string","example":"404"},"detail":{"description":"Names the campaign.","type":"string","example":"Campaign 174 has no messages"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"A query parameter was refused: campaignId is missing, not positive, not a campaign or not one the user can access; messageId is not positive, not a message or not a message of the campaign; limit is outside 1 to 100; or offset is negative.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error per refused parameter.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the parameter was refused.","type":"string","example":"Campaign ID is required"},"source":{"description":"Which parameter was refused.","properties":{"pointer":{"description":"The parameter, as /data/attributes/ followed by its name.","type":"string","example":"/data/attributes/campaignId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"message","x-internal":true}},"/stripo/versions/markup":{"get":{"summary":"Retrieve the markup of one version of a campaign message","description":"Reads the editor HTML of one entry in the Stripo draft version history of a campaign message, server-side with a privileged Stripo token, and changes nothing. Use it to preview a version before restoring it with POST /stripo/versions/restore. A failure talking to Stripo, including Stripo reporting an error for the patchId, is answered with HTTP 200 and an error body whose meta.status is 502, not with a 5xx, so check for error. Internal: backs the version preview of the campaign editor in the app.","operationId":"retrieve-stripo-message-version-markup","parameters":[{"name":"limit","in":"query","description":"Not used by this endpoint. It is still checked as on GET /stripo/versions, so a value outside 1 to 100 is refused with 422.","schema":{"type":"integer"},"example":5},{"name":"offset","in":"query","description":"Not used by this endpoint. It is still checked as on GET /stripo/versions, so a negative value is refused with 422.","schema":{"type":"integer"},"example":5},{"name":"patchId","in":"query","description":"Which version to read: the id of an entry returned by GET /stripo/versions for the same campaign and message.","required":true,"schema":{"type":"string"}},{"name":"campaignId","in":"query","description":"ID of the campaign. It must exist and be a campaign the user can access.","required":true,"schema":{"type":"integer"},"example":174},{"name":"messageId","in":"query","description":"ID of the message of the campaign whose versions to read. Left out, the first message of the campaign is used. It must be a message of campaignId.","schema":{"type":"integer"},"example":180}],"responses":{"200":{"description":"The markup of the version, or an error body when Stripo could not be read.","content":{"application/json":{"schema":{"oneOf":[{"description":"The markup.","required":["html"],"properties":{"html":{"description":"Editor HTML of the version as Stripo stored it, not compiled for sending.","type":"string"}},"type":"object"},{"description":"Stripo could not be reached, did not answer 200, reported an error, or answered without HTML.","required":["error","meta"],"properties":{"error":{"description":"What failed, including the error Stripo reported when it reported one.","type":"string","example":"Error calling Stripo versionhistory markup endpoint"},"meta":{"description":"The status the failure stands for; the HTTP status itself is 200.","required":["status"],"properties":{"status":{"description":"Always 502.","type":"integer","enum":[502],"example":502}},"type":"object"}},"type":"object"}]}}}},"404":{"description":"messageId was left out and the campaign has no message.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string.","type":"string","example":"404"},"detail":{"description":"Names the campaign.","type":"string","example":"Campaign 174 has no messages"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"A query parameter was refused: patchId is missing or empty; campaignId is missing, not positive, not a campaign or not one the user can access; messageId is not positive, not a message or not a message of the campaign; or limit or offset is out of range.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error per refused parameter.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the parameter was refused.","type":"string","example":"patchId is required"},"source":{"description":"Which parameter was refused.","properties":{"pointer":{"description":"The parameter, as /data/attributes/ followed by its name.","type":"string","example":"/data/attributes/patchId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"message","x-internal":true}},"/stripo/versions/restore":{"post":{"summary":"Restore a campaign message to an earlier version","description":"Replaces the current content of a campaign message with one entry from its Stripo draft version history. Hosted fetches the editor HTML of the version from Stripo, compiles it with the current CSS of the message, and in one transaction writes the editor HTML to the editor markup of the message and the compiled HTML to the message; the plain-text body is regenerated as well unless the campaign manages its text by hand. It then records the restored content as a new version-history entry named Restore, best-effort: that step never fails the call. The campaign must still be modifiable. A failure after validation is answered with HTTP 200 and an error body whose meta.status says what failed (502 Stripo, 404 a missing record, 500 anything else), not with that status, so check for error. Internal: backs restoring a version from the version history of the campaign editor in the app.","operationId":"restore-stripo-message-version","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreVersionRequest"}}}},"responses":{"200":{"description":"The restored content, or an error body when the restore failed. Nothing is written when Stripo fails, and a failure while writing rolls the write back.","content":{"application/json":{"schema":{"oneOf":[{"description":"The content now on the message.","required":["html","css","messageId"],"properties":{"html":{"description":"The restored editor HTML, as now stored in the editor markup of the message.","type":"string"},"css":{"description":"Editor CSS of the message, which the restore leaves unchanged; empty when there is none.","type":"string"},"messageId":{"description":"Id of the message restored: the first message of the campaign when messageId was left out.","type":"integer","example":180}},"type":"object"},{"description":"The restore failed.","required":["error","meta"],"properties":{"error":{"description":"What failed.","type":"string","example":"Error calling Stripo versionhistory markup endpoint"},"meta":{"description":"The status the failure stands for; the HTTP status itself is 200.","required":["status"],"properties":{"status":{"description":"502 when Stripo could not be read or the HTML could not be compiled, 404 when a record the restore needs, such as the editor markup of the message, is missing, 500 for any other failure.","type":"integer","enum":[404,500,502],"example":502}},"type":"object"}},"type":"object"}]}}}},"400":{"description":"The body is empty or not a JSON object, or messageId was left out and the campaign has no message.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code, as a string.","type":"string","example":"400"},"detail":{"description":"What was wrong.","type":"string","example":"Campaign 174 has no messages"}},"type":"object"}}},"type":"object"}}}},"422":{"description":"A body field was refused: campaignId is missing, not positive, not a campaign, not one the user can access, or not modifiable (only a draft, scheduled, paused or disabled campaign, or the campaign of an automation, is); messageId is not positive, not a message or not a message of the campaign; or patchId is missing, empty or not a string.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error per refused field.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always Invalid attribute.","type":"string","example":"Invalid attribute"},"detail":{"description":"Why the field was refused.","type":"string","example":"Campaign is not modifiable."},"source":{"description":"Which field was refused.","properties":{"pointer":{"description":"The field, as /data/attributes/ followed by its name.","type":"string","example":"/data/attributes/campaignId"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"message","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/subscriberEmails/verification":{"get":{"summary":"Check whether an email address is on a verified domain","description":"Says whether the domain of an email address is one of the account's verified sending domains. The deal email composer calls it with the sender address and shows a warning when the domain is not verified. The check only runs when both the CRM and the campaign test send verified-domain rules are on for the account. When either is off, domain_verified is always true. Otherwise it is true only when the part after the @ matches a sending domain the account has verified, so an email without @, or no email, gives false. The Content-Type header is json rather than application/json.","operationId":"retrieve-email-domain-verification","parameters":[{"name":"email","in":"query","description":"The sender email address to check. The text after the first @, up to any second @, is the domain checked.","required":false,"schema":{"type":"string"},"example":"sam@example.com"}],"responses":{"200":{"description":"Whether the domain is verified.","content":{"application/json":{"schema":{"required":["domain_verified"],"properties":{"domain_verified":{"description":"True when the domain is verified or the check is off for the account.","type":"boolean","example":true}},"type":"object"},"example":{"domain_verified":true}}}}},"x-canonical-resource":"activecampaign_account","x-internal":true}},"/syncs":{"get":{"summary":"List database syncs","description":"The database syncs on the account. A user other than the primary admin sees only the syncs that write to lists they can access. Every sync is returned in one response; there is no paging. Internal: backs the Database Sync page in the app.","operationId":"list-all-database-syncs","parameters":[{"name":"orderBy","in":"query","description":"What to sort by: the sync name, the source database name, or when the sync last ran. Case-sensitive; any other value sorts by name.","required":false,"schema":{"type":"string","default":"name","enum":["name","database","lastRun"]}},{"name":"direction","in":"query","description":"Sort direction: `ASC` or `DESC`, in any letter case (`desc` sorts descending too). Any other value sorts ascending.","required":false,"schema":{"type":"string","default":"ASC"},"example":"DESC"}],"responses":{"200":{"description":"The syncs, in the order asked for.","content":{"application/json":{"schema":{"properties":{"syncs":{"type":"array","items":{"$ref":"#/components/schemas/SyncJob"}},"meta":{"properties":{"total":{"description":"Number of syncs returned.","type":"integer","example":1}},"type":"object"}},"type":"object"},"example":{"syncs":[{"id":"7","name":"Nightly CRM import","listId":"3","destination":"1","host":"db.example.com","database":"crm","username":"reader","hasPassword":true,"type":"mysql","charset":"utf8","table":"customers","query":"","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"deleteAll":false,"updateExisting":true,"sendLastMessage":false,"sendResponder":false,"instantResponder":false,"optIn":false,"sentResponders":[],"lastRun":"2026-10-01 04:00:00"}],"meta":{"total":1}}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}}},"x-canonical-resource":"import","x-internal":true},"post":{"summary":"Create a database sync","description":"Saves a new database sync. Nothing is read from the source database and no run is started: test the connection with POST /syncs/connection and start a run with POST /syncs/{id}/run. The sync is owned by the calling user. Internal: backs the Database Sync wizard in the app.","operationId":"create-a-database-sync","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSyncJobRequest"},"example":{"name":"Nightly CRM import","listId":3,"host":"db.example.com","database":"crm","username":"reader","password":"s3cr3t","table":"customers","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"updateExisting":true}}}},"responses":{"201":{"description":"Created. The body is the saved sync.","content":{"application/json":{"schema":{"properties":{"sync":{"$ref":"#/components/schemas/SyncJob"}},"type":"object"},"example":{"sync":{"id":"7","name":"Nightly CRM import","listId":"3","destination":"1","host":"db.example.com","database":"crm","username":"reader","hasPassword":true,"type":"mysql","charset":"utf8","table":"customers","query":"","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"deleteAll":false,"updateExisting":true,"sendLastMessage":false,"sendResponder":false,"instantResponder":false,"optIn":false,"sentResponders":[],"lastRun":"2026-10-01 04:00:00"}}}}},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, the account's plan does not include Database Sync, or the user cannot access `listId` (`detail` names the list).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"List not found [id=3]"}]}}}},"422":{"description":"Nothing was saved. Either a field failed validation (`SyncApiErrorResponse`, one error per field: a blank `name`, `host`, `database` or `username`, a `listId` or `destination` that is not positive, no `fields`, a missing `password`, a `type` other than `mysql`, a `query` without SELECT when `table` is empty, or a value of the wrong JSON type, whose `detail` is `Unexpected type`), or the sync is incomplete once its blanks and `DNI` mappings are dropped (`SyncHttpErrorResponse`, with a translated \"information is missing\" message).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SyncApiErrorResponse"},{"$ref":"#/components/schemas/SyncHttpErrorResponse"}]},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"name can not be blank","source":{"pointer":"/data/attributes/name"}}]}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete several database syncs","description":"Deletes every sync named in `ids`, with the records of their runs, or none of them: each is looked up first, and one that cannot be found fails the call before anything is deleted. Contacts the syncs imported stay. Internal: backs the bulk delete of the Database Sync page in the app.","operationId":"bulk-delete-database-syncs","parameters":[{"name":"ids","in":"query","description":"Comma-separated IDs of the syncs to delete. Spaces around an ID are ignored and a repeated ID counts once.","required":true,"schema":{"type":"string"},"example":"7,8"}],"responses":{"204":{"description":"Deleted. There is no body."},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"One of the IDs names no sync, or a sync that writes to a list the user cannot access. Nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=8]"}]}}}},"422":{"description":"`ids` is missing or blank (`No sync job was named`), or one of its entries is not a positive integer (`Not a sync job id [id=<entry>]`). Nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"422","detail":"Not a sync job id [id=abc]"}]}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/syncs/connection":{"post":{"summary":"Test a database sync connection","description":"Connects to the source database with the credentials sent and lists its tables. Nothing is saved. To test the connection of a saved sync without sending its password, send its `syncId` and leave `password` out. Internal: backs the Database Sync wizard in the app.","operationId":"test-a-database-sync-connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceConnectionRequest"},"example":{"host":"db.example.com","database":"crm","username":"reader","password":"s3cr3t"}}}},"responses":{"200":{"description":"Connected. `tables` lists the tables of the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncConnectionTestResult"},"example":{"connected":true,"message":"Connection successful","tables":["customers","orders"]}}}},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"`password` was left out and `syncId` names no sync, or a sync that writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}},"422":{"description":"Either the connection failed (a `SyncConnectionTestResult` with `connected` false and the reason in `message`), or a field failed validation (`SyncApiErrorResponse`: a blank `host`, `database` or `username`, a negative `syncId`, or a `type` other than `mysql`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SyncConnectionTestResult"},{"$ref":"#/components/schemas/SyncApiErrorResponse"}]},"example":{"connected":false,"message":"Error: Could not connect to host db.example.com as user reader","tables":[]}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/syncs/contact-fields":{"get":{"summary":"List the contact fields a database sync can map","description":"The standard contact fields a source column can be mapped to, in the order the wizard offers them, with labels in the user's language. Custom fields are listed by GET /syncs/custom-fields. Internal: backs the Database Sync wizard in the app.","operationId":"list-database-sync-contact-fields","responses":{"200":{"description":"The fields","content":{"application/json":{"schema":{"properties":{"fields":{"type":"array","items":{"$ref":"#/components/schemas/SyncContactField"}}},"type":"object"},"example":{"fields":[{"id":"email","name":"Email Address","required":true},{"id":"first_name","name":"First Name","required":false}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}}},"x-canonical-resource":"import","x-internal":true}},"/syncs/custom-fields":{"get":{"summary":"List the custom fields a database sync can map","description":"The contact custom fields a sync writing to the given list can map a source column to: the fields of that list and the fields shared by every list, in their list order. Internal: backs the Database Sync wizard in the app.","operationId":"list-database-sync-custom-fields","parameters":[{"name":"listId","in":"query","description":"ID of the list the sync writes to. `0`, the default, lists only the fields shared by every list.","required":false,"schema":{"type":"integer","default":0,"minimum":0},"example":3}],"responses":{"200":{"description":"The fields","content":{"application/json":{"schema":{"properties":{"fields":{"type":"array","items":{"$ref":"#/components/schemas/SyncCustomField"}}},"type":"object"},"example":{"fields":[{"id":"12","title":"Company"}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, the account's plan does not include Database Sync, or the user cannot access the list. For the list, `detail` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"List not found [id=3]"}]}}}}},"x-canonical-resource":"import","x-internal":true}},"/syncs/fields":{"post":{"summary":"List the source columns a database sync can map","description":"Connects to the source database and lists the columns of `table`, or of the rows `query` returns, which the sync `fields` can then map. Nothing is saved. For a custom query only its first row is read. Internal: backs the Database Sync wizard in the app.","operationId":"discover-database-sync-source-fields","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverFieldsRequest"},"example":{"host":"db.example.com","database":"crm","username":"reader","password":"s3cr3t","table":"customers"}}}},"responses":{"200":{"description":"The columns","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncFieldDiscoveryResult"},"example":{"succeeded":true,"message":"Found 3 columns","isCustomQuery":false,"rules":[],"fields":[{"name":"email_address","type":"varchar(255)"},{"name":"fname","type":"varchar(64)"},{"name":"status","type":"tinyint(1)"}]}}}},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"`syncId` names no sync, or a sync that writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}},"422":{"description":"Either the columns could not be read (a `SyncFieldDiscoveryResult` with `succeeded` false and the reason in `message`), or a field failed validation (`SyncApiErrorResponse`: neither `table` nor `query` given, a blank `host`, `database` or `username`, a negative `syncId`, or a `type` other than `mysql`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SyncFieldDiscoveryResult"},{"$ref":"#/components/schemas/SyncApiErrorResponse"}]},"example":{"succeeded":false,"message":"Table orders_old not found in database","isCustomQuery":false,"rules":[],"fields":[]}}}}},"x-canonical-resource":"import","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/syncs/options":{"get":{"summary":"List the options a database sync can be saved with","description":"The sync options the Database Sync wizard offers, whether each starts out set, and whether this account can be offered it. Internal: backs the Database Sync wizard in the app.","operationId":"list-database-sync-options","responses":{"200":{"description":"The options","content":{"application/json":{"schema":{"properties":{"options":{"type":"array","items":{"$ref":"#/components/schemas/SyncOption"}}},"type":"object"},"example":{"options":[{"id":"updateExisting","checked":true,"available":true},{"id":"sendLastMessage","checked":false,"available":true}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}}},"x-canonical-resource":"import","x-internal":true}},"/syncs/processes/{processId}":{"get":{"summary":"Retrieve the progress of a database sync run","description":"How many rows a run started with POST /syncs/{id}/run has processed. Poll it until `finished`. Internal: backs the Database Sync page in the app.","operationId":"retrieve-a-database-sync-run-progress","parameters":[{"name":"processId","in":"path","description":"ID of the run, the `processId` POST /syncs/{id}/run returned.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncRunProgress"},"example":{"processId":812,"total":1500,"completed":600,"percentage":40,"finished":false}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No run of a sync with this ID, or its sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync process not found [id=812]"}]}}}}},"x-canonical-resource":"import","x-internal":true}},"/syncs/processes/{processId}/report":{"get":{"summary":"Retrieve the report of a database sync run","description":"The rows a run could not import, grouped by why, with the message logged for each. Rows imported successfully are not listed. Internal: backs the Database Sync page in the app.","operationId":"retrieve-a-database-sync-run-report","parameters":[{"name":"processId","in":"path","description":"ID of the run, the `processId` POST /syncs/{id}/run returned.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncRunReport"},"example":{"processId":812,"total":1,"counts":{"bounced":1},"rows":{"bounced":[{"email":"jane@example.com","code":4,"message":"This contact has been removed in the past due to numerous bounces.","tstamp":"2026-10-01 04:00:12"}]}}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No run of a sync with this ID, or its sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync process not found [id=812]"}]}}}}},"x-canonical-resource":"import","x-internal":true}},"/syncs/{id}":{"get":{"summary":"Retrieve a database sync","description":"One database sync, as the wizard loads it for an edit. The source password is never returned; `hasPassword` says whether one is stored. Internal: backs the Database Sync page in the app.","operationId":"retrieve-a-database-sync","parameters":[{"name":"id","in":"path","description":"ID of the sync.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"200":{"description":"The sync","content":{"application/json":{"schema":{"properties":{"sync":{"$ref":"#/components/schemas/SyncJob"}},"type":"object"},"example":{"sync":{"id":"7","name":"Nightly CRM import","listId":"3","destination":"1","host":"db.example.com","database":"crm","username":"reader","hasPassword":true,"type":"mysql","charset":"utf8","table":"customers","query":"","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"deleteAll":false,"updateExisting":true,"sendLastMessage":false,"sendResponder":false,"instantResponder":false,"optIn":false,"sentResponders":[],"lastRun":"2026-10-01 04:00:00"}}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No sync with this ID, or the sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}}},"x-canonical-resource":"import","x-internal":true},"put":{"summary":"Update a database sync","description":"Replaces a database sync with the body. Every field is overwritten, an omitted one with its default, except that an omitted `password` keeps the stored password and an omitted `sentResponders` keeps the stored list. Internal: backs the Database Sync wizard in the app.","operationId":"update-a-database-sync","parameters":[{"name":"id","in":"path","description":"ID of the sync.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveSyncJobRequest"},"example":{"name":"Nightly CRM import","listId":3,"host":"db.example.com","database":"crm","username":"reader","table":"customers","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"updateExisting":true}}}},"responses":{"200":{"description":"The saved sync","content":{"application/json":{"schema":{"properties":{"sync":{"$ref":"#/components/schemas/SyncJob"}},"type":"object"},"example":{"sync":{"id":"7","name":"Nightly CRM import","listId":"3","destination":"1","host":"db.example.com","database":"crm","username":"reader","hasPassword":true,"type":"mysql","charset":"utf8","table":"customers","query":"","rules":["status = 1"],"fields":{"email":"email_address","first_name":"fname"},"deleteAll":false,"updateExisting":true,"sendLastMessage":false,"sendResponder":false,"instantResponder":false,"optIn":false,"sentResponders":[],"lastRun":"2026-10-01 04:00:00"}}}}},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, the account's plan does not include Database Sync, or the user cannot access `listId` (`detail` names the list).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"List not found [id=3]"}]}}}},"404":{"description":"No sync with this ID, or the sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}},"422":{"description":"Nothing was saved. Either a field failed validation (`SyncApiErrorResponse`, one error per field: a blank `name`, `host`, `database` or `username`, a `listId` or `destination` that is not positive, no `fields`, a `type` other than `mysql`, a `query` without SELECT when `table` is empty, or a value of the wrong JSON type, whose `detail` is `Unexpected type`), or the sync is incomplete once its blanks and `DNI` mappings are dropped (`SyncHttpErrorResponse`, with a translated \"information is missing\" message).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SyncApiErrorResponse"},{"$ref":"#/components/schemas/SyncHttpErrorResponse"}]},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"At least one field mapping is required","source":{"pointer":"/data/attributes/fields"}}]}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":false,"x-internal":true},"delete":{"summary":"Delete a database sync","description":"Deletes a database sync and the records of its runs, whose progress and reports can then no longer be read. Contacts it imported stay. Internal: backs the Database Sync page in the app.","operationId":"delete-a-database-sync","parameters":[{"name":"id","in":"path","description":"ID of the sync.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"responses":{"204":{"description":"Deleted. There is no body."},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No sync with this ID, or the sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/syncs/{id}/run":{"post":{"summary":"Run a database sync","description":"Starts a run of a saved sync. The source rows are counted and the run is handed to a background process, which imports each row as a contact of the list with the sync's options; follow it with GET /syncs/processes/{processId} and read what failed with GET /syncs/processes/{processId}/report. If a run of the sync is already going, that run is returned instead (`alreadyRunning`). A source with no rows answers 202 with `processId` 0. A run that gets as far as counting the rows, a test run included, sets the sync's `lastRun` to now. Internal: backs the Database Sync page in the app.","operationId":"run-a-database-sync","parameters":[{"name":"id","in":"path","description":"ID of the sync.","required":true,"schema":{"type":"integer","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunSyncJobRequest"},"example":{"test":false}}}},"responses":{"202":{"description":"Started, already running, or nothing to sync. `started` is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncRunResult"},"example":{"started":true,"message":"Synchronization process initiated","processId":812,"total":1500,"alreadyRunning":false}}}},"400":{"description":"The body is empty or not a JSON object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"403":{"description":"The user's group lacks the permission to sync contacts, or the account's plan does not include Database Sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncApiErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden"}]}}}},"404":{"description":"No sync with this ID, or the sync writes to a list the user cannot access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHttpErrorResponse"},"example":{"errors":[{"status":"404","detail":"Sync job not found [id=7]"}]}}}},"422":{"description":"Nothing was started. Either the run could not start (a `SyncRunResult` with `started` false and the reason in `message`: the connection failed, a test run found the table gone, or the rows could not be counted), or `test` is not a boolean (`SyncApiErrorResponse`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SyncRunResult"},{"$ref":"#/components/schemas/SyncApiErrorResponse"}]},"example":{"started":false,"message":"Error: Could not connect to host db.example.com as user reader","processId":0,"total":0,"alreadyRunning":false}}}}},"x-canonical-resource":"import","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/tags":{"post":{"summary":"Create a tag","description":"Creates a tag definition. This does not apply the tag to any contact; to do that, pass the new tag id to POST /contactTags, or use POST /contacts/{id}/tags to create and apply by name in one call. Always send tagType (contact or template): a tag created without it does not appear in GET /tags listings. If a non-deleted tag with the same name and type already exists, the request returns 200 with the existing tag instead of creating a duplicate. If the name is held by a deleted tag that has not been purged, the request fails with 422 and a {message, error} body rather than an errors array. Tag names must be 1 to 250 characters and cannot contain commas, line breaks, or HTML markup; such requests fail with 422 (see the 422 response for the two body shapes). Emoji and other 4-byte characters are not supported in tag names. Names are compared case-insensitively: creating a name that differs from an existing tag only in letter case returns the existing tag. Names are stored exactly as sent; leading and trailing spaces are not trimmed. Requires the tag management permission.","operationId":"create-a-new-tag","x-canonical-resource":"tags","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"description":"The tag to create.","properties":{"tag":{"type":"string","description":"The tag name: 1 to 250 characters, no commas, line breaks, or HTML markup. Emoji and other 4-byte characters are not supported. Stored exactly as sent."},"tagType":{"type":"string","description":"Type of the new tag: contact or template. Always send this; a tag created without a type does not appear in tag listings."},"description":{"type":"string","description":"Description of the new tag"}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"tag":{"tag":"My Tag","tagType":"contact","description":"Description"}}}}}}},"responses":{"200":{"description":"A non-deleted tag with the same name (compared case-insensitively) and type already exists. It is returned unchanged and nothing is created.","content":{"application/json":{"examples":{"Existing tag":{"value":"{\"tag\":{\"tagType\":\"contact\",\"tag\":\"newsletter\",\"description\":\"\",\"subscriber_count\":\"12\",\"cdate\":\"2026-09-01T09:15:02-05:00\",\"created_timestamp\":\"2026-09-01 09:15:02\",\"updated_timestamp\":\"2026-09-01 09:15:02\",\"created_by\":null,\"updated_by\":null,\"deleted\":\"0\",\"links\":{\"contactGoalTags\":\"https://:account.api-us1.com/api/3/tags/12/contactGoalTags\",\"templateTags\":\"https://:account.api-us1.com/api/3/tags/12/templateTags\"},\"id\":\"12\"}}"}},"schema":{"type":"object","properties":{"tag":{"description":"The existing tag, with the same fields as GET /tags/{id}.","type":"object"}}}}}},"201":{"description":"The tag was created.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tag\": {\n        \"tag\": \"My Tag\",\n        \"description\": \"Description\",\n        \"tagType\": \"contact\",\n        \"cdate\": \"2018-09-29T19:21:25-05:00\",\n        \"links\": {\n            \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/16/contactGoalTags\"\n        },\n        \"id\": \"16\"\n    }\n}"}},"schema":{"type":"object","properties":{"tag":{"description":"The new tag. Only the fields sent, cdate, links and id are returned; read the tag with GET /tags/{id} for subscriber_count and the audit fields.","type":"object","properties":{"tag":{"description":"The tag name.","type":"string","example":"My Tag"},"description":{"description":"Free-text description of the tag. Absent when none was sent.","type":"string","example":"Description"},"tagType":{"description":"The tag type: contact (applied to contacts) or template (applied to email templates).","type":"string","example":"contact"},"cdate":{"description":"When the tag was created, in ISO 8601.","type":"string","example":"2018-09-29T19:21:25-05:00"},"links":{"description":"URLs of the tag's related reads.","type":"object","properties":{"contactGoalTags":{"description":"URL of the goal tags that reference this tag.","type":"string","example":"https://:account.api-us1.com/api/:version/tags/16/contactGoalTags"}}},"id":{"description":"The tag id. Pass it as tag to POST /contactTags to apply the tag to a contact.","type":"string","example":"16"}}}}}}}},"403":{"description":"The API user does not have the tag management permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry, describing the refusal.","type":"array","items":{"type":"object","properties":{"status":{"description":"HTTP status code, always 403.","type":"integer","example":403},"title":{"description":"\"Forbidden\" in English; the title follows the API user's language.","type":"string"},"detail":{"description":"Says why: \"You do not have permission to create new tags.\"","type":"string"}}}}}}}}},"422":{"description":"The name breaks a rule, or is held by a deleted tag. Three body shapes. For a comma, a line break, or HTML markup: errors[0].detail is \"Invalid input\", errors[0].error names the rule, and source.pointer is /data/attributes/tag. For an empty name or one longer than 250 characters: the message is in errors[0].title, error is empty, and source.pointer is /data/attributes/[tag]; a name made only of spaces is accepted. For a name still held by a deleted tag that has not been purged: no errors array, but {\"message\":\"Could not process request\",\"error\":\"Duplicate entry ... for key 'typetag'\"}.","content":{"application/json":{"examples":{"Comma":{"value":"{\"errors\":[{\"title\":\"\",\"detail\":\"Invalid input\",\"code\":\"field_invalid\",\"error\":\"Tag cannot include ','\",\"source\":{\"pointer\":\"/data/attributes/tag\"}}]}"},"Line break":{"value":"{\"errors\":[{\"title\":\"\",\"detail\":\"Invalid input\",\"code\":\"field_invalid\",\"error\":\"Tag cannot include line breaks\",\"source\":{\"pointer\":\"/data/attributes/tag\"}}]}"},"Too long":{"value":"{\"errors\":[{\"title\":\"This value is too long. It should have 250 characters or less.\",\"detail\":\"\",\"code\":\"field_invalid\",\"error\":\"\",\"source\":{\"pointer\":\"/data/attributes/[tag]\"}}]}"},"Held by a deleted tag":{"value":"{\"message\":\"Could not process request\",\"error\":\"Duplicate entry 'contact-newsletter' for key 'em_tag.typetag'\"}"}},"schema":{"type":"object","properties":{"errors":{"description":"One entry per broken rule. Absent for a name held by a deleted tag.","type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Empty for the comma, line-break and markup rules; the message for an empty or over-long name."},"detail":{"type":"string","description":"\"Invalid input\" for the comma, line-break and markup rules; empty otherwise."},"code":{"description":"Always field_invalid.","type":"string","example":"field_invalid"},"error":{"type":"string","description":"Names the rule for a comma, a line break, or HTML markup; empty for an empty or over-long name."},"source":{"description":"Which field broke the rule.","type":"object","properties":{"pointer":{"type":"string","description":"/data/attributes/tag for the comma, line-break and markup rules; /data/attributes/[tag] for an empty or over-long name."}}}}}},"message":{"type":"string","description":"Only for the deleted-tag case: \"Could not process request\"."},"error":{"type":"string","description":"Only for the deleted-tag case: the database duplicate-entry message."}}}}}}},"deprecated":false},"get":{"summary":"List all tags","description":"Returns tag definitions, each with subscriber_count, the number of contacts the tag is applied to. Contact tags are returned by default; pass type=template for template tags. To find a tag by exact name, use filters[tag] or filters[search][eq]; both match the whole name, ignoring case. For a partial-name search, use search: it is a case-insensitive substring match, so it returns every similarly named tag alongside the one asked for. Identify the tag you want by comparing the tag field of each result, never by its position in the list. To apply a tag to a contact, pass the returned id to POST /contactTags. Unrecognized filter and order parameters are silently ignored. When that happens the response contains the unfiltered set with the unfiltered total, so a request with a misspelled filter looks successful while returning every tag. Soft-deleted tags are never listed. Results are sorted by id ascending unless order, selected_tag_id or orders[search]=weight applies; orders[tag], orders[type] and orders[id] have no effect. meta.total is the number of tags that matched, returned as a string; when counting is slow it can come from a cache of up to five minutes. The list is read from a replica, so a tag created a moment ago can be missing briefly.","operationId":"retrieve-all-tags","x-canonical-resource":"tags","parameters":[{"name":"search","in":"query","description":"Filters tags by name. Partial matches are included (a contains match), within the selected type only. If both search and filters[search] are sent, search wins and filters[search] is ignored. The characters % and _ in the value act as SQL wildcards, and a value of 0 is ignored.","schema":{"type":"string"}},{"name":"filters[tag]","in":"query","description":"Filters by exact tag name. The simplest way to look up one tag by name. Names are unique within a type, so at most one tag matches.","schema":{"type":"string"}},{"name":"exact_tag","in":"query","description":"Exact tag name; the same as filters[tag].","schema":{"type":"string"}},{"name":"tags[]","in":"query","description":"Array form, tags[]=a&tags[]=b: returns the tags whose name is exactly one of the values, within the selected type. A single tags=value without brackets is ignored.","schema":{"type":"array","items":{"type":"string"}}},{"name":"type","in":"query","description":"Selects which tag type the response contains: contact (the default) or template. Any other value is treated as contact. Every response contains only one type of tag. Sending filters[type] instead of this parameter does not work and can return an empty result.","schema":{"type":"string","enum":["contact","template"]}},{"name":"filters[search][<operator>]","in":"query","description":"Filters tags by name using the operator. Supported operators: eq (exact name match), neq, lt, lte, gt, gte, contains, starts_with. Send only one operator per request: when several are sent, the last value is applied to every operator. in is not supported here and returns an empty list, as does any other operator value.","schema":{"type":"string"}},{"name":"filters[id][<operator>]","in":"query","description":"Filters by tag id. Supported operators: eq, neq, lt, lte, gt, gte, and in with a comma-separated list of ids (for example filters[id][in]=1,2,3). Always send an operator: filters[id]=1 without one is a contains match on the digits, so it also returns ids such as 10 and 21.","schema":{"type":"string"}},{"name":"ids","in":"query","description":"Comma-separated list of tag ids to return, or the array form ids[]=1&ids[]=2. Overrides limit. Only tags of the selected type are returned, so ids of template tags need type=template.","schema":{"type":"string"}},{"name":"orders[search]","in":"query","description":"Sorts search results by relevance: exact matches first, then tags starting with the searched text, then the rest. weight is the only supported value, and it only applies when filters[search] is also sent and the legacy order parameter is absent. Ordering by other fields is not supported; any other orders parameter is silently ignored and the default sort by id applies.","schema":{"type":"string","enum":["weight"]}},{"name":"order","in":"query","description":"Legacy sort. popular orders by subscriber_count, highest first, and adds a count field to each tag (for type=template, count is the number of templates using the tag, reported as 1 for a tag no template uses); alpha orders by name, A to Z. Overrides the default id order and orders[search]=weight. Any other value leaves the list in no particular order.","schema":{"type":"string","enum":["popular","alpha"]}},{"name":"direction","in":"query","description":"Sort direction for order. Defaults to desc for popular and asc for alpha; ignored without order.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"selected_tag_id","in":"query","description":"Tag id, or array of ids, to place at the top of the list ahead of the normal ordering. Tags the filters exclude are not added.","schema":{"type":"string"}},{"name":"template_in_use","in":"query","description":"When present with any value, returns only tags applied to at least one template. Meant for type=template.","schema":{"type":"string"}},{"name":"include_automation_status","in":"query","description":"1 adds has_automation to every tag in the response: true when a visible automation has a tag added or tag removed trigger for the tag, an add or remove tag action naming it, or a segment condition on the tag in its start or actions. It runs several extra queries per tag, so use a small limit.","schema":{"type":"integer"}},{"name":"include","in":"query","description":"Comma-separated related collections to add to the response: contactGoalTags, templateTags. Unknown names are ignored. GET /tags/{id} ignores this parameter.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return. Default 20. Values above 100 are capped to 100; the literal value null raises the cap to 1000 for that request.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of results to skip. Use with limit to page through results.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The tags that matched, one type per response.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tags\": [\n        {\n            \"tagType\": \"contact\",\n            \"tag\": \"one\",\n            \"description\": \"\",\n            \"cdate\": \"2018-08-17T09:43:15-05:00\",\n            \"subscriber_count\": \"0\",\n            \"links\": {\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/1/contactGoalTags\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"tagType\": \"contact\",\n            \"tag\": \"two\",\n            \"description\": \"\",\n            \"cdate\": \"2018-08-17T13:41:16-05:00\",\n            \"subscriber_count\": \"0\",\n            \"links\": {\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/2/contactGoalTags\"\n            },\n            \"id\": \"2\"\n        },\n        {\n            \"tagType\": \"contact\",\n            \"tag\": \"three\",\n            \"description\": \"\",\n            \"cdate\": \"2018-08-17T13:41:18-05:00\",\n            \"subscriber_count\": \"0\",\n            \"links\": {\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/3/contactGoalTags\"\n            },\n            \"id\": \"3\"\n        },\n        {\n            \"tagType\": \"template\",\n            \"tag\": \"test1\",\n            \"description\": \"\",\n            \"cdate\": \"2018-08-28T11:54:36-05:00\",\n            \"subscriber_count\": \"0\",\n            \"links\": {\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/4/contactGoalTags\"\n            },\n            \"id\": \"4\"\n        },\n        {\n            \"tagType\": \"template\",\n            \"tag\": \"test2\",\n            \"description\": \"\",\n            \"cdate\": \"2018-08-28T11:54:38-05:00\",\n            \"subscriber_count\": \"0\",\n            \"links\": {\n                \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/5/contactGoalTags\"\n            },\n            \"id\": \"5\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"5\"\n    }\n}"}},"schema":{"type":"object","properties":{"tags":{"description":"The tags that matched, in the order described above.","type":"array","items":{"type":"object","properties":{"tagType":{"description":"The tag type: contact (applied to contacts) or template (applied to email templates).","type":"string","example":"contact"},"tag":{"description":"The tag name.","type":"string","example":"one"},"description":{"description":"Free-text description of the tag. An empty string when none was set.","type":"string","example":""},"cdate":{"type":["string","null"],"example":"2018-08-17T09:43:15-05:00","description":"When the tag was created, in ISO 8601; null when not recorded."},"subscriber_count":{"type":"string","example":"0","description":"How many contacts this tag is applied to, counting every contact status: active, unconfirmed, unsubscribed and bounced alike. It is the same number the Tags page under Contacts shows in the app, and it answers how many contacts have this tag without another call. It is not a count of active contacts: GET /contacts?tagid={id}&status=1 and its meta.total counts only the tagged contacts that are active on at least one list, so that figure is lower whenever a tagged contact is active on no list: unsubscribed, bounced or unconfirmed everywhere, or on no list at all. The value is maintained by database triggers rather than computed on read, so it can occasionally drift from the live total. Returned as a string."},"deleted":{"type":"string","example":"0","description":"0 for every listed tag: soft-deleted tags are left out of this list."},"created_timestamp":{"type":"string","example":"2018-08-17 09:43:15","description":"When the tag was created, as YYYY-MM-DD HH:MM:SS rather than the ISO 8601 form cdate uses."},"updated_timestamp":{"type":"string","example":"2018-08-17 09:43:15","description":"When the tag last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":["string","null"],"example":"1","description":"Id of the user who created the tag, or null."},"updated_by":{"type":["string","null"],"example":"1","description":"Id of the user who last changed the tag, or null."},"has_automation":{"type":"boolean","description":"Only with include_automation_status=1: true when a visible automation has a tag added or tag removed trigger for this tag, an add or remove tag action naming it, or a segment condition on it in its start or actions."},"count":{"type":"string","example":"0","description":"Only with order=popular: the value the list is sorted by, subscriber_count for contact tags and the number of templates using the tag for template tags, reported as 1 for a tag no template uses."},"links":{"description":"URLs of the tag's related reads.","type":"object","properties":{"contactGoalTags":{"description":"URL of the goal tags that reference this tag.","type":"string","example":"https://:account.api-us1.com/api/:version/tags/1/contactGoalTags"},"templateTags":{"description":"URL of the links between this tag and email templates.","type":"string","example":"https://:account.api-us1.com/api/:version/tags/1/templateTags"}}},"id":{"description":"The tag id. Pass it as tag to POST /contactTags to apply the tag to a contact.","type":"string","example":"1"}}}},"meta":{"description":"Paging information.","type":"object","properties":{"total":{"description":"Number of tags that matched, ignoring limit and offset, as a string. When counting is slow it can come from a cache of up to five minutes.","type":"string","example":"5"}}}}}}}}},"deprecated":false}},"/tags/{id}":{"get":{"summary":"Retrieve a tag","description":"Returns a single tag definition, including subscriber_count, the number of contacts the tag is applied to. Use GET /tags with filters[tag] to find a tag by name when the id is not known. Unlike GET /tags, it also returns soft-deleted tags, with deleted set to 1, and template tags. Returns 404 only when no tag with this id exists. Query parameters, including include, are ignored.","operationId":"retrieve-a-tag","x-canonical-resource":"tags","parameters":[{"name":"id","in":"path","description":"ID of the tag to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The tag.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tag\": {\n        \"tagType\": \"contact\",\n        \"tag\": \"My Tag\",\n        \"description\": \"Description\",\n        \"cdate\": \"2018-10-04T14:55:13-05:00\",\n        \"subscriber_count\": \"0\",\n        \"links\": {\n            \"contactGoalTags\": \"https://:account.api-us1.com/api/3/tags/1/contactGoalTags\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"tag":{"description":"The tag definition.","type":"object","properties":{"tagType":{"description":"The tag type: contact (applied to contacts) or template (applied to email templates).","type":"string","example":"contact"},"tag":{"description":"The tag name.","type":"string","example":"My Tag"},"description":{"description":"Free-text description of the tag. An empty string when none was set.","type":"string","example":"Description"},"cdate":{"type":["string","null"],"example":"2018-10-04T14:55:13-05:00","description":"When the tag was created, in ISO 8601; null when not recorded."},"subscriber_count":{"type":"string","example":"0","description":"How many contacts this tag is applied to, counting every contact status: active, unconfirmed, unsubscribed and bounced alike. It is the same number the Tags page under Contacts shows in the app, and it answers how many contacts have this tag without another call. It is not a count of active contacts: GET /contacts?tagid={id}&status=1 and its meta.total counts only the tagged contacts that are active on at least one list, so that figure is lower whenever a tagged contact is active on no list: unsubscribed, bounced or unconfirmed everywhere, or on no list at all. The value is maintained by database triggers rather than computed on read, so it can occasionally drift from the live total. Returned as a string."},"deleted":{"type":"string","example":"0","description":"1 when the tag was soft-deleted. Such a tag is still returned here but never by GET /tags."},"created_timestamp":{"type":"string","example":"2018-08-17 09:43:15","description":"When the tag was created, as YYYY-MM-DD HH:MM:SS rather than the ISO 8601 form cdate uses."},"updated_timestamp":{"type":"string","example":"2018-08-17 09:43:15","description":"When the tag last changed, as YYYY-MM-DD HH:MM:SS."},"created_by":{"type":["string","null"],"example":"1","description":"Id of the user who created the tag, or null."},"updated_by":{"type":["string","null"],"example":"1","description":"Id of the user who last changed the tag, or null."},"links":{"description":"URLs of the tag's related reads.","type":"object","properties":{"contactGoalTags":{"description":"URL of the goal tags that reference this tag.","type":"string","example":"https://:account.api-us1.com/api/3/tags/1/contactGoalTags"},"templateTags":{"description":"URL of the links between this tag and email templates.","type":"string","example":"https://:account.api-us1.com/api/3/tags/1/templateTags"}}},"id":{"description":"The tag id. Pass it as tag to POST /contactTags to apply the tag to a contact.","type":"string","example":"1"}}}}}}}},"404":{"description":"No tag with this id.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Tag with id 1\"\n}"}},"schema":{"type":"object","properties":{"message":{"description":"Says no tag has this id.","type":"string","example":"No Result found for Tag with id 1"}}}}}}},"deprecated":false},"put":{"summary":"Update a tag","description":"Updates a tag's name, type, or description. Renaming a tag also updates automations and segments that reference the old name. The new name follows the same rules as POST /tags: 1 to 250 characters, no commas, line breaks, or HTML markup, and emoji and other 4-byte characters are not supported; a name that breaks a rule fails with 422 (see the 422 response for the two body shapes). If another tag already uses the new name, the request fails with 422 and errors[0].detail is \"Tag already exists\". Returns 404 if the tag does not exist (unless the new name is already in use, which is checked first and returns 422). Requires the tag management permission.","operationId":"update-a-tag","x-canonical-resource":"tags","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the tag to update","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"description":"The tag fields to change.","properties":{"tag":{"type":"string","description":"The new tag name: 1 to 250 characters, no commas, line breaks, or HTML markup. Must not be in use by another tag."},"tagType":{"type":"string","description":"Tag-type of the tag being updated. Possible Values: template, contact"},"description":{"type":"string","description":"Description of the tag being updated"}},"required":[],"type":"object"}}},"examples":{"Request Example":{"value":{"tag":{"tag":"My Tag","tagType":"contact","description":"Description"}}}}}}},"responses":{"200":{"description":"The tag was updated.","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tag\": {\n        \"tagType\": \"contact\",\n        \"tag\": \"My Tag\",\n        \"description\": \"Description\",\n        \"cdate\": \"2018-08-17T13:41:16-05:00\",\n        \"links\": {\n            \"contactGoalTags\": \"https://:account.api-us1.com/api/:version/tags/2/contactGoalTags\"\n        },\n        \"id\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"tag":{"description":"The tag after the update, with the same fields as GET /tags/{id}.","type":"object","properties":{"tagType":{"description":"The tag type: contact (applied to contacts) or template (applied to email templates).","type":"string","example":"contact"},"tag":{"description":"The tag name.","type":"string","example":"My Tag"},"description":{"description":"Free-text description of the tag. An empty string when none was set.","type":"string","example":"Description"},"cdate":{"description":"When the tag was created, in ISO 8601; null when not recorded.","type":["string","null"],"example":"2018-08-17T13:41:16-05:00"},"links":{"description":"URLs of the tag's related reads.","type":"object","properties":{"contactGoalTags":{"description":"URL of the goal tags that reference this tag.","type":"string","example":"https://:account.api-us1.com/api/:version/tags/2/contactGoalTags"}}},"id":{"description":"The tag id. Pass it as tag to POST /contactTags to apply the tag to a contact.","type":"string","example":"2"}}}}}}}},"403":{"description":"The API user does not have the tag management permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry, describing the refusal.","type":"array","items":{"type":"object","properties":{"status":{"description":"HTTP status code, always 403.","type":"integer","example":403},"title":{"description":"\"Forbidden\" in English; the title follows the API user's language.","type":"string"},"detail":{"description":"Says why: \"You do not have permission to edit tags.\"","type":"string"}}}}}}}}},"404":{"description":"No tag with that id.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Tag with id 999999\"}"}},"schema":{"type":"object","properties":{"message":{"description":"Says no tag has this id.","type":"string"}}}}}},"422":{"description":"Either the new name breaks a rule, or another tag already uses it. A rule violation has two body shapes: for a comma, a line break, or HTML markup, errors[0].detail is \"Invalid input\", errors[0].error names the rule, and source.pointer is /data/attributes/tag; for an empty name or one longer than 250 characters, the message is in errors[0].title, error is empty, and source.pointer is /data/attributes/[tag]. A name already in use returns errors[0].detail \"Tag already exists\" with errors[0].title \"Invalid Input Parameter\"; that check runs before the id lookup, so it applies even when the id does not exist.","content":{"application/json":{"examples":{"Line break":{"value":"{\"errors\":[{\"title\":\"\",\"detail\":\"Invalid input\",\"code\":\"field_invalid\",\"error\":\"Tag cannot include line breaks\",\"source\":{\"pointer\":\"/data/attributes/tag\"}}]}"},"Name already used":{"value":"{\"errors\":[{\"status\":422,\"title\":\"Invalid Input Parameter\",\"detail\":\"Tag already exists\"}]}"},"Too long":{"value":"{\"errors\":[{\"title\":\"This value is too long. It should have 250 characters or less.\",\"detail\":\"\",\"code\":\"field_invalid\",\"error\":\"\",\"source\":{\"pointer\":\"/data/attributes/[tag]\"}}]}"}},"schema":{"type":"object","properties":{"errors":{"description":"One entry describing the problem.","type":"array","items":{"type":"object","properties":{"status":{"description":"422 for a name already in use; absent for a broken name rule.","type":"integer","example":422},"title":{"description":"\"Invalid Input Parameter\" for a name already in use; the message for an empty or over-long name; empty otherwise.","type":"string"},"detail":{"description":"\"Tag already exists\" for a name already in use; \"Invalid input\" for the comma, line-break and markup rules; empty otherwise.","type":"string"},"code":{"description":"field_invalid for a broken name rule; absent for a name already in use.","type":"string"},"error":{"description":"Names the rule for a comma, a line break, or HTML markup.","type":"string"},"source":{"description":"Which field broke the rule; absent for a name already in use.","type":"object","properties":{"pointer":{"type":"string","description":"/data/attributes/tag for the comma, line-break and markup rules; /data/attributes/[tag] for an empty or over-long name."}}}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a tag","description":"Deletes a tag definition. The delete is permanent: the tag no longer appears in GET /tags and GET /tags/{id} returns 404. The tag's associations to contacts are not deleted with it: they no longer appear under GET /contacts/{id}/contactTags, but GET /contactTags still lists them (for example with filters[tagid]) and counts them in meta.total, and each one can still be fetched with GET /contactTags/{id} and removed with DELETE /contactTags/{id}. Links from templates to the tag are removed. Automations and segments that reference the tag are not changed. To take a tag off a single contact without deleting the tag, use DELETE /contacts/{id}/tags/{tagId} instead. Returns 200 with an empty object. Requires the tag management permission.","operationId":"delete-a-tag","x-canonical-resource":"tags","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the tag to remove","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"The tag was deleted.","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object"}}}},"403":{"description":"The API user does not have the tag management permission.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"description":"One entry, describing the refusal.","type":"array","items":{"type":"object","properties":{"status":{"description":"HTTP status code, always 403.","type":"integer","example":403},"title":{"description":"\"Forbidden\" in English; the title follows the API user's language.","type":"string"},"detail":{"description":"Says why: \"You do not have permission to delete tags.\"","type":"string"}}}}}}}}},"404":{"description":"No tag with that id, or it was already deleted.","content":{"application/json":{"examples":{"Result":{"value":"{\"message\":\"No Result found for Tag with id 999999\"}"}},"schema":{"type":"object","properties":{"message":{"description":"Says no tag has this id.","type":"string"}}}}}}},"deprecated":false}},"/taskNotifications":{"post":{"summary":"Create a task reminder","description":"Create a reminder for a deal task, sent to the task's assignee ahead of its due date. The request body must be wrapped in a `taskNotification` object; both `dealTask` and `interval` are required.","operationId":"create-a-task-reminder","x-canonical-resource":"taskNotifications","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["taskNotification"],"properties":{"taskNotification":{"type":"object","required":["dealTask","interval"],"properties":{"dealTask":{"type":"string","description":"ID of task"},"interval":{"type":"integer","format":"int32","description":"Amount of time in minutes that a reminder will be sent to a task assignee ahead of task's due date."}},"additionalProperties":false}}},"examples":{"Request Example":{"value":{"taskNotification":{"dealTask":"1","interval":"123"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":""}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":""}}}}}},"deprecated":false}},"/taskOutcomes":{"post":{"summary":"Create a task outcome","description":"Create a new task outcome","operationId":"create-a-task-outcome","x-canonical-resource":"taskOutcomes","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["taskOutcome"],"properties":{"taskOutcome":{"type":"object","required":["title","sentiment"],"properties":{"title":{"type":"string","description":"Title of the outcome. Must be unique among task outcomes and at most 250 characters."},"sentiment":{"type":"string","description":"Positive, Neutral or Negative, in any letter case.","enum":["Positive","Neutral","Negative"]},"disabled":{"type":"integer","description":"1 to disable the outcome, 0 to enable it.","enum":[0,1]}}}}},"examples":{"Request Example":{"value":{"taskOutcome":{"title":"Interested","sentiment":"Positive"}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"taskOutcome\": {\n    \"title\": \"Interested\",\n    \"sentiment\": \"POSITIVE\",\n    \"created_by\": \"1\",\n    \"disabled\": \"\",\n    \"links\": {\n      \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels\",\n      \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"taskOutcome":{"type":"object","properties":{"title":{"type":"string","example":"Interested"},"sentiment":{"type":"string","example":"POSITIVE"},"created_by":{"type":"string","example":"1"},"disabled":{"type":"string","example":""},"links":{"type":"object","properties":{"tasktypeOutcomeRels":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels"},"dealTasks":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks"}}},"id":{"type":"string","example":"1"}}}}}}}},"422":{"description":"422","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"The taskOutcome title was not provided.\",\n            \"detail\": \"\",\n            \"code\": \"field_missing\",\n            \"error\": \"taskOutcome_title_was_not_provided\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Sentiment value must be one of Positive, Neutral, or Negative.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sentiment\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The taskOutcome title was not provided."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"},"error":{"type":"string","example":"taskOutcome_title_was_not_provided"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}},"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"A task outcome with the same title already exists.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Sentiment value must be one of Positive, Neutral, or Negative.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sentiment\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"A task outcome with the same title already exists."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_invalid"},"error":{"type":"string","example":""},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}}}}},"deprecated":false},"get":{"summary":"List all task outcomes","description":"Retrieve all existing task outcomes","operationId":"list-all-task-outcomes","x-canonical-resource":"taskOutcomes","parameters":[{"name":"filters[sentiment]","in":"query","description":"1 is for Negative, 2 is for Neutral and 3 is for Positive","schema":{"type":"string","enum":["1","2 or 3"]}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"taskOutcomes\": [\n        {\n            \"title\": \"Interested\",\n            \"sentiment\": \"POSITIVE\",\n            \"disabled\": \"0\",\n            \"created_by\": \"1\",\n            \"updated_by\": \"1\",\n            \"created_utc_timestamp\": \"2021-02-16T12:26:15-06:00\",\n            \"updated_utc_timestamp\": \"2021-02-16T12:27:56-06:00\",\n            \"dealTasktype_ids\": [],\n            \"links\": {\n                \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels\",\n                \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks\"\n            },\n            \"id\": \"1\"\n        },\n        {\n            \"title\": \"Not Interested\",\n            \"sentiment\": \"NEGATIVE\",\n            \"disabled\": \"0\",\n            \"created_by\": \"1\",\n            \"updated_by\": \"1\",\n            \"created_utc_timestamp\": \"2021-02-16T12:27:01-06:00\",\n            \"updated_utc_timestamp\": \"2021-02-16T12:27:01-06:00\",\n            \"dealTasktype_ids\": [],\n            \"links\": {\n                \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/2/tasktypeOutcomeRels\",\n                \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/2/dealTasks\"\n            },\n            \"id\": \"2\"\n        },\n        {\n            \"title\": \"Left a voicemail\",\n            \"sentiment\": \"NEUTRAL\",\n            \"disabled\": \"0\",\n            \"created_by\": \"1\",\n            \"updated_by\": \"1\",\n            \"created_utc_timestamp\": \"2021-02-16T12:27:13-06:00\",\n            \"updated_utc_timestamp\": \"2021-02-16T12:27:13-06:00\",\n            \"dealTasktype_ids\": [],\n            \"links\": {\n                \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/3/tasktypeOutcomeRels\",\n                \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/3/dealTasks\"\n            },\n            \"id\": \"3\"\n        },\n        {\n            \"title\": \"Disabled outcome\",\n            \"sentiment\": \"NEUTRAL\",\n            \"disabled\": \"1\",\n            \"created_by\": \"1\",\n            \"updated_by\": \"1\",\n            \"created_utc_timestamp\": \"2021-02-16T12:28:27-06:00\",\n            \"updated_utc_timestamp\": \"2021-02-16T12:28:27-06:00\",\n            \"dealTasktype_ids\": [],\n            \"links\": {\n                \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/4/tasktypeOutcomeRels\",\n                \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/4/dealTasks\"\n            },\n            \"id\": \"4\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"4\"\n    }\n}"}},"schema":{"type":"object","properties":{"taskOutcomes":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","examples":["Interested"]},"sentiment":{"type":"string","examples":["POSITIVE"]},"disabled":{"type":"string","examples":["0"]},"created_by":{"type":"string","examples":["1"]},"updated_by":{"type":"string","examples":["1"]},"created_utc_timestamp":{"type":"string","examples":["2021-02-16T12:26:15-06:00"]},"updated_utc_timestamp":{"type":"string","examples":["2021-02-16T12:27:56-06:00"]},"dealTasktype_ids":{"type":"array"},"links":{"type":"object","properties":{"tasktypeOutcomeRels":{"type":"string","examples":["https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels"]},"dealTasks":{"type":"string","examples":["https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks"]}}},"id":{"type":"string","examples":["1"]}}}},"meta":{"type":"object","properties":{"total":{"type":"string","examples":["4"]}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false,"x-mcp-tool":{"name":"list_task_outcomes","title":"List Task Outcomes","description":"List the task outcomes a completed task can record (for example Meeting Scheduled), with their sentiment (Positive, Negative or Neutral) and the task types they are assigned to.","annotations":{"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}}}},"/taskOutcomes/bulkUpsert":{"patch":{"summary":"Replace the account's task outcomes","description":"Internal: backs saving the task outcome list in Settings. The list in the body becomes the account's full set of task outcomes. First every existing outcome whose id is not in the list is deleted; an item without an id counts as id 0, so a list of only new outcomes deletes every existing one. Then each item without an id is created, and each item with an id is updated: its title when one is given and different, its sentiment always, and disabled when given. Disabled outcomes lose their links to task types. The deletes are plain row deletes, so task types' links to a deleted outcome and tasks completed with it are left as they are. Nothing runs in a transaction: a failure part-way leaves the deletes and earlier saves in place. The body is checked first and only the first problem is reported. Only PATCH is accepted; other methods get 405.","operationId":"bulk-upsert-task-outcomes","x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["taskOutcomes"],"properties":{"taskOutcomes":{"type":"array","minItems":1,"description":"Every task outcome the account should have afterwards. At least one.","items":{"type":"object","required":["sentiment"],"properties":{"id":{"type":"integer","description":"ID of an existing outcome to keep and update. Leave out for a new outcome. An id that does not exist is a 422."},"title":{"type":"string","description":"Title. Required for a new outcome. Titles must be unique within the list, ignoring letter case; two items that both leave title out count as duplicates."},"sentiment":{"type":"string","description":"Positive, Neutral or Negative, in any letter case. Required on every item.","enum":["Positive","Neutral","Negative"]},"disabled":{"type":"integer","description":"1 to disable the outcome, 0 to enable it.","enum":[0,1]}}}}}},"example":{"taskOutcomes":[{"id":1,"title":"Interested","sentiment":"positive"},{"title":"Left a voicemail","sentiment":"neutral"}]}}}},"responses":{"200":{"description":"The account's task outcomes after the change, at most 20 and in no particular order, with the total count.","content":{"application/json":{"schema":{"type":"object","properties":{"taskOutcomes":{"type":"array","description":"The task outcomes.","items":{"type":"object","properties":{"title":{"type":"string","description":"Title of the outcome."},"sentiment":{"type":"string","description":"Sentiment of the outcome: POSITIVE, NEUTRAL or NEGATIVE.","enum":["POSITIVE","NEUTRAL","NEGATIVE"]},"disabled":{"type":"string","description":"1 when the outcome is disabled, 0 when it is active."},"created_by":{"type":"string","description":"ID of the account user who created the outcome."},"updated_by":{"type":"string","description":"ID of the account user who last changed the outcome."},"created_utc_timestamp":{"type":"string","description":"When the outcome was created, as a date and time with UTC offset."},"updated_utc_timestamp":{"type":"string","description":"When the outcome was last changed, as a date and time with UTC offset."},"dealTasktype_ids":{"type":"array","description":"IDs of the task types the outcome is offered for.","items":{"type":"string"}},"links":{"type":"object","description":"URLs of the records related to the outcome.","properties":{"tasktypeOutcomeRels":{"type":"string","description":"URL of the links between this outcome and task types."},"dealTasks":{"type":"string","description":"URL of the tasks completed with this outcome."}}},"id":{"type":"string","description":"ID of the outcome."}}}},"meta":{"type":"object","description":"List metadata.","properties":{"total":{"type":"integer","description":"How many task outcomes the account has."}}}}}}}},"405":{"description":"A method other than PATCH. The Allow header says PATCH.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item.","items":{"type":"object","properties":{"status":{"type":"integer","description":"The HTTP status code."},"title":{"type":"string","description":"The error title."}}}}}},"example":{"errors":[{"status":405,"title":"Method Not Allowed"}]}}}},"422":{"description":"The body is not valid: empty, taskOutcomes missing, not a list or empty, a duplicate title in the list, an id that does not exist, an item with neither id nor title, or a sentiment that is not Positive, Neutral or Negative. Body: errors, one item carrying status and title (the message). A save that collides with the unique title index, for example two listed outcomes swapping titles, is also a 422, after the deletes have run; its body carries message and error instead.","content":{"application/json":{"schema":{"type":"object","properties":{"errors":{"type":"array","description":"One item, for a body that is not valid.","items":{"type":"object","properties":{"status":{"type":"integer","description":"Always 422."},"title":{"type":"string","description":"What was wrong."}}}},"message":{"type":"string","description":"For a save that collides with the unique title index: Could not process request."},"error":{"type":"string","description":"For a save that collides with the unique title index: the database's message."}}},"example":{"errors":[{"status":422,"title":"At least one taskOutcome is required."}]}}}}},"deprecated":false,"x-internal":true}},"/taskOutcomes/getConfig":{"get":{"summary":"Retrieve the task outcomes setting","description":"Internal: tells the app whether task outcomes are turned on for the account, an account-wide setting shared by every user. Only GET is answered; any other method does nothing and returns an empty body.","operationId":"retrieve-task-outcomes-setting","x-canonical-resource":"taskOutcomes","responses":{"200":{"description":"The setting.","content":{"application/json":{"schema":{"type":"object","properties":{"val":{"type":"string","description":"1 when task outcomes are on, 0 when they are off, and an empty string when the setting has never been saved.","enum":["1","0",""]}}},"example":{"val":"1"}}}}},"deprecated":false,"x-internal":true}},"/taskOutcomes/setConfig":{"put":{"summary":"Turn task outcomes on or off","description":"Internal: backs the task outcomes switch in Settings. Saves the account-wide setting read by GET /taskOutcomes/getConfig (retrieve-task-outcomes-setting): on when val is truthy, off otherwise, including when val is left out. Any per-user copies of the setting are deleted first, so every user sees the same value. PUT and POST behave the same; the app sends PUT with val in the query string. Any other method does nothing and returns an empty body.","operationId":"update-task-outcomes-setting-via-put","x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"val","in":"query","description":"1 turns task outcomes on; 0, empty or missing turns them off. Any other non-empty value also turns them on. A form-encoded POST may send it as a body field instead of in the query string.","required":false,"schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"The setting was saved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true."}}},"example":{"success":true}}}}},"deprecated":false,"x-internal":true},"post":{"summary":"Turn task outcomes on or off","description":"Internal: backs the task outcomes switch in Settings. Saves the account-wide setting read by GET /taskOutcomes/getConfig (retrieve-task-outcomes-setting): on when val is truthy, off otherwise, including when val is left out. Any per-user copies of the setting are deleted first, so every user sees the same value. PUT and POST behave the same; the app sends PUT with val in the query string. Any other method does nothing and returns an empty body.","operationId":"update-task-outcomes-setting-via-post","x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"val","in":"query","description":"1 turns task outcomes on; 0, empty or missing turns them off. Any other non-empty value also turns them on. A form-encoded POST may send it as a body field instead of in the query string.","required":false,"schema":{"type":"integer","enum":[0,1]}}],"responses":{"200":{"description":"The setting was saved.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Always true."}}},"example":{"success":true}}}}},"deprecated":false,"x-internal":true}},"/taskOutcomes/{id}":{"get":{"summary":"Retrieve a task outcome","description":"Retrieve an existing task outcome","operationId":"retrieve-a-task-outcome","x-canonical-resource":"taskOutcomes","parameters":[{"name":"id","in":"path","description":"Task outcome's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"taskOutcome\": {\n        \"title\": \"Interested\",\n        \"sentiment\": \"POSITIVE\",\n        \"disabled\": \"0\",\n        \"created_by\": \"1\",\n        \"updated_by\": \"1\",\n        \"created_utc_timestamp\": \"2021-02-16T12:26:15-06:00\",\n        \"updated_utc_timestamp\": \"2021-02-16T12:27:56-06:00\",\n        \"dealTasktype_ids\": [],\n        \"links\": {\n            \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels\",\n            \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"taskOutcome":{"type":"object","properties":{"title":{"type":"string","example":"Interested"},"sentiment":{"type":"string","example":"POSITIVE"},"disabled":{"type":"string","example":"0"},"created_by":{"type":"string","example":"1"},"updated_by":{"type":"string","example":"1"},"created_utc_timestamp":{"type":"string","example":"2021-02-16T12:26:15-06:00"},"updated_utc_timestamp":{"type":"string","example":"2021-02-16T12:27:56-06:00"},"dealTasktype_ids":{"type":"array"},"links":{"type":"object","properties":{"tasktypeOutcomeRels":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels"},"dealTasks":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks"}}},"id":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TaskOutcome with id 111\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TaskOutcome with id 111"}}}}}}},"deprecated":false},"put":{"summary":"Update a task outcome","description":"Update an existing task outcome","operationId":"update-a-task-outcome","x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Task outcome's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["taskOutcome"],"properties":{"taskOutcome":{"type":"object","required":["sentiment"],"properties":{"title":{"type":"string","description":"Title of the outcome. Must be unique among task outcomes and at most 250 characters."},"sentiment":{"type":"string","description":"Positive, Neutral or Negative, in any letter case.","enum":["Positive","Neutral","Negative"]},"disabled":{"type":"integer","description":"1 to disable the outcome, 0 to enable it.","enum":[0,1]}}}}},"examples":{"Request Example":{"value":{"taskOutcome":{"sentiment":"Neutral"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"taskOutcome\": {\n        \"title\": \"Interested\",\n        \"sentiment\": \"NEUTRAL\",\n        \"disabled\": \"0\",\n        \"created_by\": \"1\",\n        \"updated_by\": \"1\",\n        \"created_utc_timestamp\": \"2021-02-16T12:26:15-06:00\",\n        \"updated_utc_timestamp\": \"2021-02-16T12:27:56-06:00\",\n        \"links\": {\n            \"tasktypeOutcomeRels\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels\",\n            \"dealTasks\": \"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks\"\n        },\n        \"id\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"taskOutcome":{"type":"object","properties":{"title":{"type":"string","example":"Interested"},"sentiment":{"type":"string","example":"NEUTRAL"},"disabled":{"type":"string","example":"0"},"created_by":{"type":"string","example":"1"},"updated_by":{"type":"string","example":"1"},"created_utc_timestamp":{"type":"string","example":"2021-02-16T12:26:15-06:00"},"updated_utc_timestamp":{"type":"string","example":"2021-02-16T12:27:56-06:00"},"links":{"type":"object","properties":{"tasktypeOutcomeRels":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels"},"dealTasks":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/taskOutcomes/1/dealTasks"}}},"id":{"type":"string","example":"1"}}}}}}}},"422":{"description":"422","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"A task outcome with the same title already exists.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Sentiment value must be one of Positive, Neutral, or Negative.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sentiment\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"A task outcome with the same title already exists."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_invalid"},"error":{"type":"string","example":""},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}}}}},"deprecated":false},"delete":{"summary":"Delete a task outcome","description":"Delete an existing task outcome","operationId":"delete-a-task-outcome","x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Task outcome's id","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TaskOutcome with id 111\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TaskOutcome with id 111"}}}}}}},"deprecated":false},"patch":{"summary":"Update a task outcome (PATCH)","description":"The PATCH form of PUT /taskOutcomes/{id} (update-a-task-outcome): the same handler, body and response. Changes the title, sentiment or disabled flag of a task outcome; fields left out keep their value. sentiment must be sent on every update, even when it does not change: the stored value is a number the validator does not accept, so leaving it out fails with 422. The title must be unique among task outcomes and at most 250 characters. Disabling an outcome removes its links to task types. The response gives sentiment as text, unlike the stored number, and does not include dealTasktype_ids. Returns 404 when the outcome does not exist, 403 when the request has no authenticated account user, and 422 when the title or sentiment is invalid.","operationId":"patch-a-task-outcome","parameters":[{"name":"id","in":"path","description":"ID of the task outcome to update","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["taskOutcome"],"properties":{"taskOutcome":{"description":"The fields to change.","required":["sentiment"],"properties":{"title":{"description":"New title. Must be unique among task outcomes and at most 250 characters.","type":"string"},"sentiment":{"description":"Positive, Neutral or Negative, in any letter case. Required in practice: see the operation description.","type":"string","enum":["Positive","Neutral","Negative"]},"disabled":{"description":"1 to disable the outcome, 0 to enable it. Disabling removes its links to task types.","type":"integer","enum":[0,1]}},"type":"object"}},"type":"object"},"example":{"taskOutcome":{"title":"Interested","sentiment":"Positive"}}}}},"responses":{"200":{"description":"The outcome after the change, under taskOutcome.","content":{"application/json":{"schema":{"properties":{"taskOutcome":{"description":"The task outcome.","properties":{"title":{"description":"Title of the outcome.","type":"string","example":"Interested"},"sentiment":{"description":"Sentiment of the outcome: POSITIVE, NEUTRAL or NEGATIVE.","type":"string","example":"NEUTRAL"},"disabled":{"description":"1 when the outcome is disabled, 0 when it is active.","type":"string","example":"0"},"created_by":{"description":"ID of the account user who created the outcome.","type":"string","example":"1"},"updated_by":{"description":"ID of the account user who last changed the outcome: the API user.","type":"string","example":"1"},"created_utc_timestamp":{"description":"When the outcome was created, as a date and time with UTC offset.","type":"string","example":"2021-02-16T12:26:15-06:00"},"updated_utc_timestamp":{"description":"When the outcome was last changed, as a date and time with UTC offset.","type":"string","example":"2021-02-16T12:27:56-06:00"},"links":{"description":"URLs of the records related to the outcome.","properties":{"tasktypeOutcomeRels":{"description":"URL of the links between this outcome and task types.","type":"string","example":"https://:account.api-us1.com/api/3/taskOutcomes/1/tasktypeOutcomeRels"},"dealTasks":{"description":"URL of the tasks completed with this outcome.","type":"string","example":"https://:account.api-us1.com/api/3/taskOutcomes/1/dealTasks"}},"type":"object"},"id":{"description":"ID of the outcome.","type":"string","example":"1"}},"type":"object"}},"type":"object"}}}},"403":{"description":"No authenticated account user. Body: errors, a list with one item carrying status and detail (Forbidden)."},"404":{"description":"No task outcome with that id. Body: message, a sentence naming the id."},"422":{"description":"The title is missing, longer than 250 characters or already used by another outcome, or the sentiment is missing or not Positive, Neutral or Negative. Body: errors, a list with one item per failed field carrying title, detail, code, error and source.pointer."}},"x-canonical-resource":"taskOutcomes","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/tasktypeOutcomeRels":{"post":{"summary":"WIP Create a task type - outcome relation","description":"Link a task outcome to a deal task type","operationId":"create-a-task-outcome-1","x-canonical-resource":"tasktypeOutcomeRels","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["tasktypeOutcomeRel"],"properties":{"tasktypeOutcomeRel":{"type":"object","required":["tasktype","outcome"],"properties":{"tasktype":{"type":["integer","string"],"description":"ID of the deal task type (see /dealTasktypes)."},"outcome":{"type":["integer","string"],"description":"ID of the task outcome (see /taskOutcomes)."},"display_order":{"type":["integer","string"],"description":"Position of the outcome in the task type's outcome list."}}}}},"examples":{"Request Example":{"value":{"tasktypeOutcomeRel":{"tasktype":1,"outcome":9,"display_order":0}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tasktypeOutcomeRel\": {\n        \"tasktype_id\": \"1\",\n        \"outcome_id\": \"9\",\n        \"display_order\": \"0\",\n        \"created_by\": \"0\",\n        \"created_utc_timestamp\": \"2021-04-05T15:19:36-05:00\",\n        \"updated_by\": null,\n        \"updated_utc_timestamp\": \"2021-04-05 15:19:36\",\n        \"links\": {\n            \"tasktype\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype\",\n            \"outcome\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome\",\n            \"createdBy\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy\"\n        },\n        \"id\": \"1\",\n        \"tasktype\": \"1\",\n        \"outcome\": \"9\",\n        \"createdBy\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"tasktypeOutcomeRel":{"type":"object","properties":{"tasktype_id":{"type":"string","example":"1"},"outcome_id":{"type":"string","example":"9"},"display_order":{"type":"string","example":"0"},"created_by":{"type":"string","example":"0"},"created_utc_timestamp":{"type":"string","example":"2021-04-05T15:19:36-05:00"},"updated_by":{},"updated_utc_timestamp":{"type":"string","example":"2021-04-05 15:19:36"},"links":{"type":"object","properties":{"tasktype":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype"},"outcome":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome"},"createdBy":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy"}}},"id":{"type":"string","example":"1"},"tasktype":{"type":"string","example":"1"},"outcome":{"type":"string","example":"9"},"createdBy":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"422":{"description":"422","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"A task outcome with the same title already exists.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Sentiment value must be one of Positive, Neutral, or Negative.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sentiment\"\n            }\n        }\n    ]\n}"}},"schema":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"A task outcome with the same title already exists."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_invalid"},"error":{"type":"string","example":""},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}}}}},"deprecated":false},"get":{"summary":"List all task type - outcome relations","description":"Retrieve all existing task type - outcome relations","operationId":"list-all-task-type-outcome-relations","x-canonical-resource":"tasktypeOutcomeRels","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tasktypeOutcomeRels\": [\n        {\n            \"tasktype_id\": \"1\",\n            \"outcome_id\": \"9\",\n            \"display_order\": \"0\",\n            \"created_by\": \"0\",\n            \"created_utc_timestamp\": \"2021-04-02T12:06:06-05:00\",\n            \"updated_by\": null,\n            \"updated_utc_timestamp\": \"2021-04-02 12:06:06\",\n            \"links\": {\n                \"tasktype\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/tasktype\",\n                \"outcome\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/outcome\",\n                \"createdBy\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/createdBy\"\n            },\n            \"id\": \"1\",\n            \"tasktype\": \"1\",\n            \"outcome\": \"9\",\n            \"createdBy\": \"1\"\n        },\n        {\n            \"tasktype_id\": \"1\",\n            \"outcome_id\": \"10\",\n            \"display_order\": \"1\",\n            \"created_by\": \"0\",\n            \"created_utc_timestamp\": \"2021-04-02T12:06:06-05:00\",\n            \"updated_by\": null,\n            \"updated_utc_timestamp\": \"2021-04-02 12:06:06\",\n            \"links\": {\n                \"tasktype\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/58/tasktype\",\n                \"outcome\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/58/outcome\",\n                \"createdBy\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/58/createdBy\"\n            },\n            \"id\": \"2\",\n            \"tasktype\": \"1\",\n            \"outcome\": \"10\",\n            \"createdBy\": \"1\"\n        },\n        {\n            \"tasktype_id\": \"2\",\n            \"outcome_id\": \"9\",\n            \"display_order\": \"2\",\n            \"created_by\": \"0\",\n            \"created_utc_timestamp\": \"2021-04-02T12:06:07-05:00\",\n            \"updated_by\": null,\n            \"updated_utc_timestamp\": \"2021-04-02 12:06:07\",\n            \"links\": {\n                \"tasktype\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/60/tasktype\",\n                \"outcome\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/60/outcome\",\n                \"createdBy\": \"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/60/createdBy\"\n            },\n            \"id\": \"3\",\n            \"tasktype\": \"2\",\n            \"outcome\": \"9\",\n            \"createdBy\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"tasktypeOutcomeRels":{"type":"array","items":{"type":"object","properties":{"tasktype_id":{"type":"string","example":"1"},"outcome_id":{"type":"string","example":"9"},"display_order":{"type":"string","example":"0"},"created_by":{"type":"string","example":"0"},"created_utc_timestamp":{"type":"string","example":"2021-04-02T12:06:06-05:00"},"updated_by":{},"updated_utc_timestamp":{"type":"string","example":"2021-04-02 12:06:06"},"links":{"type":"object","properties":{"tasktype":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/tasktype"},"outcome":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/outcome"},"createdBy":{"type":"string","example":"https://youraccountname.api-us1.com/api/3/tasktypeOutcomeRels/57/createdBy"}}},"id":{"type":"string","example":"1"},"tasktype":{"type":"string","example":"1"},"outcome":{"type":"string","example":"9"},"createdBy":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/tasktypeOutcomeRels/{id}":{"get":{"summary":"Retrieve a task type - outcome relation","description":"Retrieve an existing task type - outcome relation","operationId":"retrieve-a-task-type-outcome-relation","x-canonical-resource":"tasktypeOutcomeRels","parameters":[{"name":"id","in":"path","description":"Task type - outcome relation's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tasktypeOutcomeRel\": {\n        \"tasktype_id\": \"1\",\n        \"outcome_id\": \"9\",\n        \"display_order\": \"0\",\n        \"created_by\": \"0\",\n        \"created_utc_timestamp\": \"2021-04-05T15:19:36-05:00\",\n        \"updated_by\": null,\n        \"updated_utc_timestamp\": \"2021-04-05 15:19:36\",\n        \"links\": {\n            \"tasktype\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype\",\n            \"outcome\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome\",\n            \"createdBy\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy\"\n        },\n        \"id\": \"1\",\n        \"tasktype\": \"1\",\n        \"outcome\": \"9\",\n        \"createdBy\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"tasktypeOutcomeRel":{"type":"object","properties":{"tasktype_id":{"type":"string","example":"1"},"outcome_id":{"type":"string","example":"9"},"display_order":{"type":"string","example":"0"},"created_by":{"type":"string","example":"0"},"created_utc_timestamp":{"type":"string","example":"2021-04-05T15:19:36-05:00"},"updated_by":{},"updated_utc_timestamp":{"type":"string","example":"2021-04-05 15:19:36"},"links":{"type":"object","properties":{"tasktype":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype"},"outcome":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome"},"createdBy":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy"}}},"id":{"type":"string","example":"1"},"tasktype":{"type":"string","example":"1"},"outcome":{"type":"string","example":"9"},"createdBy":{"type":"string","example":"1"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TasktypeOutcomeRel with id 111\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TasktypeOutcomeRel with id 111"}}}}}}},"deprecated":false},"put":{"summary":"WIP Update a task type - outcome relation","description":"Update an existing task type - outcome relation","operationId":"update-a-task-outcome-1","x-canonical-resource":"tasktypeOutcomeRels","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Task type - outcome relation's id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["tasktypeOutcomeRel"],"properties":{"tasktypeOutcomeRel":{"type":"object","required":[],"properties":{"tasktype":{"type":["integer","string"],"description":"ID of the deal task type (see /dealTasktypes)."},"outcome":{"type":["integer","string"],"description":"ID of the task outcome (see /taskOutcomes)."},"display_order":{"type":["integer","string"],"description":"Position of the outcome in the task type's outcome list."}}}}},"examples":{"Request Example":{"value":{"tasktypeOutcomeRel":{"display_order":1}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"tasktypeOutcomeRel\": {\n        \"tasktype_id\": \"1\",\n        \"outcome_id\": \"9\",\n        \"display_order\": \"1\",\n        \"created_by\": \"0\",\n        \"created_utc_timestamp\": \"2021-04-05T15:19:36-05:00\",\n        \"updated_by\": null,\n        \"updated_utc_timestamp\": \"2021-04-05 15:19:36\",\n        \"links\": {\n            \"tasktype\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype\",\n            \"outcome\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome\",\n            \"createdBy\": \"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy\"\n        },\n        \"id\": \"1\",\n        \"tasktype\": \"1\",\n        \"outcome\": \"9\",\n        \"createdBy\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"tasktypeOutcomeRel":{"type":"object","properties":{"tasktype_id":{"type":"string","example":"1"},"outcome_id":{"type":"string","example":"9"},"display_order":{"type":"string","example":"1"},"created_by":{"type":"string","example":"0"},"created_utc_timestamp":{"type":"string","example":"2021-04-05T15:19:36-05:00"},"updated_by":{},"updated_utc_timestamp":{"type":"string","example":"2021-04-05 15:19:36"},"links":{"type":"object","properties":{"tasktype":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/tasktype"},"outcome":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/outcome"},"createdBy":{"type":"string","example":"https://:account.api-us1.com/api/3/tasktypeOutcomeRels/1/createdBy"}}},"id":{"type":"string","example":"1"},"tasktype":{"type":"string","example":"1"},"outcome":{"type":"string","example":"9"},"createdBy":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"422":{"description":"422","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"errors\": [\n        {\n            \"title\": \"A task outcome with the same title already exists.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/title\"\n            }\n        },\n        {\n            \"title\": \"Sentiment value must be one of Positive, Neutral, or Negative.\",\n            \"detail\": \"\",\n            \"code\": \"field_invalid\",\n            \"error\": \"\",\n            \"source\": {\n                \"pointer\": \"/data/attributes/sentiment\"\n            }\n        }\n    ]\n}"}},"schema":{"oneOf":[{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"The taskOutcome title was not provided."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_missing"},"error":{"type":"string","example":"taskOutcome_title_was_not_provided"},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}},{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","example":"A task outcome with the same title already exists."},"detail":{"type":"string","example":""},"code":{"type":"string","example":"field_invalid"},"error":{"type":"string","example":""},"source":{"type":"object","properties":{"pointer":{"type":"string","example":"/data/attributes/title"}}}}}}}}]}}}}},"deprecated":false},"delete":{"summary":"Delete a task type - outcome relation","description":"Delete an existing task type - outcome relation","operationId":"delete-a-task-type-outcome-relation","x-canonical-resource":"tasktypeOutcomeRels","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Task type - outcome relation's id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"text/plain":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TasktypeOutcomeRel with id 111\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TasktypeOutcomeRel with id 111"}}}}}}},"deprecated":false}},"/templates":{"post":{"summary":"Create a template","description":"Create an email template. This is the v3 equivalent of the v1 `message_template_add` action.\n\nRequires the `CreateEmailTemplates` permission. The new template is made available to the lists the authenticated user can access; users in the admin group create account-wide templates.","operationId":"create-a-template","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"object","properties":{"name":{"type":"string","description":"Template's name."},"subject":{"type":"string","description":"Default subject line applied to campaigns built from this template."},"content":{"type":"string","description":"HTML content of the template."},"categoryid":{"type":"integer","format":"int32","description":"ID of the template category."},"userid":{"type":"integer","format":"int32","description":"Owner of the template. Defaults to the authenticated user. Assigning another user requires permission to share templates with that user, otherwise the request answers `403`."},"ed_version":{"type":"integer","format":"int32","description":"Designer version the template is built for: `1` legacy, `2` current designer, `3` new designer."},"hidden":{"type":"integer","format":"int32","description":"Set to `1` to hide the template from the template gallery."},"additional_data":{"type":"object","description":"Free-form JSON metadata stored with the template."},"basecampaignid":{"type":"integer","description":"Id of a campaign whose content the template is created from."},"basetemplateid":{"type":["integer","string"],"description":"Id of an account template, or the hash of a stock template, to copy content from."}},"required":["name"]}},"required":["template"]},"examples":{"Request Example":{"value":{"template":{"name":"Welcome email","subject":"Welcome!","content":"<html><body>Hello!</body></html>","categoryid":1,"ed_version":2}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"template\": {\n        \"userid\": \"1\",\n        \"ed_instanceid\": \"0\",\n        \"ed_version\": \"2\",\n        \"name\": \"Welcome email\",\n        \"subject\": \"Welcome!\",\n        \"content\": \"<html><body>Hello!</body></html>\",\n        \"categoryid\": \"1\",\n        \"used\": \"3\",\n        \"waitpreview\": \"1\",\n        \"importnum\": \"0\",\n        \"mdate\": \"2026-08-23 10:04:11\",\n        \"preview_content\": null,\n        \"modified\": \"1\",\n        \"hidden\": \"0\",\n        \"source\": \"0\",\n        \"read_only\": \"0\",\n        \"additional_data\": null,\n        \"screenshot\": \"https://youraccountname.api-us1.com/tplimages/template-12.png\",\n        \"links\": [],\n        \"id\": \"12\"\n    }\n}"}},"schema":{"type":"object","properties":{"template":{"type":"object","properties":{"userid":{"type":"string"},"ed_instanceid":{"type":"string"},"ed_version":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"content":{"type":"string"},"categoryid":{"type":"string"},"used":{"type":"string"},"waitpreview":{"type":"string"},"importnum":{"type":"string"},"mdate":{"type":"string"},"preview_content":{},"modified":{"type":"string"},"hidden":{"type":"string"},"source":{"type":"string"},"read_only":{"type":"string"},"additional_data":{},"screenshot":{"type":"string"},"links":{"type":"array"},"id":{"type":"string"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"You cannot assign this template to that user\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}},"deprecated":false},"get":{"summary":"List all templates","description":"Retrieve the email templates in the account. Results are paginated and can be filtered; `meta.total` holds the total number of templates matching the request. Responses include each template's full HTML by default and are large as a result; pass `exclude=content,preview_content` whenever the body is not needed.","operationId":"list-all-templates","x-canonical-resource":"templates","parameters":[{"name":"limit","in":"query","description":"The number of templates to return for each call. Maximum value is 100.","schema":{"type":"integer","format":"int32","default":20}},{"name":"offset","in":"query","description":"Offset index of records to return.","schema":{"type":"integer","format":"int32","default":0}},{"name":"filters[name]","in":"query","description":"Filter by template name. Matches any template whose name contains this value.","schema":{"type":"string"}},{"name":"filters[id]","in":"query","description":"Filter by template id.","schema":{"type":"integer","format":"int32"}},{"name":"filters[categoryid]","in":"query","description":"Filter by template category id.","schema":{"type":"integer","format":"int32"}},{"name":"filters[source]","in":"query","description":"Filter by the source the template was created from.","schema":{"type":"integer","format":"int32"}},{"name":"filters[read_only]","in":"query","description":"Filter by read-only templates. Use 1 for read-only templates, 0 for editable ones.","schema":{"type":"integer","format":"int32"}},{"name":"filters[mdate]","in":"query","description":"Filter by the date the template was last modified (YYYY-MM-DD).","schema":{"type":"string"}},{"name":"filters[hidden]","in":"query","description":"Filter by hidden templates. Use 1 for hidden templates, 0 for visible ones.","schema":{"type":"integer","format":"int32"}},{"name":"filters[ed_version]","in":"query","description":"Filter by the designer version the template was built with.","schema":{"type":"integer","format":"int32"}},{"name":"filters[has_content]","in":"query","description":"Set to `true` to only return templates that have content.","schema":{"type":"string"}},{"name":"filters[tagid]","in":"query","description":"Filter to templates carrying the given tag id.","schema":{"type":"integer","format":"int32"}},{"name":"exclude","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of response fields to omit. Use `exclude=content,preview_content` unless the caller needs the template's HTML body: those two fields carry the whole email and dominate the response. On a five-template account the full response is roughly 512 KB, of which about 123 KB per record is `content` and about 60 KB is `preview_content`; omitting both returns the same ids, names, URLs and timestamps in roughly 2.6 KB. Listing, searching, counting and identifying templates need none of the omitted fields. Not supported on `GET /templates/{id}`, which always returns the full record."}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"templates\": [\n        {\n            \"userid\": \"1\",\n            \"ed_instanceid\": \"0\",\n            \"ed_version\": \"2\",\n            \"name\": \"Welcome email\",\n            \"subject\": null,\n            \"content\": \"<html><body>Hello!</body></html>\",\n            \"categoryid\": \"1\",\n            \"used\": \"0\",\n            \"waitpreview\": \"0\",\n            \"importnum\": \"0\",\n            \"mdate\": \"2026-08-11 09:14:22\",\n            \"preview_content\": null,\n            \"modified\": \"1\",\n            \"hidden\": \"0\",\n            \"source\": \"0\",\n            \"read_only\": \"0\",\n            \"additional_data\": null,\n            \"screenshot\": \"https://youraccountname.api-us1.com/tplimages/template-1.png\",\n            \"links\": [],\n            \"id\": \"1\"\n        }\n    ],\n    \"meta\": {\n        \"total\": \"1\"\n    }\n}"}},"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"ed_instanceid":{"type":"string","example":"0"},"ed_version":{"type":"string","example":"2"},"name":{"type":"string","example":"Welcome email"},"subject":{},"content":{"type":"string","example":"<html><body>Hello!</body></html>"},"categoryid":{"type":"string","example":"1"},"used":{"type":"string","example":"0"},"waitpreview":{"type":"string","example":"0"},"importnum":{"type":"string","example":"0"},"mdate":{"type":"string","example":"2026-08-11 09:14:22"},"preview_content":{},"modified":{"type":"string","example":"1"},"hidden":{"type":"string","example":"0"},"source":{"type":"string","example":"0"},"read_only":{"type":"string","example":"0"},"additional_data":{},"screenshot":{"type":"string","example":"https://youraccountname.api-us1.com/tplimages/template-1.png"},"links":{"type":"array"},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"1"}}}}}}}}},"deprecated":false}},"/templates/autoSave":{"put":{"summary":"Autosave the markup of a version 3 template","description":"Replaces the `content` of a template with the `html` and `css` sent, as the version 3 designer (Stripo) holds them. JavaScript event handlers and script tags are stripped from both first, and empty Emotion style tags from the html. The template is set to `ed_version` 3, the caller becomes its owner (`userid`), and its modified date is set to now. The compiled preview is not touched; see `PUT /templates/inlineStyles`. Requires the `pg_template_edit` permission and access to the template. Only PUT is served; any other method is answered 405. Internal: called by the template editor in the app (`campaign/template`) as the user edits.","operationId":"autosave-a-template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["templateId"],"properties":{"templateId":{"type":"integer","description":"ID of the template to save.","example":12},"html":{"type":"string","description":"HTML of the template, as the designer edits it. Both `html` and `css` are overwritten on every call, so leaving either out stores it empty."},"css":{"type":"string","description":"CSS of the template, as the designer edits it."}}}}}},"responses":{"200":{"description":"Saved. The response body is empty."},"400":{"description":"The body is empty or is not valid JSON. The response body is empty."},"403":{"description":"The caller lacks the `pg_template_edit` permission or may not modify the template. A `templateId` that names no template is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"500":{"description":"The save failed. The response body is empty; the cause is only logged."}},"deprecated":false,"x-internal":true}},"/templates/inlineStyles":{"put":{"summary":"Save the compiled HTML of a version 3 template","description":"Stores the ready-to-send HTML the version 3 designer (Stripo) compiles, with the styles inlined, as the template's `preview_content`. Before it is stored, images on the account's image hosts are pointed at the image resizer, four-byte characters are fixed and JavaScript event handlers and script tags are stripped. The caller becomes the template's owner (`userid`) and its modified date is set to now; `content` is not changed. Requires the `pg_template_edit` permission and access to the template. Only PUT is served; any other method is answered 405. Internal: called by the template editor in the app (`campaign/template`) when the user saves.","operationId":"update-template-compiled-html","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["templateId","compiledHtml"],"properties":{"templateId":{"type":"integer","description":"ID of the template to save.","example":12},"compiledHtml":{"type":"string","description":"Compiled HTML of the template, with the styles inlined."}}}}}},"responses":{"200":{"description":"Saved. The response body is empty."},"400":{"description":"The body is empty or is not valid JSON. The response body is empty."},"403":{"description":"The caller lacks the `pg_template_edit` permission or may not modify the template. A `templateId` that names no template is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"500":{"description":"The save failed. The response body is empty; the cause is only logged."}},"deprecated":false,"x-internal":true}},"/templates/screenshot":{"post":{"summary":"Request a new screenshot of a template","description":"Asks the screenshot service to take a new screenshot of the template, the thumbnail the template library shows. The template itself is not changed. Requires the `pg_template_edit` permission and access to the template. Only POST is served; any other method is answered 405, although the `Allow` header of that answer names PUT. Internal: called by the template editor in the app (`campaign/template`) after a save.","operationId":"request-a-template-screenshot","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["templateId"],"properties":{"templateId":{"type":"integer","description":"ID of the template to take a screenshot of.","example":12}}}}}},"responses":{"200":{"description":"The screenshot was requested. The response body is empty."},"400":{"description":"The body is empty or is not valid JSON. The response body is empty."},"403":{"description":"The caller lacks the `pg_template_edit` permission or may not modify the template. A `templateId` that names no template is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"500":{"description":"The request failed. The response body is empty; the cause is only logged."}},"deprecated":false,"x-internal":true}},"/templates/search":{"get":{"summary":"Search templates","description":"Searches the account's templates by name and ID, one page at a time. Hidden templates and templates with no content are never returned. Internal: read by the AI campaign tools.","operationId":"search-templates","parameters":[{"name":"limit","in":"query","description":"Number of templates to return, 1 to 100. Leaving it out is refused with 422.","required":true,"schema":{"type":"integer","maximum":100,"minimum":1},"example":10},{"name":"offset","in":"query","description":"Number of matching templates to skip. Leaving it out is refused with 422.","required":true,"schema":{"type":"integer","minimum":0},"example":0},{"name":"q","in":"query","description":"Words to search for, separated by spaces. A template matches when its name contains any word, or its ID equals a numeric word. Leave it out to list every template.","schema":{"type":"string"},"example":"welcome"},{"name":"modifiedBefore","in":"query","description":"Only templates last modified on or before this day, `Y-m-d`. Must be later than `modifiedAfter` when both are sent.","schema":{"type":"string"},"example":"2026-12-31"},{"name":"modifiedAfter","in":"query","description":"Only templates last modified on or after this day, `Y-m-d`.","schema":{"type":"string"},"example":"2026-01-01"},{"name":"edVersion","in":"query","description":"Designer version to search: `1`, `2` or `3`, or `all` for every version. Leave it out to search version 3 templates only, the only ones the template editor can open.","schema":{"type":"string","enum":["1","2","3","all"]},"example":"all"}],"responses":{"200":{"description":"One page of matching templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateSearchResponse"}}}},"422":{"description":"A query parameter was refused: `limit` or `offset` missing or out of range, a date that is not `Y-m-d`, `modifiedBefore` not later than `modifiedAfter`, or an unknown `edVersion`.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused check; a parameter can appear more than once.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always `Invalid attribute`.","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with the value.","type":"string","example":"This value should be between 1 and 100."},"source":{"description":"Which parameter was refused.","properties":{"pointer":{"description":"The parameter, as a JSON pointer under `/data/attributes`.","type":"string","example":"/data/attributes/limit"}},"type":"object"}},"type":"object"}}},"type":"object"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/templates/share":{"post":{"summary":"Import a shared template","description":"Creates a template in the account from a share link made with `POST /templates/{templateId}/share`, owned by the caller and available to the caller's lists (every list for an admin). The shared snapshot's tags come with it. Requires the `pg_template_add` permission. Internal: used by the AI template import tool.","operationId":"import-a-shared-template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportShareRequest"},"example":{"url":"http://tplshare.com/aB3dE5g"}}}},"responses":{"201":{"description":"The template was created","content":{"application/json":{"schema":{"required":["success","message","id"],"properties":{"success":{"description":"Always 1.","type":"integer","enum":[1],"example":1},"message":{"description":"Always `Template created successfully`.","type":"string","example":"Template created successfully"},"id":{"description":"ID of the new template, as a numeric string.","type":"string","example":"42"}},"type":"object"}}}},"400":{"description":"The link cannot be imported: it is not a URL with a scheme, host and path, its host is not the share host of this environment, no shared template has its hash, the shared template is too old for this account, or the request runs in developer mode. A body that is not JSON is also a 400, in the framework's `errors` body instead.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Why the link cannot be imported.","type":"string"}},"type":"object"},"example":{"message":"This share URL is not valid for this environment. Expected host: tplshare.com"}}}},"403":{"description":"The caller lacks `pg_template_add`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create templates"}]}}}},"422":{"description":"`url` is missing, empty, not a string, or longer than 500 characters.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One entry per refused check.","type":"array","items":{"properties":{"status":{"description":"Always 422.","type":"integer","example":422},"title":{"description":"Always `Invalid attribute`.","type":"string","example":"Invalid attribute"},"detail":{"description":"What is wrong with `url`.","type":"string","example":"Missing url parameter"},"source":{"description":"The refused field.","properties":{"pointer":{"description":"Always `/data/attributes/url`.","type":"string","example":"/data/attributes/url"}},"type":"object"}},"type":"object"}}},"type":"object"}}}},"500":{"description":"The import failed part-way. The message is the cause.","content":{"application/json":{"schema":{"properties":{"message":{"description":"The message of the error that stopped the import.","type":"string"}},"type":"object"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/templates/stock":{"get":{"summary":"List stock templates","description":"Lists the shared stock template catalog an account can start a template from. The whole matching catalog is read and then paged, so `total` counts every match; an `offset` greater than `total` returns the last `limit` templates instead of an empty page. Internal: read by the AI template tools.","operationId":"list-all-stock-templates","parameters":[{"name":"offset","in":"query","description":"Number of matching stock templates to skip.","schema":{"type":"integer","default":0},"example":0},{"name":"limit","in":"query","description":"Number of stock templates to return.","schema":{"type":"integer","default":20},"example":20},{"name":"search","in":"query","description":"Only stock templates whose name contains this text.","schema":{"type":"string"},"example":"newsletter"},{"name":"ed_version","in":"query","description":"Only stock templates for this designer version: `3` for the version 3 designer (Stripo), `2` for the classic designer. Leave it out for both.","schema":{"type":"integer","enum":[2,3]},"example":3},{"name":"orders","in":"query","description":"Sort order as `orders[<field>]=ASC|DESC`, repeatable; the order of the keys is the order of precedence. Sortable fields are `name`, `cdate`, `mdate` and `id`; the direction is case-insensitive, and any other field or direction is dropped. Without a usable order the newest modified come first.","style":"deepObject","explode":true,"schema":{"type":"object","additionalProperties":{"type":"string","enum":["ASC","DESC"]}},"example":{"name":"ASC"}}],"responses":{"200":{"description":"One page of stock templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateStockList"}}}},"400":{"description":"`ed_version` is something other than 2 or 3. An `orders` sent as a plain value rather than `orders[<field>]` is also a 400, in the framework's shorter body: `errors` items with a string `status` and a `detail`, no `title`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Invalid ed_version. Allowed values: 2, 3."}]}}}}},"x-canonical-resource":"templates","x-internal":true}},"/templates/stock/{hash}/markup":{"get":{"summary":"Retrieve the markup of a stock template","description":"Returns the editable html and css of one stock template, decoded from its catalog archive. Every hash answers 404 unless the account has the `ac-agents-stripo-campaign-gen` feature flag. Requires the `pg_message_add` permission; stock templates are a shared catalog, so there is no ownership check. Internal: read by the campaign generation engine.","operationId":"retrieve-stock-template-markup","parameters":[{"name":"hash","in":"path","description":"Hash of the stock template, the `id` that `GET /templates/stock` returns","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The markup of the stock template","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateStockMarkup"}}}},"403":{"description":"The caller lacks `pg_message_add`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to access template markup"}]}}}},"404":{"description":"The account does not have the feature flag, or no stock template has this hash. Both give the detail `Stock template '<hash>' not found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}},"422":{"description":"The archive of the stock template cannot be decoded, or it has no html. The detail says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"}}}}},"x-canonical-resource":"templates","x-internal":true}},"/templates/stripo":{"post":{"summary":"Import a template from Stripo","description":"Creates a version 3 designer (Stripo) template from its `html` and `css`. The template is owned by the caller, available to every list, and has a screenshot requested; a link to the designer's white-label stylesheet is added to the `<head>` of its html. JavaScript event handlers and script tags are stripped from `html`, `css` and `compiledHtml`. Requires the `pg_template_add` permission. The HTTP status of a create is 200; `meta.code` is 201. The same handler as `/templates/v3`, kept at this path because the Stripo service calls it to import and update templates its users build. Only POST and PUT are served; any other method is answered 405. Internal.","operationId":"import-a-stripo-template","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["html","css"],"properties":{"html":{"type":"string","description":"HTML of the template, as the designer edits it. Must not be empty."},"css":{"type":"string","description":"CSS of the template, as the designer edits it. Must not be empty."},"compiledHtml":{"type":"string","description":"Ready-to-send HTML with the styles inlined, stored as the preview. Leaving it out stores an empty preview."},"name":{"type":"string","description":"Name of the template. Defaults to `v3-` followed by a generated suffix.","example":"Spring sale"},"subject":{"type":"string","description":"Default subject line of the template. Defaults to `v3 Designer Template`.","example":"Our spring sale starts now"}}}}}},"responses":{"200":{"description":"The template was created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDesignerWriteResponse"}}}},"403":{"description":"The caller lacks the `pg_template_add` permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create templates"}]}}}},"500":{"description":"`html` or `css` is missing or empty, or the body is not JSON: the body is a translated plain-text message. When the insert itself fails the body is empty.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update a template imported from Stripo","description":"Replaces the `content` of a template with the `html` and `css` sent and its preview with `compiledHtml`, then requests a new screenshot. `name` and `subject` change only when they are sent. JavaScript event handlers and script tags are stripped from `html`, `css` and `compiledHtml`. The markup is replaced on every call, so a caller changing only the name has to send the markup back. Requires the `pg_template_edit` permission and access to the template. The same handler as `/templates/v3`, kept at this path because the Stripo service calls it to import and update templates its users build. Only POST and PUT are served; any other method is answered 405. Internal.","operationId":"update-an-imported-stripo-template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer","description":"ID of the template to update.","example":12},"html":{"type":"string","description":"HTML of the template, as the designer edits it. Leaving it out stores it empty."},"css":{"type":"string","description":"CSS of the template, as the designer edits it. Leaving it out stores it empty."},"compiledHtml":{"type":"string","description":"Ready-to-send HTML with the styles inlined, stored as the preview. Leaving it out stores an empty preview."},"name":{"type":"string","description":"New name of the template. Left as it is when not sent.","example":"Spring sale"},"subject":{"type":"string","description":"New default subject line of the template. Left as it is when not sent.","example":"Our spring sale starts now"}}}}}},"responses":{"200":{"description":"The template was updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDesignerWriteResponse"}}}},"403":{"description":"The caller lacks the `pg_template_edit` permission or may not modify the template. An `id` that names no template is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"404":{"description":"The body has no `id`. The body is a translated plain-text message.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The update failed. The response body is empty; the cause is only logged."}},"deprecated":false,"x-internal":true}},"/templates/v3":{"post":{"summary":"Create a version 3 template from markup","description":"Creates a version 3 designer (Stripo) template from its `html` and `css`. The template is owned by the caller, available to every list, and has a screenshot requested; a link to the designer's white-label stylesheet is added to the `<head>` of its html. JavaScript event handlers and script tags are stripped from `html`, `css` and `compiledHtml`. Requires the `pg_template_add` permission. The HTTP status of a create is 200; `meta.code` is 201. `/templates/stripo` is the same handler at the path the Stripo service knows. Only POST and PUT are served; any other method is answered 405. Internal.","operationId":"create-a-v3-template","x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["html","css"],"properties":{"html":{"type":"string","description":"HTML of the template, as the designer edits it. Must not be empty."},"css":{"type":"string","description":"CSS of the template, as the designer edits it. Must not be empty."},"compiledHtml":{"type":"string","description":"Ready-to-send HTML with the styles inlined, stored as the preview. Leaving it out stores an empty preview."},"name":{"type":"string","description":"Name of the template. Defaults to `v3-` followed by a generated suffix.","example":"Spring sale"},"subject":{"type":"string","description":"Default subject line of the template. Defaults to `v3 Designer Template`.","example":"Our spring sale starts now"}}}}}},"responses":{"200":{"description":"The template was created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDesignerWriteResponse"}}}},"403":{"description":"The caller lacks the `pg_template_add` permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to create templates"}]}}}},"500":{"description":"`html` or `css` is missing or empty, or the body is not JSON: the body is a translated plain-text message. When the insert itself fails the body is empty.","content":{"text/plain":{"schema":{"type":"string"}}}}},"deprecated":false,"x-internal":true},"put":{"summary":"Update a version 3 template from markup","description":"Replaces the `content` of a template with the `html` and `css` sent and its preview with `compiledHtml`, then requests a new screenshot. `name` and `subject` change only when they are sent. JavaScript event handlers and script tags are stripped from `html`, `css` and `compiledHtml`. The markup is replaced on every call, so a caller changing only the name has to send the markup back. Requires the `pg_template_edit` permission and access to the template. `/templates/stripo` is the same handler at the path the Stripo service knows. Only POST and PUT are served; any other method is answered 405. Internal: the AI template tools use it to rename a template, sending its markup back.","operationId":"update-a-v3-template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer","description":"ID of the template to update.","example":12},"html":{"type":"string","description":"HTML of the template, as the designer edits it. Leaving it out stores it empty."},"css":{"type":"string","description":"CSS of the template, as the designer edits it. Leaving it out stores it empty."},"compiledHtml":{"type":"string","description":"Ready-to-send HTML with the styles inlined, stored as the preview. Leaving it out stores an empty preview."},"name":{"type":"string","description":"New name of the template. Left as it is when not sent.","example":"Spring sale"},"subject":{"type":"string","description":"New default subject line of the template. Left as it is when not sent.","example":"Our spring sale starts now"}}}}}},"responses":{"200":{"description":"The template was updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDesignerWriteResponse"}}}},"403":{"description":"The caller lacks the `pg_template_edit` permission or may not modify the template. An `id` that names no template is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"404":{"description":"The body has no `id`. The body is a translated plain-text message.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The update failed. The response body is empty; the cause is only logged."}},"deprecated":false,"x-internal":true}},"/templates/{id}":{"get":{"summary":"Retrieve a template","description":"","operationId":"retrieve-a-template","x-canonical-resource":"templates","parameters":[{"name":"id","in":"path","description":"ID of the template to retrieve","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"template\": {\n        \"userid\": \"1\",\n        \"ed_instanceid\": \"0\",\n        \"ed_version\": \"0\",\n        \"name\": \"Test 2\",\n        \"subject\": null,\n        \"content\": \"<div>Thanks for subscribing, %FIRSTNAME%!</div>\",\n        \"categoryid\": \"1\",\n        \"used\": \"1\",\n        \"waitpreview\": \"1\",\n        \"importnum\": \"0\",\n        \"mdate\": \"2018-08-28 11:54:54\",\n        \"preview_content\": null,\n        \"modified\": \"1\",\n        \"hidden\": \"0\",\n        \"links\": [],\n        \"id\": \"2\"\n    }\n}"}},"schema":{"type":"object","properties":{"template":{"type":"object","properties":{"userid":{"type":"string","example":"1"},"ed_instanceid":{"type":"string","example":"0"},"ed_version":{"type":"string","example":"0"},"name":{"type":"string","example":"Test 2"},"subject":{},"content":{"type":"string","example":"<div>Thanks for subscribing, %FIRSTNAME%!</div>"},"categoryid":{"type":"string","example":"1"},"used":{"type":"string","example":"1"},"waitpreview":{"type":"string","example":"1"},"importnum":{"type":"string","example":"0"},"mdate":{"type":"string","example":"2018-08-28 11:54:54"},"preview_content":{},"modified":{"type":"string","example":"1"},"hidden":{"type":"string","example":"0"},"links":{"type":"array"},"id":{"type":"string","example":"2"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Template with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Template with id 10"}}}}}}},"deprecated":false},"delete":{"summary":"Delete a template","description":"Delete an existing message template. Associated designer instances and list associations are removed as well.","operationId":"delete-a-template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the template to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Template with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for Template with id 10"}}}}}}},"deprecated":false},"put":{"summary":"Update a template","description":"Update an existing email template. This is the v3 equivalent of the v1 `message_template_edit` action.\n\nRequires the `UpdateEmailTemplates` permission and access to the template being updated, otherwise the request answers `403`; an unknown id answers `404`.\n\nThe content of the template can also be reseeded from an existing campaign or template instead of being supplied directly: send `basecampaignid` to copy the content of a campaign message, or `basetemplateid` to copy the content of another template (a numeric id, which requires access to that template) or of a stock template (its identifier). The design of the source is carried over with the markup.","operationId":"update-a-template","x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","required":true,"description":"ID of the template to update","schema":{"type":"integer","format":"int32"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"object","properties":{"name":{"type":"string","description":"Template's name."},"hidden":{"type":"integer","format":"int32","description":"Set to `1` to hide the template from the template gallery."},"basecampaignid":{"type":"integer","format":"int32","description":"Reseed the content of this template from the message of the given campaign. Mutually exclusive with `basetemplateid`."},"basetemplateid":{"type":"string","description":"Reseed the content of this template from another template. A numeric id copies that template; any other value is treated as a stock template identifier. Mutually exclusive with `basecampaignid`."}},"additionalProperties":false}},"required":["template"],"additionalProperties":false},"examples":{"Request Example":{"value":{"template":{"name":"Welcome email (revised)"}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"template\": {\n        \"userid\": \"1\",\n        \"ed_instanceid\": \"0\",\n        \"ed_version\": \"2\",\n        \"name\": \"Welcome email\",\n        \"subject\": \"Welcome!\",\n        \"content\": \"<html><body>Hello!</body></html>\",\n        \"categoryid\": \"1\",\n        \"used\": \"3\",\n        \"waitpreview\": \"1\",\n        \"importnum\": \"0\",\n        \"mdate\": \"2026-08-23 10:04:11\",\n        \"preview_content\": null,\n        \"modified\": \"1\",\n        \"hidden\": \"0\",\n        \"source\": \"0\",\n        \"read_only\": \"0\",\n        \"additional_data\": null,\n        \"screenshot\": \"https://youraccountname.api-us1.com/tplimages/template-12.png\",\n        \"links\": [],\n        \"id\": \"12\"\n    }\n}"}},"schema":{"type":"object","properties":{"template":{"type":"object","properties":{"userid":{"type":"string"},"ed_instanceid":{"type":"string"},"ed_version":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"content":{"type":"string"},"categoryid":{"type":"string"},"used":{"type":"string"},"waitpreview":{"type":"string"},"importnum":{"type":"string"},"mdate":{"type":"string"},"preview_content":{},"modified":{"type":"string"},"hidden":{"type":"string"},"source":{"type":"string"},"read_only":{"type":"string"},"additional_data":{},"screenshot":{"type":"string"},"links":{"type":"array"},"id":{"type":"string"}}}}}}}},"403":{"description":"403","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"You do not have permission to modify this template\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for Template with id 10\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}},"deprecated":false},"patch":{"summary":"Update a template (PATCH)","description":"The PATCH form of `PUT /templates/{id}`: both verbs reach the same handler and behave the same. Only `name`, `hidden` and a content reseed from `basecampaignid` or `basetemplateid` are applied; every other key of `template` is ignored. The modified date is set to now. Requires the `pg_template_edit` permission and access to the template. Internal: the documented update is `PUT /templates/{id}`.","operationId":"patch-a-template","parameters":[{"name":"id","in":"path","description":"ID of the template to update","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePatchRequest"},"example":{"template":{"name":"Welcome email (revised)","hidden":0}}}}},"responses":{"200":{"description":"The template after the update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateItemResponse"}}}},"400":{"description":"`name` is not a string, or the body is JSON but not an object. Nothing was changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":400,"title":"Bad Request","detail":"Invalid name. It must be a string."}]}}}},"403":{"description":"The caller lacks `pg_template_edit`, may not modify this template, or may not modify the `basetemplateid` source template. A `basecampaignid` campaign the caller may not read is refused with the same status in the framework's shorter body: `errors` items with a string `status` and a `detail`, no `title`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"404":{"description":"No template has this ID, or no template has the numeric `basetemplateid`. A `basecampaignid` that names no campaign is also a 404, in the framework's `errors` body with the detail `Campaign not found`.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Which record was not found.","type":"string"}},"type":"object"},"example":{"message":"No Result found for Template with id 10"}}}},"422":{"description":"The template failed model validation when it was saved. The body is the validation message as plain text, not JSON.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"The body has no `template` object, or the write failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerErrorResponse"}}}}},"x-canonical-resource":"templates","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/templates/{templateId}/share":{"post":{"summary":"Create a share link for a template","description":"Publishes a snapshot of the template to the template share service and returns the public link another account can import it from with `POST /templates/share`. Only version 2 (classic designer, with its designer instance) and version 3 templates can be shared. Requires the `pg_template_add` permission and access to the template. Internal.","operationId":"create-a-template-share-link","parameters":[{"name":"templateId","in":"path","description":"ID of the template to share","required":true,"schema":{"type":"integer"}}],"responses":{"201":{"description":"The share link was created","content":{"application/json":{"schema":{"required":["success","message","hash","url"],"properties":{"success":{"description":"Always 1.","type":"integer","enum":[1],"example":1},"message":{"description":"Always `Template shared successfully`.","type":"string","example":"Template shared successfully"},"hash":{"description":"Seven-character hash that identifies the shared snapshot.","type":"string","example":"aB3dE5g"},"url":{"description":"Public share link, `http://<share host>/<hash>`.","type":"string","example":"http://tplshare.com/aB3dE5g"}},"type":"object"}}}},"400":{"description":"The template cannot be shared: its version is too old to import, or the request runs in developer mode.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Why the template cannot be shared.","type":"string"}},"type":"object"},"example":{"message":"You cannot create shared templates in developer mode."}}}},"403":{"description":"The caller lacks `pg_template_add`, or may not modify this template. A template ID that does not exist is refused the same way.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpExceptionErrorResponse"},"example":{"errors":[{"status":403,"title":"Forbidden","detail":"You do not have permission to modify this template"}]}}}},"500":{"description":"The share could not be created. The message is the cause.","content":{"application/json":{"schema":{"properties":{"message":{"description":"The message of the error that stopped the share.","type":"string"}},"type":"object"},"example":{"message":"Failed to create share hash"}}}}},"x-canonical-resource":"templates","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/tracking/generate-tracked-message":{"post":{"summary":"Generate a tracked message","description":"Internal: test-only endpoint (TrackedMessageGeneratorController is marked ONLY USED FOR TESTING PURPOSES) used by QA automation to render a campaign message for a contact with its tracked links. Not for publication.","operationId":"generate-tracked-message","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["subscriberId","listId","messageId","campaignId"],"properties":{"subscriberId":{"type":"integer","format":"int32"},"listId":{"type":"integer","format":"int32"},"messageId":{"type":"integer","format":"int32"},"campaignId":{"type":"integer","format":"int32"},"linkId":{"description":"Restricts the result to this link, which must belong to messageId.","type":["integer","string","null"]}},"type":"object","additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"properties":{"tracked_links":{"type":"array","items":{"type":"object","additionalProperties":true}},"final_content":{"type":"string"}},"type":"object"}}}},"400":{"description":"Malformed body or invalid IDs","content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}}},"404":{"description":"Contact, campaign or message not found","content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}}},"500":{"description":"Unexpected failure","content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}}}},"x-canonical-resource":"campaign","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/tracking/omni-channel-link-data":{"post":{"summary":"Record omni-channel link data","description":"Internal: service-to-service endpoint called by Kirby with a Hosted-audience JWT (config/kirby.php) to record a tracked link interaction for a contact. Not a customer API. camelCase body keys are accepted and normalised to snake_case.","operationId":"create-omni-channel-link-data","x-canonical-resource":"tracked_event","x-destructive":false,"x-bulk-operation":false,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Each field may be sent in snake_case or camelCase (`messageId`, `linkId`, `subscriberId`, `eventTimestamp`); sending both forms of one field is rejected with 400.","required":["type"],"allOf":[{"anyOf":[{"required":["message_id"]},{"required":["messageId"]}]},{"anyOf":[{"required":["link_id"]},{"required":["linkId"]}]},{"anyOf":[{"required":["subscriber_id"]},{"required":["subscriberId"]}]}],"properties":{"message_id":{"type":["integer","string"]},"messageId":{"type":["integer","string"]},"link_id":{"type":["integer","string"]},"linkId":{"type":["integer","string"]},"subscriber_id":{"type":["integer","string"]},"subscriberId":{"type":["integer","string"]},"type":{"type":"string"},"event_timestamp":{"type":"string"},"eventTimestamp":{"type":"string"},"list":{"type":["integer","string","array"],"items":{"type":["integer","string"]},"description":"List ID whose sms_link_clicked webhooks are fired; when absent no webhook is sent."}},"additionalProperties":false}}}},"responses":{"200":{"description":"200","content":{"application/json":{"schema":{"type":"object","properties":{"omniChannelLinkData":{"$ref":"#/components/schemas/OmniChannelLinkData"}}}}}},"400":{"description":"Body is not valid JSON, or the same field was sent in both snake_case and camelCase","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"A required field is missing or empty (the service's validation error is caught by the controller's catch-all handler), or the record could not be saved","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}},"deprecated":false,"x-internal":true}},"/trackingLogs":{"get":{"summary":"List the tracked events that have fired, with their contacts","description":"Lists site-tracking and event-tracking log entries across all contacts, 20 per page by default. Each entry's id is the eventId that GET /trackingLogs/{eventId}/contact accepts. Use filters[subscriberid] to scope the list to one contact. Use only the query parameters documented here: unsupported filter and order fields are silently ignored, so the response looks filtered but is not. An entry's type is __pagevisit for a site-tracking page visit (value holds the page URL), __redir for a tracked link redirect (value holds the destination URL), or the name of an event-tracking event (value holds the event data). Entries are copied in when a contact's activity feed is refreshed, so events recorded moments ago may not appear yet.","operationId":"list-all-tracked-events","x-canonical-resource":"tracked_event","parameters":[{"name":"filters[subscriberid]","in":"query","description":"Return only entries belonging to this contact id. Exact match.","schema":{"type":"string"}},{"name":"filters[tstamp]","in":"query","description":"Return only entries recorded at this exact date and time, formatted YYYY-MM-DD HH:MM:SS in the account's timezone. A date without a time matches only entries recorded at exactly 00:00:00.","schema":{"type":"string"}},{"name":"filters[type]","in":"query","description":"Return only entries whose type contains this text (substring match). Operator suffixes such as filters[type][eq] are not supported on this endpoint and fall back to the same substring match.","schema":{"type":"string"}},{"name":"orders[tstamp]","in":"query","description":"Order entries by recorded time. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[subscriberid]","in":"query","description":"Order entries by contact id. ASC or DESC.","schema":{"type":"string"}},{"name":"orders[type]","in":"query","description":"Order entries by type. ASC or DESC.","schema":{"type":"string"}},{"name":"ids","in":"query","description":"Comma-separated list of entry ids to fetch. Overrides limit.","schema":{"type":"string"}},{"name":"include","in":"query","description":"include=contact adds a contacts array to the response holding the contact each entry belongs to.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of entries per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"offset","in":"query","description":"Number of entries to skip, for pagination.","schema":{"type":"integer"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"trackingLogs\": [\n        {\n            \"subscriberid\": \"112\",\n            \"type\": \"__pagevisit\",\n            \"value\": \"https://example.com/pricing\",\n            \"tstamp\": \"2026-09-18T12:20:52-05:00\",\n            \"hash\": \"d855fd4ecb9dd4a88c9b30cc857c765a913ebd69\",\n            \"links\": {\n                \"contact\": \"https://yourAccountName.api-us1.com/api/3/trackingLogs/1/contact\"\n            },\n            \"id\": \"1\",\n            \"contact\": \"112\"\n        },\n        {\n            \"subscriberid\": \"112\",\n            \"type\": \"Order Shipped\",\n            \"value\": \"order 1042\",\n            \"tstamp\": \"2026-09-18T12:25:52-05:00\",\n            \"hash\": \"b0390c0772f0b5393486e7c542b80bd4d41730e8\",\n            \"links\": {\n                \"contact\": \"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact\"\n            },\n            \"id\": \"2\",\n            \"contact\": \"112\"\n        }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}"}},"schema":{"type":"object","properties":{"trackingLogs":{"type":"array","items":{"type":"object","properties":{"subscriberid":{"type":"string","example":"112"},"type":{"type":"string","example":"Order Shipped"},"value":{"type":"string","example":"order 1042"},"tstamp":{"type":"string","example":"2026-09-18T12:25:52-05:00"},"hash":{"type":"string","example":"b0390c0772f0b5393486e7c542b80bd4d41730e8"},"links":{"type":"object","properties":{"contact":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact"}}},"id":{"type":"string","example":"2"},"contact":{"type":"string","example":"112"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":2}}}}}}}}},"deprecated":false}},"/trackingLogs/{eventId}/contact":{"get":{"summary":"Get Contact By Event ID","description":"Returns the contact that a tracking-log entry belongs to. eventId must be the id of a tracking log entry, as returned by GET /contacts/{id}/trackingLogs or GET /trackingLogs. It is not a contact id and not an event-tracking event name. Passing a contact id returns 404 (No Result found for TrackingLog) when no entry has that id, or the contact of an unrelated entry when one does, so a 200 does not mean the id spaces are interchangeable. To fetch a contact by contact id, use GET /contacts/{id} (get-contact) instead. To list the tracking events of a known contact, use GET /contacts/{id}/trackingLogs.","operationId":"get-contact-by-event-id","x-canonical-resource":"tracked_event","parameters":[{"name":"eventId","in":"path","description":"The id of a tracking log entry: the id field returned by GET /contacts/{id}/trackingLogs or GET /trackingLogs. Not a contact id and not an event name; to look up a contact by its id use GET /contacts/{id} instead.","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"contact\": {\n        \"cdate\": \"2022-09-22T12:36:33-05:00\",\n        \"email\": \"jd@example.com\",\n        \"phone\": \"555-555-5555\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"orgid\": \"0\",\n        \"orgname\": \"\",\n        \"segmentio_id\": \"\",\n        \"bounced_hard\": \"0\",\n        \"bounced_soft\": \"0\",\n        \"bounced_date\": \"0000-00-00\",\n        \"ip\": \"0\",\n        \"ua\": \"\",\n        \"hash\": \"ef73fe360240b8bf171744f7f341524f\",\n        \"socialdata_lastcheck\": \"0000-00-00 00:00:00\",\n        \"email_local\": \"\",\n        \"email_domain\": \"example.com\",\n        \"sentcnt\": \"0\",\n        \"rating_tstamp\": \"0000-00-00\",\n        \"gravatar\": \"0\",\n        \"deleted\": \"0\",\n        \"anonymized\": \"0\",\n        \"adate\": \"2022-09-27T14:57:35-05:00\",\n        \"udate\": \"2022-09-22T12:36:33-05:00\",\n        \"edate\": \"2022-09-27T13:36:04-05:00\",\n        \"deleted_at\": \"0000-00-00 00:00:00\",\n        \"created_utc_timestamp\": \"2022-09-22 12:36:33\",\n        \"updated_utc_timestamp\": \"2022-09-27 13:36:04\",\n        \"created_timestamp\": \"2022-09-22 12:36:33\",\n        \"updated_timestamp\": \"2022-09-27 13:36:04\",\n        \"created_by\": \"0\",\n        \"updated_by\": \"0\",\n        \"email_empty\": false,\n        \"mpp_tracking\": \"0\",\n        \"links\": {\n            \"bounceLogs\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/bounceLogs\",\n            \"contactAutomations\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactAutomations?limit=1000&orders%5Blastdate%5D=DESC\",\n            \"contactData\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactData\",\n            \"contactGoals\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactGoals\",\n            \"contactLists\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactLists\",\n            \"contactLogs\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactLogs\",\n            \"contactTags\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactTags\",\n            \"contactDeals\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/contactDeals\",\n            \"deals\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/deals\",\n            \"fieldValues\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/fieldValues\",\n            \"geoIps\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/geoIps\",\n            \"notes\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/notes\",\n            \"organization\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/organization\",\n            \"plusAppend\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/plusAppend\",\n            \"trackingLogs\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/trackingLogs\",\n            \"scoreValues\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/scoreValues\",\n            \"accountContacts\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/accountContacts\",\n            \"automationEntryCounts\": \"https://yourAccountName.api-us1.com/api/3/contacts/112/automationEntryCounts\"\n        },\n        \"id\": \"112\",\n        \"organization\": null\n    }\n}"}},"schema":{"type":"object","properties":{"contact":{"type":"object","properties":{"cdate":{"type":"string","example":"2022-09-22T12:36:33-05:00"},"email":{"type":"string","example":"jd@example.com"},"phone":{"type":"string","example":"555-555-5555"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"orgid":{"type":"string","example":"0"},"orgname":{"type":"string","example":""},"segmentio_id":{"type":"string","example":""},"bounced_hard":{"type":"string","example":"0"},"bounced_soft":{"type":"string","example":"0"},"bounced_date":{"type":"string","example":"0000-00-00"},"ip":{"type":"string","example":"0"},"ua":{"type":"string","example":""},"hash":{"type":"string","example":"ef73fe360240b8bf171744f7f341524f"},"socialdata_lastcheck":{"type":"string","example":"0000-00-00 00:00:00"},"email_local":{"type":"string","example":""},"email_domain":{"type":"string","example":"example.com"},"sentcnt":{"type":"string","example":"0"},"rating_tstamp":{"type":"string","example":"0000-00-00"},"gravatar":{"type":"string","example":"0"},"deleted":{"type":"string","example":"0"},"anonymized":{"type":"string","example":"0"},"adate":{"type":"string","example":"2022-09-27T14:57:35-05:00"},"udate":{"type":"string","example":"2022-09-22T12:36:33-05:00"},"edate":{"type":"string","example":"2022-09-27T13:36:04-05:00"},"deleted_at":{"type":"string","example":"0000-00-00 00:00:00"},"created_utc_timestamp":{"type":"string","example":"2022-09-22 12:36:33"},"updated_utc_timestamp":{"type":"string","example":"2022-09-27 13:36:04"},"created_timestamp":{"type":"string","example":"2022-09-22 12:36:33"},"updated_timestamp":{"type":"string","example":"2022-09-27 13:36:04"},"created_by":{"type":"string","example":"0"},"updated_by":{"type":"string","example":"0"},"email_empty":{"type":"boolean","example":false,"default":true},"mpp_tracking":{"type":"string","example":"0"},"links":{"type":"object","properties":{"bounceLogs":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/bounceLogs"},"contactAutomations":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactAutomations?limit=1000&orders%5Blastdate%5D=DESC"},"contactData":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactData"},"contactGoals":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactGoals"},"contactLists":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactLists"},"contactLogs":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactLogs"},"contactTags":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactTags"},"contactDeals":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/contactDeals"},"deals":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/deals"},"fieldValues":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/fieldValues"},"geoIps":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/geoIps"},"notes":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/notes"},"organization":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/organization"},"plusAppend":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/plusAppend"},"trackingLogs":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/trackingLogs"},"scoreValues":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/scoreValues"},"accountContacts":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/accountContacts"},"automationEntryCounts":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/contacts/112/automationEntryCounts"}}},"id":{"type":"string","example":"112"},"organization":{}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TrackingLog with id 999\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TrackingLog with id 999"}}}}}}},"deprecated":false}},"/trackingLogs/{id}":{"get":{"summary":"Retrieve a tracking log entry","description":"Returns a single tracking log entry by its id. The same id is the eventId that GET /trackingLogs/{eventId}/contact accepts. Entry ids are returned by GET /trackingLogs and GET /contacts/{id}/trackingLogs; they are not contact ids. Returns 404 if no entry has the given id.","operationId":"retrieve-a-tracking-log","x-canonical-resource":"tracked_event","parameters":[{"name":"id","in":"path","description":"The tracking log entry's id. Not a contact id.","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"trackingLog\": {\n        \"subscriberid\": \"112\",\n        \"type\": \"Order Shipped\",\n        \"value\": \"order 1042\",\n        \"tstamp\": \"2026-09-18T12:25:52-05:00\",\n        \"hash\": \"b0390c0772f0b5393486e7c542b80bd4d41730e8\",\n        \"links\": {\n            \"contact\": \"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact\"\n        },\n        \"id\": \"2\",\n        \"contact\": \"112\"\n    }\n}"}},"schema":{"type":"object","properties":{"trackingLog":{"type":"object","properties":{"subscriberid":{"type":"string","example":"112"},"type":{"type":"string","example":"Order Shipped"},"value":{"type":"string","example":"order 1042"},"tstamp":{"type":"string","example":"2026-09-18T12:25:52-05:00"},"hash":{"type":"string","example":"b0390c0772f0b5393486e7c542b80bd4d41730e8"},"links":{"type":"object","properties":{"contact":{"type":"string","example":"https://yourAccountName.api-us1.com/api/3/trackingLogs/2/contact"}}},"id":{"type":"string","example":"2"},"contact":{"type":"string","example":"112"}}}}}}}},"404":{"description":"404","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"message\": \"No Result found for TrackingLog with id 999\"\n}"}},"schema":{"type":"object","properties":{"message":{"type":"string","example":"No Result found for TrackingLog with id 999"}}}}}}},"deprecated":false}},"/updates":{"get":{"summary":"List all contact update records","description":"Lists the records kept each time a contact updates their details through a campaign's update link, across the whole account. Each record names the contact, the campaign and the message. The list has no filters or sort options, and records come in no guaranteed order. Page with limit and offset, or fetch specific records with ids.","operationId":"list-all-contact-update-records","x-canonical-resource":"campaign","x-internal":true,"parameters":[{"name":"limit","in":"query","description":"Number of records to return. Defaults to 20; values above 100 are treated as 100. The value is read as a whole number. 0, a negative number or a value that does not read as a number returns every record, and offset then has no effect. The string null returns up to 1000.","schema":{"type":["integer","string"],"default":20}},{"name":"offset","in":"query","description":"Number of records to skip. Use with limit to page through the records.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"ids","in":"query","description":"Comma-separated record IDs to return. When set, only those records are returned; limit does not apply, but offset still does. An empty ids, or ids=0, returns one record.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of records under updates, with the number of matching records in meta.total. updates is an empty array when there are none.","content":{"application/json":{"schema":{"type":"object","properties":{"updates":{"type":"array","description":"The records on this page.","items":{"$ref":"#/components/schemas/ContactUpdateRecord"}},"meta":{"type":"object","description":"About the whole result, not just this page.","properties":{"total":{"type":"integer","description":"Number of matching records across all pages. When ids is set and is not empty or 0, the number of those ids that exist.","example":1}}}}},"examples":{"Result":{"value":{"updates":[{"subscriberid":"110","campaignid":"12","messageid":"15","tstamp":"2026-10-14T09:12:44-05:00","ip":"3405803786","links":{"contact":"https://example.api-us1.com/api/3/updates/31/contact","campaign":"https://example.api-us1.com/api/3/updates/31/campaign","message":"https://example.api-us1.com/api/3/updates/31/message"},"id":"31","contact":"110","campaign":"12","message":"15"}],"meta":{"total":1}}}}}}}},"deprecated":false}},"/updates/{id}":{"get":{"summary":"Retrieve a contact update record","description":"Returns one record by its ID. Each record is kept when a contact updates their details through a campaign's update link. Returns 404 if no record has the id.","operationId":"retrieve-a-contact-update-record","x-canonical-resource":"campaign","x-internal":true,"parameters":[{"name":"id","in":"path","description":"ID of the record.","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The record under update.","content":{"application/json":{"schema":{"type":"object","properties":{"update":{"description":"The record.","allOf":[{"$ref":"#/components/schemas/ContactUpdateRecord"}]}}},"examples":{"Result":{"value":{"update":{"subscriberid":"110","campaignid":"12","messageid":"15","tstamp":"2026-10-14T09:12:44-05:00","ip":"3405803786","links":{"contact":"https://example.api-us1.com/api/3/updates/31/contact","campaign":"https://example.api-us1.com/api/3/updates/31/campaign","message":"https://example.api-us1.com/api/3/updates/31/message"},"id":"31","contact":"110","campaign":"12","message":"15"}}}}}}},"404":{"description":"No record has that id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Says which id was not found.","example":"No Result found for Update with id 100"}}},"examples":{"Result":{"value":{"message":"No Result found for Update with id 100"}}}}}}},"deprecated":false}},"/userStates/all":{"get":{"summary":"Retrieve the user's saved interface state","description":"Returns every piece of interface state saved for the calling user, such as a page's last chosen folder or column layout. It is saved with POST /userStates/all. State is kept per user in a cache store, grouped by namespace, then by key. Returns an empty object when nothing is saved. Methods other than GET and POST write nothing and return 200 with an empty body.","operationId":"retrieve-all-user-states","x-canonical-resource":"account_user","x-internal":true,"responses":{"200":{"description":"The saved state, by namespace and key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStateNamespaces"},"examples":{"Result":{"value":{"automation":{"lastFolder":{"type":"value","value":"12"},"recentIds":{"type":"list","value":["4","9","2"]},"columns":{"type":"hash","value":{"name":"1","status":"0"}}}}}}}}}}},"post":{"summary":"Save interface state for the user","description":"Saves pieces of interface state for the calling user. The body is an object of namespaces, each an object of keys, each with a type and a value. Each key named replaces what was saved under that namespace and key; keys not named stay as they are. type must be value, list, set or hash. Keys are saved one at a time, so keys before one with an invalid type stay saved. Values come back from GET /userStates/all as strings. Returns the body decoded and encoded again, so an empty object comes back as an empty array: {} returns []. A body that is not a JSON object or array saves nothing, and the response is the decoded body (null when it is not JSON).","operationId":"save-user-states","x-canonical-resource":"account_user","x-internal":true,"x-destructive":true,"x-bulk-operation":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStateNamespaces"},"examples":{"Request":{"value":{"automation":{"lastFolder":{"type":"value","value":"12"},"columns":{"type":"hash","value":{"name":"1","status":"0"}}}}}}}}},"responses":{"200":{"description":"The request body, decoded and encoded again. Empty objects come back as empty arrays.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStateNamespaces"}}}}}}},"/users":{"post":{"summary":"Create a user","description":"Create a new user with full account access, gated by their group (role). All of `username`, `email`, `firstName`, `lastName`, `group` and `password` are required — there is no partial or invited-user creation. `password` must be at least 8 characters; `username` may contain only lower-case letters and/or numbers, no spaces.","operationId":"create-user","x-canonical-resource":"account_user","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"user":{"properties":{"username":{"type":"string","description":"Username. Lower-case letters and/or numbers only, no spaces."},"email":{"type":"string","description":"Email address"},"firstName":{"type":"string","description":"First name"},"lastName":{"type":"string","description":"Last name"},"group":{"type":"integer","description":"Group ID","format":"int32"},"password":{"type":"string","description":"Plain text password. At least 8 characters."},"phone":{"type":"string"},"signature":{"type":"string"},"mfaEnabled":{"type":["boolean","integer"]},"roles":{"type":["string","null"],"description":"JSON-encoded array of role names."},"seats":{"type":"array","items":{"type":"integer"},"description":"Seat ids to assign."},"lang":{"type":"string"},"timezone":{"type":"string"}},"required":["username","email","firstName","lastName","group","password"],"type":"object"}},"required":["user"]},"examples":{"Request Example":{"value":{"user":{"username":"jdoe","firstName":"John","lastName":"Doe","email":"johndoe@example.com","password":"myPa$$w0rd","group":4}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n    \"user\": {\n        \"username\": \"jdoe\",\n        \"email\": \"johndoe@example.com\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"lang\": \"english\",\n        \"localZoneid\": \"America/New_York\",\n        \"cdate\": \"2022-02-02T16:01:44-06:00\",\n        \"udate\": \"2022-02-02T16:01:44-06:00\",\n        \"links\": {\n            \"lists\": \"https://:account.api-us1.com/api/3/users/3/lists\",\n            \"userGroup\": \"https://:account.api-us1.com/api/3/users/3/userGroup\",\n            \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/3/dealGroupTotals\",\n            \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/3/dealGroupUsers\",\n            \"configs\": \"https://:account.api-us1.com/api/3/users/3/configs\",\n            \"dealConnection\": \"https://:account.api-us1.com/api/3/users/3/dealConnection\",\n            \"userConversationsPermission\": \"https://:account.api-us1.com/api/3/users/3/userConversationsPermission\",\n            \"seatUser\": \"https://:account.api-us1.com/api/3/users/3/seatUser\"\n        },\n        \"id\": \"3\"\n    }\n}"}},"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"username":{"type":"string","example":"jdoe"},"email":{"type":"string","example":"johndoe@example.com"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"lang":{"type":"string","example":"english"},"localZoneid":{"type":"string","example":"America/New_York"},"cdate":{"type":"string","example":"2022-02-02T16:01:44-06:00"},"udate":{"type":"string","example":"2022-02-02T16:01:44-06:00"},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/configs"},"dealConnection":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/dealConnection"},"userConversationsPermission":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/userConversationsPermission"},"seatUser":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/seatUser"}}},"id":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"get":{"summary":"List all users","description":"List all existing users","operationId":"list-all-users","x-canonical-resource":"account_user","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"users\": [\n    {\n      \"username\": \"admin\",\n      \"firstName\": \"John\",\n      \"lastName\": \"Doe\",\n      \"email\": \"johndoe@example.com\",\n      \"phone\": \"\",\n      \"signature\": null,\n      \"links\": {\n        \"lists\": \"https://:account.api-us1.com/api/3/users/1/lists\",\n        \"userGroup\": \"https://:account.api-us1.com/api/3/users/1/userGroup\",\n        \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/1/dealGroupTotals\",\n        \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/1/dealGroupUsers\",\n        \"configs\": \"https://:account.api-us1.com/api/3/users/1/configs\"\n      },\n      \"id\": \"1\"\n    },\n    {\n      \"username\": \"janedoe\",\n      \"firstName\": \"Jane\",\n      \"lastName\": \"Doe\",\n      \"email\": \"janedoe@example.com\",\n      \"phone\": \"\",\n      \"signature\": null,\n      \"links\": {\n        \"lists\": \"https://:account.api-us1.com/api/3/users/5/lists\",\n        \"userGroup\": \"https://:account.api-us1.com/api/3/users/5/userGroup\",\n        \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/5/dealGroupTotals\",\n        \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/5/dealGroupUsers\",\n        \"configs\": \"https://:account.api-us1.com/api/3/users/5/configs\"\n      },\n      \"id\": \"5\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}},"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","properties":{"username":{"type":"string","example":"admin"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/configs"}}},"id":{"type":"string","example":"1"}}}},"meta":{"type":"object","properties":{"total":{"type":"string","example":"2"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/users/email/{email}":{"get":{"summary":"Retrieve a user by email","description":"Retrieve an existing user by looking up their email address","operationId":"get-user-email","x-canonical-resource":"account_user","parameters":[{"name":"email","in":"path","description":"Email address of the user you want to view","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"user\": {\n    \"username\": \"somebody\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"email\": \"johndoe@example.com\",\n    \"phone\": \"\",\n    \"signature\": null,\n    \"links\": {\n      \"lists\": \"https://:account.api-us1.com/api/3/users/1/lists\",\n      \"userGroup\": \"https://:account.api-us1.com/api/3/users/1/userGroup\",\n      \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/1/dealGroupTotals\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/1/dealGroupUsers\",\n      \"configs\": \"https://:account.api-us1.com/api/3/users/1/configs\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"username":{"type":"string","example":"somebody"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/configs"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/users/me":{"get":{"summary":"Retrieve logged-in user","description":"Retrieve the logged-in user","operationId":"get-user-loggedin","x-canonical-resource":"account_user","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"user\": {\n    \"username\": \"jdoe\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"email\": \"johndoe@example.com\",\n    \"phone\": \"\",\n    \"signature\": null,\n    \"links\": {\n      \"lists\": \"https://:account.api-us1.com/api/3/users/1/lists\",\n      \"userGroup\": \"https://:account.api-us1.com/api/3/users/1/userGroup\",\n      \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/1/dealGroupTotals\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/1/dealGroupUsers\",\n      \"configs\": \"https://:account.api-us1.com/api/3/users/1/configs\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"username":{"type":"string","example":"jdoe"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/configs"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/users/username/{username}":{"get":{"summary":"Retrieve a user by username","description":"Retrieve an existing user by looking up their username","operationId":"get-user-username","x-canonical-resource":"account_user","parameters":[{"name":"username","in":"path","description":"Username of the user you want to view","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"user\": {\n    \"username\": \"admin\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"email\": \"johndoe@example.com\",\n    \"phone\": \"\",\n    \"signature\": null,\n    \"links\": {\n      \"lists\": \"https://:account.api-us1.com/api/3/users/1/lists\",\n      \"userGroup\": \"https://:account.api-us1.com/api/3/users/1/userGroup\",\n      \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/1/dealGroupTotals\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/1/dealGroupUsers\",\n      \"configs\": \"https://:account.api-us1.com/api/3/users/1/configs\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"username":{"type":"string","example":"admin"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/configs"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/users/{id}":{"get":{"summary":"Retrieve a user","description":"Retrieve an existing user","operationId":"get-user","x-canonical-resource":"account_user","parameters":[{"name":"id","in":"path","description":"ID of the user you want to view","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"user\": {\n    \"username\": \"admin\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"email\": \"johndoe@example.com\",\n    \"phone\": \"\",\n    \"signature\": null,\n    \"links\": {\n      \"lists\": \"https://:account.api-us1.com/api/3/users/1/lists\",\n      \"userGroup\": \"https://:account.api-us1.com/api/3/users/1/userGroup\",\n      \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/1/dealGroupTotals\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/1/dealGroupUsers\",\n      \"configs\": \"https://:account.api-us1.com/api/3/users/1/configs\"\n    },\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"username":{"type":"string","example":"admin"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/1/configs"}}},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"put":{"summary":"Update a user","description":"Update an existing user","operationId":"update-user","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the user","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"user":{"properties":{"username":{"type":"string","description":"Username. Username cannot be changed!"},"password":{"type":"string","description":"Password. Example: 'newpassword'"},"email":{"type":"string","description":"Email address of the user. Example: 'test@example.com'"},"firstName":{"type":"string","description":"First name of the user. Example: 'FirstName'"},"lastName":{"type":"string","description":"Last name of the user. Example: 'LastName'"},"group":{"type":"integer","description":"Assign to Groups","format":"int32"},"phone":{"type":"string"},"signature":{"type":"string"},"mfaEnabled":{"type":["boolean","integer"]},"roles":{"type":["string","null"],"description":"JSON-encoded array of role names."},"seats":{"type":"array","items":{"type":"integer"},"description":"Seat ids to assign."}},"required":[],"type":"object"}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"userGroups\": [\n    {\n      \"userid\": \"3\",\n      \"groupid\": \"3\",\n      \"links\": {\n        \"group\": \"https://:account.api-us1.com/api/3/userGroups/3/group\",\n        \"user\": \"https://:account.api-us1.com/api/3/userGroups/3/user\"\n      },\n      \"id\": \"3\",\n      \"group\": \"3\",\n      \"user\": \"3\"\n    }\n  ],\n  \"user\": {\n    \"username\": \"user\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"email\": \"johndoe@example.com\",\n    \"phone\": \"\",\n    \"signature\": \"\",\n    \"userGroup\": \"3\",\n    \"links\": {\n      \"lists\": \"https://:account.api-us1.com/api/3/users/3/lists\",\n      \"userGroup\": \"https://:account.api-us1.com/api/3/users/3/userGroup\",\n      \"dealGroupTotals\": \"https://:account.api-us1.com/api/3/users/3/dealGroupTotals\",\n      \"dealGroupUsers\": \"https://:account.api-us1.com/api/3/users/3/dealGroupUsers\",\n      \"configs\": \"https://:account.api-us1.com/api/3/users/3/configs\"\n    },\n    \"id\": \"3\"\n  }\n}"}},"schema":{"type":"object","properties":{"userGroups":{"type":"array","items":{"type":"object","properties":{"userid":{"type":"string","example":"3"},"groupid":{"type":"string","example":"3"},"links":{"type":"object","properties":{"group":{"type":"string","example":"https://:account.api-us1.com/api/3/userGroups/3/group"},"user":{"type":"string","example":"https://:account.api-us1.com/api/3/userGroups/3/user"}}},"id":{"type":"string","example":"3"},"group":{"type":"string","example":"3"},"user":{"type":"string","example":"3"}}}},"user":{"type":"object","properties":{"username":{"type":"string","example":"user"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"string","example":"johndoe@example.com"},"phone":{"type":"string","example":""},"signature":{"type":"string","example":""},"userGroup":{"type":"string","example":"3"},"links":{"type":"object","properties":{"lists":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/lists"},"userGroup":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/userGroup"},"dealGroupTotals":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/dealGroupTotals"},"dealGroupUsers":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/dealGroupUsers"},"configs":{"type":"string","example":"https://:account.api-us1.com/api/3/users/3/configs"}}},"id":{"type":"string","example":"3"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a user","description":"Delete an existing user","operationId":"delete-user","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"ID of the user you wish to delete","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/users/{id}/singleSignOn":{"post":{"summary":"Create a single sign-on token for a user","description":"Mint a short lived single sign-on token for a user, so an application can drop that user straight into the ActiveCampaign UI without asking them for their password. This is the v3 equivalent of the v1 `singlesignon` action, and the token it returns is produced by the same implementation.\n\nThe token is spent by sending the user to `https://{account}.activehosted.com/admin/main.php?_ssot={token}`, from the IP address the token was bound to. Spending a token does not consume it: it stays usable from that address until it expires.\n\nOnly a user in the **Admin** group may call this endpoint, and only for a user they may administer; anything else is a `403`, as is minting a token for the account's primary administrator. A user id that does not exist is a `404`.\n\nMinting a token replaces the token this application previously minted for the same user and IP address, and expired tokens are deleted. There is no endpoint that revokes a token: a token stops working when it expires, so keep `duration` as short as the application needs, exactly as in v1.","operationId":"create-a-single-sign-on-token","x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"Id of the user to mint the token for","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"singleSignOn":{"type":"object","properties":{"ipAddress":{"type":"string","description":"The IP address the token may be spent from. Pass the address of the browser the user will arrive from, or `__self` to bind the token to the address this request came from, which is then reported back in the response. A value that is neither a valid IP address nor `__self` is a `422`.","example":"__self"},"duration":{"type":"integer","format":"int32","description":"How long the token remains valid, in minutes, between 1 and 1440. Defaults to 15 minutes when omitted.","example":15}},"required":["ipAddress"],"additionalProperties":false}},"additionalProperties":false},"examples":{"Bind the token to the calling application":{"value":{"singleSignOn":{"ipAddress":"__self","duration":15}}},"Bind the token to the user's browser":{"value":{"singleSignOn":{"ipAddress":"203.0.113.42","duration":60}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Token bound to the calling application":{"value":"{\n    \"singleSignOn\": {\n        \"user\": \"1\",\n        \"token\": \"5f2b1c9d8e7a46b3c0d1e2f3a4b5c6d7\",\n        \"expires\": \"2026-08-13 17:15:00\",\n        \"ipAddress\": \"203.0.113.42\"\n    }\n}"}},"schema":{"type":"object","properties":{"singleSignOn":{"type":"object","properties":{"user":{"type":"string","description":"Id of the user the token signs in.","example":"1"},"token":{"type":"string","description":"The token, to be spent as `_ssot`.","example":"5f2b1c9d8e7a46b3c0d1e2f3a4b5c6d7"},"expires":{"type":"string","description":"When the token stops working, in the account's timezone.","example":"2026-08-13 17:15:00"},"ipAddress":{"type":"string","description":"The IP address the token is bound to. For `__self` this is the address the request came from, resolved by ActiveCampaign.","example":"203.0.113.42"}}}}}}}},"403":{"description":"403"},"404":{"description":"404"},"422":{"description":"422"}}}},"/vega/connect":{"post":{"summary":"Connect a Vega library","description":"Internal: backs the Vega connect form in the email editor. Sends the submitted credentials to Deep Data, which runs one real call against Vega to prove the token works and only then stores the connection and mirrors it into this account's connections. Re-posting for an external_id the account already has edits that connection instead of adding a second. The account is taken from the session, never from the body. Hosted checks the four fields first and answers 422 for every one that fails; anything after that is Deep Data's status and body, passed through unchanged. Refused with 403 unless the account is entitled to the Vega integration and the request comes from inside the platform: the app session without an API key, a request signed by Deep Data, or one marked as internal traffic.","operationId":"create-vega-connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["token","external_id","env","base_url"],"properties":{"token":{"description":"The Vega API key. Printable ASCII with no whitespace. Stored encrypted by Deep Data and never returned.","type":"string","example":"5f4dcc3b5aa765d61d8327deb882cf99"},"external_id":{"description":"The customer's Vega library domain, at most 255 characters. Selects this connection on the showcase endpoints.","type":"string","example":"library.example.org"},"env":{"description":"The Vega environment name, at most 64 characters. Clarivate's names, so any value is accepted here; one Vega does not route on fails the health check instead.","type":"string","example":"staging"},"base_url":{"description":"The Clarivate deployment the library lives on, as an absolute URL. Hosted only checks that it is a URL; Deep Data further restricts it to https hosts under clarivate.com.","type":"string","example":"https://api.example.clarivate.com"}},"type":"object"},"example":{"token":"5f4dcc3b5aa765d61d8327deb882cf99","external_id":"library.example.org","env":"staging","base_url":"https://api.example.clarivate.com"}}}},"responses":{"201":{"description":"Vega accepted the credentials and Deep Data stored the connection (created, or edited when the account already has one for this external_id). Deep Data's body and status, passed through.","content":{"application/json":{"schema":{"properties":{"data":{"properties":{"type":{"description":"Always \"connection\"","type":"string","example":"connection"},"id":{"description":"Deep Data's composite key of the stored connection, account|service|external_id. Not the Hosted connection id.","type":"string","example":"acme.activehosted.com|vega|library.example.org"},"attributes":{"properties":{"account":{"description":"The account's hostname","type":"string","example":"acme.activehosted.com"},"service":{"description":"Always \"vega\"","type":"string","example":"vega"},"external_id":{"description":"The Vega library domain; pass it as external_id to the showcase endpoints","type":"string","example":"library.example.org"}},"type":"object"}},"type":"object"}},"type":"object"},"example":{"data":{"type":"connection","id":"acme.activehosted.com|vega|library.example.org","attributes":{"account":"acme.activehosted.com","service":"vega","external_id":"library.example.org"}}}}}},"400":{"description":"The body is not a JSON object. Deep Data is not called.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error object, not an array.","properties":{"type":{"description":"Always \"invalid_request\"","type":"string","example":"invalid_request"},"status":{"description":"HTTP status code as a string","type":"string","example":"400"},"title":{"description":"Always \"Bad Request\"","type":"string","example":"Bad Request"},"detail":{"description":"Always \"Request body must be a JSON object.\"","type":"string","example":"Request body must be a JSON object."}},"type":"object"}},"type":"object"},"example":{"errors":{"type":"invalid_request","status":"400","title":"Bad Request","detail":"Request body must be a JSON object."}}}}},"403":{"description":"The account is not entitled to the Vega integration (feature flag off and not an entitled reseller), or the request is not internal: an API-key request from outside the platform is always refused.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"422":{"description":"A field failed validation here, before Deep Data was called; every failing field is reported at once. The same status also comes back from Deep Data, passed through, with errors.code \"vega.invalid_request\" and its own per-field messages in errors.meta.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error object, not an array.","properties":{"type":{"description":"\"validation_error\" when Hosted refused the fields; \"general_error\" when Deep Data did","type":"string","example":"validation_error"},"status":{"description":"HTTP status code as a string","type":"string","example":"422"},"code":{"description":"Present only on a Deep Data refusal: \"vega.invalid_request\"","type":"string","example":"vega.invalid_request"},"title":{"description":"Short name of the HTTP status","type":"string","example":"Unprocessable Entity"},"detail":{"description":"Human-readable summary; not for branching on","type":"string","example":"One or more fields are invalid."},"meta":{"description":"From Hosted: fields, a map of field name to the translation key of its error, ending in error-required or error-validation. From Deep Data: its per-field messages.","type":"object","example":{"fields":{"token":"integrations:vega:input:token:error-required"}}}},"type":"object"}},"type":"object"},"example":{"errors":{"type":"validation_error","status":"422","title":"Unprocessable Entity","detail":"One or more fields are invalid.","meta":{"fields":{"base_url":"integrations:vega:input:base_url:error-validation"}}}}}}},"429":{"description":"Passed through from Deep Data: Vega throttled the request (errors.code \"vega.rate_limited\"). The delay is in errors.meta.retry_after; the Retry-After header Deep Data sends is not forwarded."},"500":{"description":"Passed through from Deep Data (errors.code \"vega.internal_error\"), or Hosted could not reach Deep Data at all, in which case the body is {\"message\": \"Something went wrong on our end. Please try again later\"}."},"502":{"description":"Passed through from Deep Data: Vega failed or answered something unusable. errors.code says whether a retry can help: \"vega.upstream_error\" and \"vega.network\" can, \"vega.auth_rejected\", \"vega.invalid_response\" and \"vega.bad_request\" cannot."},"504":{"description":"Passed through from Deep Data: Vega did not answer in time (errors.code \"vega.timeout\"). Safe to retry."}},"x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/vega/connect/{id}":{"put":{"summary":"Update a Vega connection","description":"Internal: backs the Vega edit form in the email editor. {id} must be a Vega connection of this account, or the answer is 404; it is only checked, not sent on. The update is the same Deep Data call as POST /vega/connect, an upsert keyed by the account and external_id, so the connection that changes is the one whose external_id is in the body. token is optional here: absent or empty keeps the stored key. Hosted checks the fields first and answers 422 for every one that fails; anything after that is Deep Data's status and body, passed through unchanged, which is 201 on success. Refused with 403 unless the account is entitled to the Vega integration and the request comes from inside the platform.","operationId":"update-vega-connection","parameters":[{"name":"id","in":"path","description":"Hosted ID of the Vega connection being edited","required":true,"schema":{"type":"string","pattern":"^(?:\\d+)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["external_id","env","base_url"],"properties":{"token":{"description":"A new Vega API key, printable ASCII with no whitespace. Leave it out or send an empty string to keep the stored key.","type":"string","example":"5f4dcc3b5aa765d61d8327deb882cf99"},"external_id":{"description":"The Vega library domain, at most 255 characters. Deep Data finds the connection to edit by this value.","type":"string","example":"library.example.org"},"env":{"description":"The Vega environment name, at most 64 characters","type":"string","example":"production"},"base_url":{"description":"The Clarivate deployment the library lives on, as an absolute URL","type":"string","example":"https://api.example.clarivate.com"}},"type":"object"},"example":{"external_id":"library.example.org","env":"production","base_url":"https://api.example.clarivate.com"}}}},"responses":{"201":{"description":"The edit is stored. Deep Data answers 201 for an edit too; its body and status are passed through.","content":{"application/json":{"schema":{"properties":{"data":{"properties":{"type":{"description":"Always \"connection\"","type":"string","example":"connection"},"id":{"description":"Deep Data's composite key of the stored connection, account|service|external_id. Not the Hosted connection id.","type":"string","example":"acme.activehosted.com|vega|library.example.org"},"attributes":{"properties":{"account":{"description":"The account's hostname","type":"string","example":"acme.activehosted.com"},"service":{"description":"Always \"vega\"","type":"string","example":"vega"},"external_id":{"description":"The Vega library domain; pass it as external_id to the showcase endpoints","type":"string","example":"library.example.org"}},"type":"object"}},"type":"object"}},"type":"object"},"example":{"data":{"type":"connection","id":"acme.activehosted.com|vega|library.example.org","attributes":{"account":"acme.activehosted.com","service":"vega","external_id":"library.example.org"}}}}}},"400":{"description":"The body is not a JSON object. Deep Data is not called.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error object, not an array.","properties":{"type":{"description":"Always \"invalid_request\"","type":"string","example":"invalid_request"},"status":{"description":"HTTP status code as a string","type":"string","example":"400"},"title":{"description":"Always \"Bad Request\"","type":"string","example":"Bad Request"},"detail":{"description":"Always \"Request body must be a JSON object.\"","type":"string","example":"Request body must be a JSON object."}},"type":"object"}},"type":"object"},"example":{"errors":{"type":"invalid_request","status":"400","title":"Bad Request","detail":"Request body must be a JSON object."}}}}},"403":{"description":"The account is not entitled to the Vega integration (feature flag off and not an entitled reseller), or the request is not internal: an API-key request from outside the platform is always refused.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"The account has no connection with this id, or it is not a Vega connection. Checked before the body is read.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"404"},"detail":{"description":"Always \"Connection not found\"","type":"string","example":"Connection not found"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"404","detail":"Connection not found"}]}}}},"422":{"description":"A field failed validation here, before Deep Data was called; every failing field is reported at once. The same status also comes back from Deep Data, passed through, with errors.code \"vega.invalid_request\" and its own per-field messages in errors.meta.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"One error object, not an array.","properties":{"type":{"description":"\"validation_error\" when Hosted refused the fields; \"general_error\" when Deep Data did","type":"string","example":"validation_error"},"status":{"description":"HTTP status code as a string","type":"string","example":"422"},"code":{"description":"Present only on a Deep Data refusal: \"vega.invalid_request\"","type":"string","example":"vega.invalid_request"},"title":{"description":"Short name of the HTTP status","type":"string","example":"Unprocessable Entity"},"detail":{"description":"Human-readable summary; not for branching on","type":"string","example":"One or more fields are invalid."},"meta":{"description":"From Hosted: fields, a map of field name to the translation key of its error, ending in error-required or error-validation. From Deep Data: its per-field messages.","type":"object","example":{"fields":{"token":"integrations:vega:input:token:error-required"}}}},"type":"object"}},"type":"object"},"example":{"errors":{"type":"validation_error","status":"422","title":"Unprocessable Entity","detail":"One or more fields are invalid.","meta":{"fields":{"base_url":"integrations:vega:input:base_url:error-validation"}}}}}}},"429":{"description":"Passed through from Deep Data: Vega throttled the request (errors.code \"vega.rate_limited\"). The delay is in errors.meta.retry_after; the Retry-After header Deep Data sends is not forwarded."},"500":{"description":"Passed through from Deep Data (errors.code \"vega.internal_error\"), or Hosted could not reach Deep Data at all, in which case the body is {\"message\": \"Something went wrong on our end. Please try again later\"}."},"502":{"description":"Passed through from Deep Data: Vega failed or answered something unusable. errors.code says whether a retry can help: \"vega.upstream_error\" and \"vega.network\" can, \"vega.auth_rejected\", \"vega.invalid_response\" and \"vega.bad_request\" cannot."},"504":{"description":"Passed through from Deep Data: Vega did not answer in time (errors.code \"vega.timeout\"). Safe to retry."}},"x-canonical-resource":"connections","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/vega/showcases":{"get":{"summary":"List the showcases of a Vega connection","description":"Internal: backs the Vega showcase picker in the email editor. Deep Data looks up the connection named by external_id and lists the published showcases in that Vega library. Hosted only checks that external_id is present; Deep Data's status and body are passed through unchanged, so a missing connection (404, errors.code \"vega.connection_missing\") can be told apart from an empty list. Refused with 403 unless the account is entitled to the Vega integration and the request comes from inside the platform.","operationId":"list-vega-showcases","parameters":[{"name":"external_id","in":"query","description":"The Vega library domain that selects which of the account's Vega connections to read, as returned in data.attributes.external_id by POST /vega/connect. Missing or empty is a 422 from Hosted; a value that names no connection is a 404 from Deep Data.","required":true,"schema":{"type":"string"},"example":"library.example.org"}],"responses":{"200":{"description":"The published showcases; an empty array when the library has none","content":{"application/json":{"schema":{"properties":{"showcases":{"type":"array","items":{"properties":{"id":{"description":"Showcase id; pass it as showcaseId to GET /vega/showcases/{showcaseId}/items","type":"string","example":"sc_9f2a1b"},"name":{"description":"Display name, as Vega holds it","type":"string","example":"New arrivals - September"},"url":{"description":"Link to the showcase in the customer's Vega library","type":"string","example":"https://library.example.org/library-list/showcase/sc_9f2a1b"}},"type":"object"}}},"type":"object"},"example":{"showcases":[{"id":"sc_9f2a1b","name":"New arrivals - September","url":"https://library.example.org/library-list/showcase/sc_9f2a1b"}]}}}},"403":{"description":"The account is not entitled to the Vega integration (feature flag off and not an entitled reseller), or the request is not internal: an API-key request from outside the platform is always refused.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"Passed through from Deep Data: the account has no Vega connection with this external_id (errors.code \"vega.connection_missing\")."},"422":{"description":"Refused by Hosted before Deep Data is called: external_id is missing or empty. Deep Data can also answer 422 (errors.code \"vega.invalid_request\"), passed through with its own envelope.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What was wrong with the query string. Only on a refusal by Hosted; a Deep Data refusal has an errors object instead.","type":"string","example":"Invalid or missing required parameter: external_id"}},"type":"object"},"example":{"error":"Invalid or missing required parameter: external_id"}}}},"429":{"description":"Passed through from Deep Data: Vega throttled the request (errors.code \"vega.rate_limited\"). The delay is in errors.meta.retry_after; the Retry-After header Deep Data sends is not forwarded."},"500":{"description":"Passed through from Deep Data (errors.code \"vega.internal_error\"), or Hosted could not reach Deep Data at all, in which case the body is {\"message\": \"Something went wrong on our end. Please try again later\"}."},"502":{"description":"Passed through from Deep Data: Vega failed or answered something unusable. errors.code says whether a retry can help: \"vega.upstream_error\" and \"vega.network\" can, \"vega.auth_rejected\", \"vega.invalid_response\" and \"vega.bad_request\" cannot."},"504":{"description":"Passed through from Deep Data: Vega did not answer in time (errors.code \"vega.timeout\"). Safe to retry."}},"x-canonical-resource":"connections","x-internal":true}},"/vega/showcases/{showcaseId}/items":{"get":{"summary":"List the items of a Vega showcase","description":"Internal: backs the Vega showcase block in the email editor. Deep Data reads one showcase from the Vega library named by external_id and returns its items with every field as a string; a field Vega leaves out arrives as an empty string. Hosted checks external_id and page_size; Deep Data's status and body are passed through unchanged. Refused with 403 unless the account is entitled to the Vega integration and the request comes from inside the platform.","operationId":"list-vega-showcase-items","parameters":[{"name":"showcaseId","in":"path","description":"Showcase id, as returned in showcases[].id by GET /vega/showcases. Letters, digits, underscore and hyphen, 1 to 64 characters.","required":true,"schema":{"type":"string","pattern":"^(?:[A-Za-z0-9_-]{1,64})$"}},{"name":"external_id","in":"query","description":"The Vega library domain that selects which of the account's Vega connections to read, as returned in data.attributes.external_id by POST /vega/connect. Missing or empty is a 422 from Hosted; a value that names no connection is a 404 from Deep Data.","required":true,"schema":{"type":"string"},"example":"library.example.org"},{"name":"page_size","in":"query","description":"Number of items to return. Digits only, otherwise 422; left out, Deep Data uses its configured default.","required":false,"schema":{"type":"integer"},"example":5}],"responses":{"200":{"description":"The showcase and its items","content":{"application/json":{"schema":{"properties":{"id":{"description":"The showcaseId from the path","type":"string","example":"sc_9f2a1b"},"name":{"description":"Display name; empty when Vega sends none","type":"string","example":"New arrivals - September"},"url":{"description":"Link to the showcase in the customer's Vega library","type":"string","example":"https://library.example.org/library-list/showcase/sc_9f2a1b"},"items":{"description":"The showcase's items; empty when it has none","type":"array","items":{"properties":{"id":{"description":"Vega item id","type":"string","example":"bib_12345"},"title":{"description":"Title of the item","type":"string","example":"The Left Hand of Darkness"},"author":{"description":"Author of the item","type":"string","example":"Ursula K. Le Guin"},"entity_type":{"description":"Vega's classification of the item, passed through unvalidated","type":"string","example":"BIB"},"cover_url":{"description":"Cover image URLs; a size Vega does not supply is an empty string","properties":{"small":{"description":"Small cover image URL","type":"string","example":"https://covers.example.org/12345-s.jpg"},"medium":{"description":"Medium cover image URL","type":"string","example":"https://covers.example.org/12345-m.jpg"},"large":{"description":"Large cover image URL","type":"string","example":"https://covers.example.org/12345-l.jpg"}},"type":"object"},"url":{"description":"Link to the item's card in the customer's Vega library","type":"string","example":"https://library.example.org/search/card?id=bib_12345&entityType=FormatGroup"}},"type":"object"}}},"type":"object"}}}},"403":{"description":"The account is not entitled to the Vega integration (feature flag off and not an entitled reseller), or the request is not internal: an API-key request from outside the platform is always refused.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"Always exactly one error.","type":"array","items":{"properties":{"status":{"description":"HTTP status code as a string","type":"string","example":"403"},"detail":{"description":"Always \"Forbidden\"","type":"string","example":"Forbidden"}},"type":"object"}}},"type":"object"},"example":{"errors":[{"status":"403","detail":"Forbidden"}]}}}},"404":{"description":"Passed through from Deep Data: the account has no Vega connection with this external_id (errors.code \"vega.connection_missing\"), or the showcase no longer exists in Vega (\"vega.showcase_not_found\")."},"422":{"description":"Refused by Hosted before Deep Data is called: external_id is missing or empty, or page_size is not all digits (\"Invalid parameter: page_size\"). Deep Data can also answer 422 (errors.code \"vega.invalid_request\"), passed through with its own envelope.","content":{"application/json":{"schema":{"properties":{"error":{"description":"What was wrong with the query string. Only on a refusal by Hosted; a Deep Data refusal has an errors object instead.","type":"string","example":"Invalid or missing required parameter: external_id"}},"type":"object"},"example":{"error":"Invalid or missing required parameter: external_id"}}}},"429":{"description":"Passed through from Deep Data: Vega throttled the request (errors.code \"vega.rate_limited\"). The delay is in errors.meta.retry_after; the Retry-After header Deep Data sends is not forwarded."},"500":{"description":"Passed through from Deep Data (errors.code \"vega.internal_error\"), or Hosted could not reach Deep Data at all, in which case the body is {\"message\": \"Something went wrong on our end. Please try again later\"}."},"502":{"description":"Passed through from Deep Data: Vega failed or answered something unusable. errors.code says whether a retry can help: \"vega.upstream_error\" and \"vega.network\" can, \"vega.auth_rejected\", \"vega.invalid_response\" and \"vega.bad_request\" cannot."},"504":{"description":"Passed through from Deep Data: Vega did not answer in time (errors.code \"vega.timeout\"). Safe to retry."}},"x-canonical-resource":"connections","x-internal":true}},"/webhook/events":{"get":{"summary":"List all webhook events","description":"List all available webhook events","operationId":"get-a-list-of-webhook-events","x-canonical-resource":"webhook_event_type","responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"webhookEvents\": [\n    \"bounce\",\n    \"click\",\n    \"contact_tag_added\",\n    \"contact_tag_removed\",\n    \"deal_add\",\n    \"deal_note_add\",\n    \"deal_pipeline_add\",\n    \"deal_stage_add\",\n    \"deal_task_add\",\n    \"deal_task_complete\",\n    \"deal_tasktype_add\",\n    \"deal_update\",\n    \"forward\",\n    \"list_add\",\n    \"open\",\n    \"reply\",\n    \"sent\",\n    \"share\",\n    \"sms_reply\",\n    \"sms_sent\",\n    \"sms_unsub\",\n    \"subscribe\",\n    \"subscriber_note\",\n    \"unsubscribe\",\n    \"update\"\n  ],\n  \"meta\": {\n    \"total\": 25\n  }\n}"}},"schema":{"type":"object","properties":{"webhookEvents":{"type":"array","items":{"type":"string","example":"bounce"}},"meta":{"type":"object","properties":{"total":{"type":"integer","example":25,"default":0}}}}}}}}},"deprecated":false}},"/webhookTest":{"post":{"summary":"Send sample webhook payloads to a URL","description":"Sends the sample payload of each requested webhook event type to `url`, as a webhook of that type is delivered: an HTTP POST with a form-encoded (`application/x-www-form-urlencoded`) body. The payloads are fixed sample data, not data of the account. The sends are made one after another from ActiveCampaign's servers, redirects are followed, and the response reports per type what the URL answered. No webhook is created or changed. Internal: a test tool for webhook endpoints.","operationId":"send-sample-webhook-payloads","requestBody":{"required":true,"content":{"application/json":{"schema":{"required":["url","types"],"properties":{"url":{"description":"The URL to send the samples to. It is not validated before the sends.","type":"string","example":"https://example.com/hooks/activecampaign"},"types":{"description":"Webhook event types to send a sample of, such as `subscribe`, `contact_tag_added` or `deal_add`. A type with no sample data is not refused: it is reported with `responseCode` 0 and a message listing the valid types.","type":"array","items":{"type":"string"},"minItems":1,"example":["subscribe","deal_add"]}},"type":"object"}}}},"responses":{"200":{"description":"One entry per requested type, keyed by the type. Sent also when every send failed.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/WebhookSampleSendResult"}},"example":{"subscribe":{"responseCode":200,"responseBody":"OK"},"deal_add":{"responseCode":404,"responseBody":"Not Found"}}}}},"400":{"description":"`url` is missing or empty, or `types` is missing, empty or not an array. A body that is not JSON is answered the same as a missing `url`. Nothing was sent. Unlike most errors of the API, `errors` is a single string.","content":{"application/json":{"schema":{"properties":{"errors":{"description":"What is wrong with the body. For `types`, it lists the valid types.","type":"string"}},"type":"object"},"example":{"errors":"`url` is required"}}}}},"x-canonical-resource":"webhooks","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/webhooks":{"post":{"summary":"Create a webhook","description":"Create a new webhook","operationId":"create-webhook","x-canonical-resource":"webhooks","x-destructive":false,"x-bulk-operation":false,"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"properties":{"name":{"type":"string","description":"A name (or label) to give this webhook."},"url":{"type":"string","description":"The URL where the webhook will send the POST request when the event occurs. Note that for https endpoints, we only can send webhooks on port 443, the default https port."},"events":{"type":"array","description":"The [event(s)](#section-events) that will trigger the webhook to fire.","items":{"type":"string"}},"sources":{"type":"array","description":"The [source(s)](#section-sources) causing an event to occur.","items":{"type":"string"}},"listid":{"type":"integer","description":"The id of a list associated with an event. If set, only events happening on this list id will trigger the webhook. This parameter has no effect on the following webhook events:     \"subscriber_note\",    \"contact_tag_added\",    \"contact_tag_removed\",    \"contact_task_add\",    \"list_add\",    \"sms_sent\",    \"sms_reply\",    \"sms_unsub\",    \"deal_add\",    \"deal_update\",    \"deal_note_add\",    \"deal_pipeline_add\",    \"deal_stage_add\",    \"deal_task_add\",    \"deal_tasktype_add\",    \"deal_task_complete\",    \"account_add\",    \"account_update\",    \"account_contact_add\",    \"account_contact_update\",","format":"int32"},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"description":"Header name; required and unique within the webhook."},"value":{"type":"string","description":"Header value; required."},"is_signature":{"type":"boolean","description":"true marks this header as the signature header. At most one per webhook; its value is blanked in responses."}}},"description":"Replaces the webhook's headers: existing headers whose name is not listed are deleted."}},"required":["name","url","events","sources"],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"JSON":{"value":{"webhook":{"name":"My Hook","url":"http://example.com/my-hook","events":["subscribe","unsubscribe","sent"],"sources":["public","system"]}}}}}}},"responses":{"201":{"description":"201","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"webhook\": {\n    \"cdate\": \"2016-01-01T12:00:00-00:00\",\n    \"listid\": \"0\",\n    \"name\": \"My Hook\",\n    \"url\": \"http://example.com/my-hook\",\n    \"events\": [\n      \"subscribe\",\n      \"unsubscribe\",\n      \"sent\"\n    ],\n    \"sources\": [\n      \"public\",\n      \"system\"\n    ],\n    \"links\": [],\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"cdate":{"type":"string","example":"2016-01-01T12:00:00-00:00"},"listid":{"type":"string","example":"0"},"name":{"type":"string","example":"My Hook"},"url":{"type":"string","example":"http://example.com/my-hook"},"events":{"type":"array","items":{"type":"string","example":"subscribe"}},"sources":{"type":"array","items":{"type":"string","example":"public"}},"links":{"type":"array"},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"get":{"summary":"List all webhooks","description":"List all existing webhooks","operationId":"get-a-list-of-webhooks","x-canonical-resource":"webhooks","parameters":[{"name":"filters[name]","in":"query","description":"Filter by webhook name","schema":{"type":"string"}},{"name":"filters[url]","in":"query","description":"Filter by webhook url","schema":{"type":"string"}},{"name":"filters[listid]","in":"query","description":"Filter by webhook's associated list","schema":{"type":"string"}}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"webhooks\": [\n    {\n      \"cdate\": \"2016-01-01T12:00:00-00:00\",\n      \"listid\": \"0\",\n      \"name\": \"My Hook\",\n      \"url\": \"http://example.com/my-hook\",\n      \"events\": [\n        \"subscribe\",\n        \"unsubscribe\",\n        \"sent\"\n      ],\n      \"sources\": [\n        \"public\",\n        \"system\"\n      ],\n      \"links\": [],\n      \"id\": \"1\"\n    },\n    {\n      \"cdate\": \"2016-01-01T12:00:00-00:00\",\n      \"listid\": \"0\",\n      \"name\": \"My Hook 2\",\n      \"url\": \"http://example.com/my-hook-2\",\n      \"events\": [\n        \"subscribe\"\n      ],\n      \"sources\": [\n        \"admin\"\n      ],\n      \"links\": [],\n      \"id\": \"2\"\n    }\n  ],\n  \"meta\": {\n    \"total\": \"2\"\n  }\n}"}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/webhooks/{id}":{"get":{"summary":"Retrieve a webhook","description":"Retrieve an existing webhook","operationId":"get-webhook","x-canonical-resource":"webhooks","parameters":[{"name":"id","in":"path","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"webhook\": {\n    \"cdate\": \"2016-01-01T12:00:00-00:00\",\n    \"listid\": \"0\",\n    \"name\": \"My hook\",\n    \"url\": \"http://example.com/my-hook\",\n    \"events\": [\n      \"subscribe\",\n      \"unsubscribe\",\n      \"sent\"\n    ],\n    \"sources\": [\n      \"admin\",\n      \"api\",\n      \"system\"\n    ],\n    \"links\": [],\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"cdate":{"type":"string","example":"2016-01-01T12:00:00-00:00"},"listid":{"type":"string","example":"0"},"name":{"type":"string","example":"My hook"},"url":{"type":"string","example":"http://example.com/my-hook"},"events":{"type":"array","items":{"type":"string","example":"subscribe"}},"sources":{"type":"array","items":{"type":"string","example":"admin"}},"links":{"type":"array"},"id":{"type":"string","example":"1"}}}}}}}}},"deprecated":false},"put":{"summary":"Update a webhook","description":"Update an existing webhook","operationId":"update-webhook","x-canonical-resource":"webhooks","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The webhook id","schema":{"type":"integer","format":"int32"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"properties":{"name":{"type":"string","description":"A name (or label) to give the webhook."},"url":{"type":"string","description":"The URL where the webhook will send the POST request when the event occurs."},"events":{"type":"array","description":"The [event(s)](#section-events) that will trigger the webhook to fire.","items":{"type":"string"}},"sources":{"type":"array","description":"The [source(s)](#section-sources) causing an event to occur.","items":{"type":"string"}},"listid":{"type":"integer","description":"The id of a list associated with an event (required for some events).","format":"int32"},"state":{"type":"integer","description":"1 means the webhook fires; any other value stops it firing."},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"description":"Header name; required and unique within the webhook."},"value":{"type":"string","description":"Header value. May be empty only for the signature header when the webhook already has one, which keeps the stored value."},"is_signature":{"type":"boolean","description":"true marks this header as the signature header. At most one per webhook; its value is blanked in responses."}}},"description":"Replaces the webhook's headers: existing headers whose name is not listed are deleted."}},"required":[],"type":"object","additionalProperties":false}},"additionalProperties":false},"examples":{"Request Example":{"value":{"webhook":{"name":"My Hook","url":"http://example.com/my-hook","events":["subscribe","unsubscribe","sent"],"sources":["public","system"]}}}}}}},"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{\n  \"webhook\": {\n    \"cdate\": \"2016-01-01T12:00:00-00:00\",\n    \"listid\": \"0\",\n    \"name\": \"My Hook\",\n    \"url\": \"http://example.com/my-hook\",\n    \"events\": [\n      \"subscribe\",\n      \"unsubscribe\",\n      \"sent\"\n    ],\n    \"sources\": [\n      \"public\",\n      \"system\"\n    ],\n    \"links\": [],\n    \"id\": \"1\"\n  }\n}"}},"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"cdate":{"type":"string","example":"2016-01-01T12:00:00-00:00"},"listid":{"type":"string","example":"0"},"name":{"type":"string","example":"My Hook"},"url":{"type":"string","example":"http://example.com/my-hook"},"events":{"type":"array","items":{"type":"string","example":"subscribe"}},"sources":{"type":"array","items":{"type":"string","example":"public"}},"links":{"type":"array"},"id":{"type":"string","example":"1"}}}}}}}},"400":{"description":"400","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false},"delete":{"summary":"Delete a webhook","description":"Delete an existing webhook","operationId":"delete-webhook","x-canonical-resource":"webhooks","x-destructive":true,"x-bulk-operation":false,"parameters":[{"name":"id","in":"path","description":"The webhook id","schema":{"type":"integer","format":"int32"},"required":true}],"responses":{"200":{"description":"200","content":{"application/json":{"examples":{"Result":{"value":"{}"}},"schema":{"type":"object","properties":{}}}}}},"deprecated":false}},"/whatsapp/config":{"post":{"summary":"Store the WhatsApp service API key on the account","description":"Saves the token as the account setting whatsapp.token, replacing any value already there. Nothing Hosted runs today reads that setting: its WhatsApp service client authenticates with a signed JWT, or in local development with a token from the environment. Internal: a development and debugging aid.","operationId":"save-a-whatsapp-service-token","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappServiceTokenRequest"}}}},"responses":{"200":{"description":"Saved. The body is the text Token saved, not JSON.","content":{"text/html":{"schema":{"type":"string","example":"Token saved"}}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"422":{"description":"token is not a JSON string. Each error has detail Unexpected type.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Unexpected type"}]}}}},"500":{"description":"token is missing.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"activecampaign_account","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/whatsapp/connected-experience/contact/bulk-sync":{"post":{"summary":"Queue a push of every contact to the WhatsApp service through an Integration Layer connection","description":"Queues a background job and answers without waiting for it. The job walks every contact with a phone number and queues one POST /whatsapp/connected-experience/contact/sync for each, through the given connection. Also records the current Unix time as the account setting whatsapp.connected_experience.last_bulk_sync. Internal: the backfill trigger for a WhatsApp connection made through the Integration Layer.","operationId":"bulk-sync-contacts-to-a-whatsapp-connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappConnectionBulkSyncRequest"}}}},"responses":{"200":{"description":"The job was queued. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"422":{"description":"connection_id is missing or blank (This value should not be blank.), or is not a JSON string (Unexpected type).","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/connectionId"}}]}}}},"500":{"description":"The job could not be queued.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/whatsapp/connected-experience/contact/sync":{"post":{"summary":"Push a contact to the WhatsApp service through an Integration Layer connection","description":"Creates or updates the contact in the WhatsApp service as POST /whatsapp/contact/sync does, but sends the request through the given Integration Layer connection, then adds the tag hilos-whatsapp-integration to the contact. A contact with no phone number is not pushed but is still tagged. Internal: queued once per contact by the job POST /whatsapp/connected-experience/contact/bulk-sync starts.","operationId":"sync-a-contact-to-a-whatsapp-connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappConnectionContactSyncRequest"}}}},"responses":{"200":{"description":"Handled. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"404":{"description":"No contact with this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing contact.","type":"string","example":"No Result found for Subscriber with id 42"}},"type":"object"}}}},"422":{"description":"contact_id or connection_id is missing or blank (This value should not be blank.), or has the wrong JSON type (Unexpected type).","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"This value should not be blank.","source":{"pointer":"/data/attributes/connectionId"}}]}}}},"500":{"description":"The WhatsApp service or the Integration Layer could not be reached or answered with a server error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/whatsapp/contact/bulk-delete":{"post":{"summary":"Queue the WhatsApp contact clean-up job","description":"Meant to queue the clean-up that removes every contact from the WhatsApp service, but it queues the same job as POST /whatsapp/contact/bulk-sync: a push of every contact with a phone number to the WhatsApp service. Nothing is deleted. Answers without waiting for the job; the request body is not read. Internal: a development and debugging trigger.","operationId":"bulk-delete-whatsapp-contacts","responses":{"200":{"description":"The job was queued. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"500":{"description":"The job could not be queued.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/whatsapp/contact/bulk-sync":{"post":{"summary":"Queue a push of every contact to the WhatsApp service","description":"Queues a background job and answers without waiting for it. The job walks every contact with a phone number and queues one POST /whatsapp/contact/sync for each, which creates or updates the contact in the WhatsApp service. The request body is not read. Internal: a manual backfill trigger for the WhatsApp integration.","operationId":"bulk-sync-contacts-to-whatsapp","responses":{"200":{"description":"The job was queued. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"500":{"description":"The job could not be queued.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/whatsapp/contact/delete":{"post":{"summary":"Remove a contact from the WhatsApp service","description":"Deletes the contact the WhatsApp service knows by this ID and drops the record Hosted keeps of the link. An ID Hosted has no record of is ignored and still answers 200. Internal: Hosted queues this call to itself through the queued HTTP service after a contact linked to the WhatsApp service is deleted.","operationId":"delete-a-whatsapp-contact","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappContactDeleteRequest"}}}},"responses":{"200":{"description":"Handled, including when no contact is linked to this ID. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"422":{"description":"contact_external_id is not a JSON string. Each error has detail Unexpected type.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Unexpected type"}]}}}},"500":{"description":"contact_external_id is missing, or the WhatsApp service refused or failed the deletion.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/whatsapp/contact/sync":{"post":{"summary":"Push a contact to the WhatsApp service","description":"Creates the contact in the WhatsApp service, or updates it there when Hosted already holds its WhatsApp ID and its phone, email, name, tags or custom field values changed since the last push. A contact with no phone number is skipped. A 4xx answer from the WhatsApp service is logged and not reported to the caller. Internal: Hosted queues this call to itself through the queued HTTP service when a contact or its tags change on an account with the WhatsApp inbox, and once per contact during a bulk sync.","operationId":"sync-a-contact-to-whatsapp","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappContactSyncRequest"}}}},"responses":{"200":{"description":"Handled, including when the contact was skipped for having no phone number. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"400":{"description":"The body is empty or is not a JSON object.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":"400","detail":"Request body is empty."}]}}}},"404":{"description":"No contact with this ID.","content":{"application/json":{"schema":{"properties":{"message":{"description":"Names the missing contact.","type":"string","example":"No Result found for Subscriber with id 42"}},"type":"object"}}}},"422":{"description":"contact_id is not a JSON integer. Each error has detail Unexpected type.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Unexpected type"}]}}}},"500":{"description":"contact_id is missing, or the WhatsApp service could not be reached or answered with a server error.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"contact","x-destructive":true,"x-bulk-operation":false,"x-internal":true}},"/whatsapp/flowEvents":{"post":{"summary":"Record a completed WhatsApp flow execution","description":"Webhook the WhatsApp service calls about a flow execution. A COMPLETED execution of a flow for an existing contact is published to SNS as a whatsapp_flow_event record carrying the flow ID, the status, when the execution was created and the contact; any other status is refused. Internal: called by the WhatsApp service, not by customers.","operationId":"create-a-whatsapp-flow-event","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappFlowEventRequest"}}}},"responses":{"200":{"description":"Published. The body is empty."},"400":{"description":"The body is empty or is not a JSON object, or event_data has no flow.id or contact.ac_id, or its status is not COMPLETED. For the event_data checks, errors[0].detail names the first that failed: The flow ID must be present, The contact ID must be present, or Only accepting COMPLETED events currently.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":400,"detail":"Only accepting COMPLETED events currently"}]}}}},"404":{"description":"No contact has the ID in contact.ac_id.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":404,"detail":"Contact not found for this ID"}]}}}},"422":{"description":"A field has the wrong JSON type. Each error has detail Unexpected type.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"status":422,"title":"Invalid attribute","detail":"Unexpected type"}]}}}},"500":{"description":"event_data.id, event_data.status or event_data.created_on is missing, or the event could not be published.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"whatsapp_flow","x-destructive":false,"x-bulk-operation":false,"x-internal":true}},"/whatsapp/user/sync":{"post":{"summary":"Push every user to the WhatsApp service","description":"Marks every user the WhatsApp service holds for the account inactive, then pushes each Hosted user to it with ID, email, first and last name and active set: an update when the service already has the user, a create when it answers 404. Runs within the request, one call per user. The request body is not read. Internal: a resync trigger for the WhatsApp integration.","operationId":"sync-users-to-whatsapp","responses":{"200":{"description":"Every user was pushed. The body is the JSON string ok.","content":{"application/json":{"schema":{"type":"string"},"example":"ok"}}},"500":{"description":"The WhatsApp service could not be reached, or answered an error other than 404 for a user. Users before that one were already pushed.","content":{"application/json":{"schema":{"properties":{"message":{"description":"A fixed message.","type":"string","example":"Something went wrong on our end. Please try again later"}},"type":"object"}}}}},"x-canonical-resource":"account_user","x-destructive":true,"x-bulk-operation":true,"x-internal":true}},"/whatsappPrimaryInbox/{id}":{"get":{"summary":"Retrieve a contact's primary WhatsApp inbox","description":"The contact's inbox entry on its default channel in the WhatsApp service, with the number of unseen messages and app links to open the inbox and the last conversation. Read live from the WhatsApp service for a contact Hosted has pushed there. Internal: part of the WhatsApp contact activities and inbox linking feature.","operationId":"retrieve-a-whatsapp-primary-inbox","parameters":[{"name":"id","in":"path","description":"ID of the contact.","required":true,"schema":{"type":"integer"},"example":42}],"responses":{"200":{"description":"The contact's primary inbox.","content":{"application/json":{"schema":{"required":["contact_uuid","default_inbox_contact","is_whatsapp_tab_visible","unseen_messages_count","open_inbox_url","last_conversation_url"],"properties":{"contact_uuid":{"description":"ID the WhatsApp service knows the contact by.","type":"string","example":"3f1c2a9e-7b4d-4e8a-9c11-5d2f6b7a8e90"},"default_inbox_contact":{"description":"The WhatsApp service's inbox contact on the contact's default channel, passed through as the service returns it. Always has channel; id, url and last_conversation when the service sends them.","type":"object","example":{"id":"7a2b9c4d-1e3f-4a5b-8c6d-9e0f1a2b3c4d","channel":12,"last_conversation":{"id":"b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"}},"additionalProperties":true},"is_whatsapp_tab_visible":{"description":"True when the inbox contact has an id.","type":"boolean","example":true},"unseen_messages_count":{"description":"Unseen messages on the inbox contact, as the WhatsApp service counts them; 0 when it cannot be read.","type":"integer","example":3},"open_inbox_url":{"description":"The inbox contact's url, else the app path of its conversation details, else null.","type":["string","null"],"example":"/app/whatsapp/inbox/conversation/7a2b9c4d-1e3f-4a5b-8c6d-9e0f1a2b3c4d/details"},"last_conversation_url":{"description":"App path of the last conversation, or null when there is none.","type":["string","null"],"example":"/app/whatsapp/inbox/conversation/b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e/details"}},"type":"object"}}}},"400":{"description":"The ID Hosted recorded for the contact in the WhatsApp service is not a UUID.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"title":"Invalid contactUuid parameter."}]}}}},"403":{"description":"The account has no WhatsApp inbox, or the WhatsApp contact activities and inbox linking feature is off for it.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"title":"WhatsApp inbox feature is not enabled."}]}}}},"404":{"description":"The contact has not been pushed to the WhatsApp service (Contact not found.), or it has no inbox contact on its default channel or the service could not be read (Primary inbox not found for given contact.).","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"title":"Contact not found."}]}}}},"500":{"description":"An unexpected error while building the answer.","content":{"application/json":{"schema":{"type":"object"},"example":{"errors":[{"title":"An unexpected error occurred."}]}}}}},"x-canonical-resource":"whatsapp_conversation","x-internal":true}},"/zendesk/rawUserData":{"get":{"summary":"Retrieve the support widget user data","description":"Who the signed-in user is and what the support widget may offer them: the same facts Retrieve the signed support widget identity token signs, returned as plain JSON. Internal: support widget diagnostics, not a customer API.","operationId":"retrieve-zendesk-widget-user-data","responses":{"200":{"description":"The user data.","content":{"application/json":{"schema":{"required":["userId","name","Email","accountId","accountName","admin","mainAdmin","planType","hasBillingAccess","hasZendeskWidgetEnabled"],"properties":{"userId":{"description":"ID of the signed-in user. A string of digits, not a JSON number.","type":"string","example":"1"},"name":{"description":"The user's first and last name joined by one space. The space is there even when a name is empty.","type":"string","example":"Pat Lee"},"Email":{"description":"The user's login email. The key starts with a capital E.","type":"string","example":"pat@example.com"},"accountId":{"description":"ID of the account.","type":"integer","example":12345},"accountName":{"description":"The account's host name.","type":"string","example":"example.activehosted.com"},"admin":{"description":"Whether the user is in the Admin group.","type":"boolean","example":true},"mainAdmin":{"description":"Whether the user is the account's primary admin, the user who owns the account.","type":"boolean","example":true},"planType":{"description":"Name of the account's plan tier, for example Forever Free or Plus.","type":"string","example":"Plus"},"hasBillingAccess":{"description":"Whether the user may manage billing: the primary admin always may, anyone else only with the billing role.","type":"boolean","example":true},"hasZendeskWidgetEnabled":{"description":"Whether the account shows the support widget. Always false for a reseller account and for an account with no branding record; otherwise true when its branding shows ActiveCampaign links or turns the support widget on.","type":"boolean","example":true}},"type":"object"}}}}},"x-canonical-resource":"account_user","x-internal":true}},"/zendesk/userData":{"get":{"summary":"Retrieve the signed support widget identity token","description":"A signed token that identifies the signed-in user to the in-app support widget, so a support conversation starts with who they are and which account they are on. Internal: the app requests it when it loads the support widget and hands the token to the widget unread.\n\nThe token is an HS256 JSON Web Token signed with a secret shared with the support tool. Its claims are the object Retrieve the support widget user data returns, plus `iat` (when it was issued) and `exp` (twelve hours later), both in Unix seconds. It is minted fresh on every call.","operationId":"retrieve-zendesk-widget-user-token","responses":{"200":{"description":"The token.","content":{"application/json":{"schema":{"required":["userData"],"properties":{"userData":{"description":"The signed JSON Web Token, in compact form (three base64url segments separated by dots).","type":"string","example":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxIn0.c2lnbmF0dXJl"}},"type":"object"}}}}},"x-canonical-resource":"account_user","x-internal":true}}},"x-readme":{"headers":[],"explorer-enabled":false,"proxy-enabled":false},"x-readme-fauxas":true}