Email campaigns & segments
Email campaigns & segments endpoints of the Zanfia Workspace API, with schemas and code samples.
One-off email broadcasts and the audience segments that target them. A campaign is composed as a draft and sent (or scheduled up to 30 days ahead) via the send route — sending is irreversible, so preview the audience first with POST /segments/preview. GET /sender-domain shows the sending identity (custom domains, their DNS records, the platform fallback address) and PUT /sender-domain/postal-address sets the footer postal address a send requires; adding or verifying a domain stays in the dashboard. All routes require a Authorization: Bearer header — see Authentication.
List email campaigns
/campaignsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/campaigns"{ "count": 0, "campaigns": [ { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } } ]}{ "error": "string", "message": "string"}Create a campaign draft
/campaignsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Creates a DRAFT campaign — nothing is emailed. Everything beyond the name is optional at draft time; completeness is enforced by the send route.
Response Body
application/json
application/json
curl -X POST "https://example.com/campaigns" \ -H "Content-Type: application/json" \ -d '{ "name": "string" }'{ "campaign": { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } }}{ "error": "string", "message": "string"}Get a campaign
/campaigns/{campaignId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Response Body
application/json
application/json
curl -X GET "https://example.com/campaigns/string"{ "campaign": { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } }}{ "error": "string", "message": "string"}Update a campaign draft
/campaigns/{campaignId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Drafts only — a campaign past draft is immutable except cancel.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/campaigns/string" \ -H "Content-Type: application/json" \ -d '{}'{ "campaign": { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } }}{ "error": "string", "message": "string"}Delete a campaign
/campaigns/{campaignId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Response Body
application/json
application/json
curl -X DELETE "https://example.com/campaigns/string"{ "campaignId": "string", "deleted": true}{ "error": "string", "message": "string"}Send or schedule a campaign
/campaigns/{campaignId}/sendAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
⚠️ HIGHEST-STAKES ROUTE: this SENDS the campaign — real bulk email to the resolved audience (every subscribed client, or the saved segment). Once the fan-out starts, delivered mail cannot be recalled; the only recovery is POST /campaigns/:campaignId/cancel, which stops REMAINING sends only.
The use case guards: draft-only (CAS status transition doubles as the double-send guard), completeness check (subject/content/sender), non-empty audience, and a ≤ 30-days-out schedule ceiling. Omit scheduledAt to send immediately.
Response Body
application/json
application/json
curl -X POST "https://example.com/campaigns/string/send" \ -H "Content-Type: application/json" \ -d '{}'{ "campaign": { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } }}{ "error": "string", "message": "string"}Cancel a scheduled/sending campaign
/campaigns/{campaignId}/cancelAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Response Body
application/json
application/json
curl -X POST "https://example.com/campaigns/string/cancel"{ "campaign": { "id": "string", "name": "string", "status": "draft", "category": "platform-announcements", "newsletterId": "string", "subject": "string", "preheader": "string", "contentMarkdown": "string", "contentFormat": "markdown", "contentHtml": "string", "sender": { "fromName": "string", "replyTo": "string", "fromEmail": "string" }, "templateId": "string", "theme": { "backgroundColor": "string", "contentBackgroundColor": "string", "linkColor": "string", "buttonColor": "string", "buttonTextColor": "string", "lineHeight": 0, "contentWidth": 0 }, "contentTextOverride": "string", "trackEngagement": true, "linkActions": [ { "url": "string", "addTagIds": [ "string" ], "removeTagIds": [ "string" ], "addToAutomationIds": [ "string" ] } ], "audience": { "type": "segment", "segmentId": "string" }, "recipientCount": 0, "duplicateRecipientsSkipped": 0, "scheduledAt": "string", "sendStartedAt": "string", "completedAt": "string", "quotaPausedUntil": "string", "stats": { "sent": 0, "delivered": 0, "bounced": 0, "complained": 0, "failed": 0, "skippedSuppressed": 0, "skippedMuted": 0, "trackedRecipients": 0, "uniqueClicks": 0, "clicks": 0, "uniqueOpens": 0, "opens": 0, "attributedOrders": 0, "attributedRevenue": 0, "attributedCurrency": "string", "unsubscribed": 0 }, "createdAt": "string", "updatedAt": "string", "importedFrom": { "provider": "string", "accountUrl": "string", "externalCampaignId": "string", "sentAt": "string", "audience": { "listNames": [ "string" ], "segmentName": "string" }, "stats": { "sends": 0, "opens": 0, "uniqueOpens": 0, "clicks": 0, "uniqueClicks": 0, "unsubscribes": 0, "bounces": 0 }, "importedAt": "string" } }}{ "error": "string", "message": "string"}List campaign recipients
/campaigns/{campaignId}/recipientsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Query Parameters
Value in
- "pending"
- "sent"
- "delivered"
- "skipped-suppressed"
- "skipped-muted"
- "failed"
- "bounced"
- "complained"
- "clicked"
Only recipients who clicked this link; wins over status.
1 <= value <= 20050Response Body
application/json
application/json
curl -X GET "https://example.com/campaigns/string/recipients"{ "recipients": [ { "id": "string", "email": "string", "status": "pending", "statusDetails": "string", "processedAt": "string", "tracked": true, "firstOpenedAt": "string", "firstClickedAt": "string", "openCount": 0, "clickCount": 0, "unsubscribedAt": "string" } ], "nextCursor": "string"}{ "error": "string", "message": "string"}List campaign link clicks
/campaigns/{campaignId}/linksAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Campaign id
Response Body
application/json
application/json
curl -X GET "https://example.com/campaigns/string/links"{ "links": [ { "id": "string", "url": "string", "label": "string", "uniqueClicks": 0, "clicks": 0, "firstClickedAt": "string", "lastClickedAt": "string" } ]}{ "error": "string", "message": "string"}List audience segments
/segmentsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/segments"{ "count": 0, "segments": [ { "id": "string", "name": "string", "type": "dynamic", "conditions": [ { "field": "tag", "operator": "has", "tagId": "string" } ], "lastEvaluatedCount": 0, "lastEvaluatedSendableCount": 0, "lastEvaluatedAt": "string", "createdAt": "string", "updatedAt": "string" } ]}{ "error": "string", "message": "string"}Create an audience segment
/segmentsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/segments" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "conditions": [ { "field": "tag", "operator": "has", "tagId": "string" } ] }'{ "segment": { "id": "string", "name": "string", "type": "dynamic", "conditions": [ { "field": "tag", "operator": "has", "tagId": "string" } ], "lastEvaluatedCount": 0, "lastEvaluatedSendableCount": 0, "lastEvaluatedAt": "string", "createdAt": "string", "updatedAt": "string" }}{ "error": "string", "message": "string"}Update an audience segment
/segments/{segmentId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/segments/string" \ -H "Content-Type: application/json" \ -d '{}'{ "segment": { "id": "string", "name": "string", "type": "dynamic", "conditions": [ { "field": "tag", "operator": "has", "tagId": "string" } ], "lastEvaluatedCount": 0, "lastEvaluatedSendableCount": 0, "lastEvaluatedAt": "string", "createdAt": "string", "updatedAt": "string" }}{ "error": "string", "message": "string"}Delete an audience segment
/segments/{segmentId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Response Body
application/json
application/json
curl -X DELETE "https://example.com/segments/string"{ "segmentId": "string", "deleted": true}{ "error": "string", "message": "string"}Preview a segment's audience
/segments/previewAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Stateless evaluation of a condition set — nothing is persisted.
Response Body
application/json
application/json
curl -X POST "https://example.com/segments/preview" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ { "field": "tag", "operator": "has", "tagId": "string" } ] }'{ "count": 0}{ "error": "string", "message": "string"}Get the sender domain
/sender-domainAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/sender-domain"{ "senderDomain": { "domain": "string", "status": "pending", "mailFromStatus": "pending", "ownershipVerified": true, "records": [ { "type": "CNAME", "name": "string", "value": "string", "purpose": "dkim", "required": true, "priority": 0 } ], "defaultFromLocalPart": "string", "defaultFromEmail": "string", "verifiedAt": "string", "lastCheckedAt": "string", "isDefault": true }, "senderDomains": [ { "domain": "string", "status": "pending", "mailFromStatus": "pending", "ownershipVerified": true, "records": [ { "type": "CNAME", "name": "string", "value": "string", "purpose": "dkim", "required": true, "priority": 0 } ], "defaultFromLocalPart": "string", "defaultFromEmail": "string", "verifiedAt": "string", "lastCheckedAt": "string", "isDefault": true } ], "maxSenderDomains": 0, "platformFromAddress": "string", "postalAddress": "string", "unsubscribeLabel": "string", "systemEmailsFromCustomDomain": true}{ "error": "string", "message": "string"}Set the footer postal address
/sender-domain/postal-addressAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://example.com/sender-domain/postal-address" \ -H "Content-Type: application/json" \ -d '{ "postalAddress": "string" }'{ "postalAddress": "string"}{ "error": "string", "message": "string"}Was this article helpful?

