Skip to main content

Communications API: campaign rules, duplicate, safer unsubscribe

  • Duplicate a campaign. POST /campaigns/{id}/duplicate copies a campaign of any status into a new draft with the same template, lists, Motor Block, From address and pacing. Completed and cancelled campaigns are final, so this is how you send one again.
  • Status machine. draft, scheduled, sending, completed, cancelled. Completed and cancelled cannot be edited, rescheduled or restarted (409 INVALID_STATE). What a draft, scheduled or sending campaign may still change is listed per status. There is no paused state.
  • Scheduling checks everything, and compiles. POST /campaigns/{id}/schedule re-checks the Motor Block, template, lists and From address, sanitises and compiles the HTML, freezes the audience, and refuses an empty audience (EMPTY_AUDIENCE) or a past time (SCHEDULED_AT_IN_PAST). A separate compile call is optional now.
  • The From address must be on the Motor Block's own domain (FROM_DOMAIN_MISMATCH), when you create the campaign, when you schedule it, and again when it is sent.
  • Templates, lists and Motor Blocks must belong to your workspace; another workspace's id is a 404. Malformed ids are 400 INVALID_ID.
  • Retry-safe creates. POST /campaigns, /schedule and /duplicate accept an Idempotency-Key; a retry replays the first answer instead of creating a second campaign.
  • One report. /campaigns/{id}/report is new, and /stats, /analytics and the overview read the same per-recipient numbers, so they agree. /stats now returns unsubscribed. /events accepts redact=true.
  • Unsubscribe links are safe to scan and no longer expire. Opening the link shows a confirmation page; only the button (or the mail client's one-click) unsubscribes, so link scanners cannot unsubscribe people. Every path records the same data, with a source of one_click, link, manual or api. The List-Unsubscribe header offers the https link only.
  • Removing a spam-complaint suppression needs acknowledge_complaint=true (409 COMPLAINT_ACKNOWLEDGEMENT_REQUIRED without it). Suppressions are account-wide.
  • GDPR export is POST /gdpr/export. It emails the export, so GET is deprecated.
  • Corrections to these pages: the paused state and the "Smart Scheduling" features never existed and are removed; suppressions are shared across the account, not isolated per workspace; and the request examples now include the Authorization header they always needed.

Documentation changed