Event Callbacks¶
DUO can notify your application when something happens to a message it sent: delivery, bounce,
open, click or unsubscription. You give DUO a URL in the event_callback parameter, and DUO
sends a POST request to that URL with the event and the contacts it applies to.
Where to set the URL¶
| Send type | Where | Parameter |
|---|---|---|
| Campaigns (email and SMS) | POST /campaign or PUT /campaign/<campaign> |
event_callback |
| Transactional messages | Each send request | event_callback |
Warning
For transactional messages, the URL must be sent in every send request. The
event_callback field of the transactional message itself is stored but not used for
callbacks.
The URL must use http or https and include a host and a path, e.g.
https://example.com/duo/events. Use https.
Events¶
event |
Meaning | SMS | |
|---|---|---|---|
submitted |
The message was submitted for delivery | ✓ | |
delivered |
The message was delivered | ✓ | ✓ |
bounced |
The message was not delivered because of a permanent error | ✓ | ✓ |
opened |
The message was opened | ✓ | |
clicked |
A link in the message was clicked | ✓ | |
unsubscribed |
The contact unsubscribed through the unsubscribe link | ✓ |
There is no event for spam complaints.
The request¶
DUO sends a POST with Content-Type: application/x-www-form-urlencoded to the URL, without
its query string. The body has these fields:
| Field | Type | Description |
|---|---|---|
event |
string | The event, as in the table above |
when |
int | Unix timestamp of the event, rounded down to the minute |
email[<n>] |
string | Email of each contact the event applies to. Empty if the contact has no email. |
telephone[<n>] |
string | Telephone of each contact. Empty if the contact has no telephone. |
Events are grouped before they are sent. One request covers one event type for one campaign
or transactional message, and lists every contact it applies to in that period, using the
same index <n> in email[], telephone[] and any per-contact field. The request can arrive
up to five minutes after the event.
Example request body (decoded):
event=delivered
when=1793701080
email[0]=ana@example.com
telephone[0]=351910000001
email[1]=bruno@example.com
telephone[1]=
Adding your own fields¶
Parameters in the query string of the event_callback URL are moved into the request body.
- A fixed value is sent unchanged, once per request. Use it to identify the source or to send a secret token (see Delivery and security).
- A placeholder is replaced with each contact's value and sent as an array, with the same index
as
email[].
| Placeholder | Value |
|---|---|
%CustomField:<id>% |
The contact's value for the custom field <id> of the list |
%List:ID% |
The contact list ID |
%EventPayload:externalid% |
Transactional SMS only: the externalid[] value sent with the message |
Placeholders must be URL-encoded in the URL: %CustomField:42% is written
%25CustomField%3A42%25.
Example: with this callback URL
DUO sends POST https://example.com/duo/events with:
source=newsletter
token=s3cr3t
event=opened
when=1793701080
email[0]=ana@example.com
telephone[0]=351910000001
customer[0]=C-1001
Delivery and security¶
- No retries. Each request is sent once. DUO does not read the response, and a failed request is not repeated. If you need every event, also use the statistics endpoints, such as Campaign Stats or Transactional Stats.
- No signature. Requests are not signed. To check that a request comes from DUO, put a secret token in the URL query string, as in the example above, and compare it on your side.
- Answer quickly with any
2xxstatus and process the events afterwards. - Expect duplicates and gaps. Design the receiver so that processing the same event twice does no harm.