Skip to content

Campaign

Campaign entity. A campaign is a scheduled send of a set of payloads (Email, SMS). The <campaign> in the URL is the numerical ID of the campaign.

Endpoints

Method URL
GET /campaign/<campaign>
POST /campaign
PUT /campaign/<campaign>
DELETE /campaign/<campaign>

GET /campaign/<campaign>

Payload: No payload.

Returns: The campaign.

Example:

curl -u "username:api_key" -H "Accept: application/json" \
  https://app.duo.pt/campaign/{campaign_id}

Response:

{
  "success": true,
  "data": {
    "campaign": {
      "id": 1,
      "owner": 1,
      "list": 1,
      "name": "Summer Newsletter 2026",
      "domain": 1,
      "segments": [],
      "recipients": null,
      "state": "DRAFT",
      "when": {
        "date": "2026-06-22 21:54:05.000000",
        "timezone_type": 3,
        "timezone": "UTC"
      },
      "event_callback": null
    },
    "email": null,
    "sms": null,
    "statistics": {
      "delivered": 0,
      "bounced": 0,
      "opened": 0,
      "clicked": 0,
      "unsubscribed": 0,
      "emails_sent": 0,
      "sms_sent": 0,
      "sent": 0
    }
  }
}

The statistics object reports totals for the campaign:

Field Description
emails_sent Email messages sent by this campaign
sms_sent SMS messages sent by this campaign
sent Total messages sent (emails_sent + sms_sent)
delivered Messages confirmed delivered
bounced Messages that bounced
opened Unique opens (email only)
clicked Unique clicks (email only)
unsubscribed Unsubscriptions attributed to this campaign

Tip

emails_sent and sms_sent give per-campaign, per-channel volume directly — no need to page through the event collections to count messages.


POST /campaign

Parameter Type Description
name string Campaign name
domain int Bounce domain ID (a Domain object enabled as bouncing domain)
list int ID of the contact list targeted by the campaign
segments[] int array IDs of segments within the list. May occur more than once. If none, campaign sends to all contacts.
state string Campaign state. Valid states: DRAFT⮂SCHEDULED⮂READY⇒SENDING⇒(DONE\|ERROR)
when timestamp Scheduled send time. Unix timestamp (int) or ISO 8601 string.
event_callback string Optional. URL called back when events occur.

Note

Transitioning out of DRAFT requires the domain to have DNS validated (DKIM, SPF, bounce). The API accepts the PUT without error but leaves the state unchanged if the domain is not fully configured.

Returns: The new campaign.

Example:

curl -u "username:api_key" -H "Accept: application/json" \
  -d "name=My+Campaign&domain={domain_id}&list={list_id}&state=DRAFT" \
  https://app.duo.pt/campaign

Response:

{
  "success": true,
  "data": {
    "list": {
      "id": 1,
      "owner": 1,
      "name": "Example...",
      "default_email_out": null,
      "unsubscribe_message": "You have been unsubscribed.",
      "email_out_custom_fields": null,
      "double_optin": false,
      "optout_allowed": false,
      "optout_category": null,
      "optin_email": null,
      "optin_sms": null,
      "shared_with_children": false,
      "read_shared_with_children": false,
      "segments": null
    },
    "campaign": {
      "id": 1,
      "owner": 1,
      "list": 1,
      "name": "Summer Newsletter 2026",
      "domain": 1,
      "segments": null,
      "recipients": null,
      "state": "DRAFT",
      "when": "2026-06-22T21:54:05+00:00",
      "event_callback": null
    }
  }
}

PUT /campaign/<campaign>

Parameter Type Description
name string Campaign name
domain int Bounce domain ID (a Domain object enabled as bouncing domain)
segments[] int array IDs of segments within the list to target. May occur more than once. If none, campaign sends to all contacts.
state string Campaign state
when timestamp Scheduled send time
event_callback string Optional. URL called back when events occur.

Returns: The edited campaign.

Example:

curl -u "username:api_key" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name": "Summer Newsletter 2026", "domain": 1, "list": 1, "state": "SCHEDULED", "when": 1750000000}' \
  https://app.duo.pt/campaign/{campaign_id}

Response:

{
  "success": true,
  "data": {
    "campaign": {
      "id": 1,
      "owner": 1,
      "list": 1,
      "name": "Summer Newsletter 2026",
      "domain": 1,
      "segments": [],
      "recipients": null,
      "state": "DRAFT",
      "when": {
        "date": "2026-06-22 21:54:05.000000",
        "timezone_type": 3,
        "timezone": "UTC"
      },
      "event_callback": null
    }
  }
}

DELETE /campaign/<campaign>

Payload: No payload.

Returns: The deleted campaign.

Example:

curl -u "username:api_key" -H "Accept: application/json" -X DELETE \
  https://app.duo.pt/campaign/{campaign_id}

Response:

{
  "success": true,
  "data": {
    "campaign": {
      "id": 1,
      "owner": 1,
      "list": 1,
      "name": "Summer Newsletter 2026",
      "domain": 1,
      "segments": [],
      "recipients": null,
      "state": "DRAFT",
      "when": {
        "date": "2026-06-22 21:54:05.000000",
        "timezone_type": 3,
        "timezone": "UTC"
      },
      "event_callback": null
    }
  }
}

Callback Behaviour

If an event_callback URL is defined, a POST request is executed against it whenever a message lifecycle event occurs.

Events

Event Description
submitted Message submitted for delivery
delivered Message delivered
bounced Permanent delivery failure
opened Message opened
clicked A link in the message was clicked

Note

SMS payloads only generate delivered and bounced events. Email payloads generate all events.

The event_callback URL may contain a query string — those parameters are forwarded unchanged.

Callback POST parameters

Parameter Type Description
event string Which event occurred
when int Unix timestamp of the event
telephone[] string array Phone numbers for SMS events (telephone[0], telephone[1], ...)
email[] string array Emails for email events (email[0], email[1], ...)

Note

Events are time-aggregated. A delay of up to five minutes is expected between the actual event and the callback execution.