SendlySendly
Integrations

Event vocabularies

Sendly has two event name lists — one a webhook subscription accepts, one a workflow triggers on — and they are not the same

Sendly names events in two places, and the names are not the same in both. Nothing warns you about this: a name from the wrong list is either rejected as invalid or, worse, accepted as a custom event that will never fire.

  • Webhook subscription events are what createWebhook accepts in eventTypes. A fixed list of ten. Anything else is a 400.
  • Workflow trigger events are what the system records on the timeline and what a workflow's event trigger matches on. A longer list, plus your own custom names.

Four names appear in both lists and mean the same thing in each: email.sent, email.opened, email.clicked and contact.unsubscribed. Every other name belongs to one list only, and three pairs are near-misses that differ by a letter or two.

Check which list you are in before hardcoding a name

The past tense is the tell, and it is not reliable. A subscription wants email.delivered; a workflow triggers on email.delivery. A subscription wants email.bounced; a workflow triggers on email.bounce.

Webhook subscription events

The ten values POST /api/webhooks accepts. A subscription names one or more of them.

EventWhen it fires
email.sentThe message was handed to the sending infrastructure.
email.deliveredThe recipient's server accepted it.
email.openedThe message was opened.
email.clickedA link in the message was clicked.
email.bouncedThe message hard-bounced. A soft bounce does not fire this.
email.complainedThe recipient marked it as spam.
email.failedThe send failed before or at handoff — rejected, or unrenderable.
contact.createdA contact was created, by any route including an import.
contact.unsubscribedA contact's status changed to unsubscribed.
contacts.bulk_createdA bulk import finished creating contacts.

Workflow trigger events

What the system records and what a workflow's event trigger matches. You do not subscribe to these; you build a workflow whose trigger names one.

Recorded by Sendly itself:

EventWhen it fires
email.sentThe message was handed to the sending infrastructure.
email.openedAn open was recorded — by Sendly's tracking pixel, or by the provider's own open tracking.
email.clickedA click was recorded — by Sendly's rewritten link, or by the provider's own click tracking.
email.receivedInbound mail arrived on a verified domain.
contact.subscribedA contact's status changed to subscribed.
contact.unsubscribedA contact's status changed to unsubscribed.
mailbox.message.receivedA message arrived in a Sendly mailbox.
mailbox.message.sentA message was sent from a Sendly mailbox.

Recorded from the sending infrastructure's own reports:

EventWhen it fires
email.deliveryThe recipient's server accepted the message.
email.bounceThe message bounced, hard or soft.
email.complaintThe recipient marked it as spam.
email.rejectThe message was refused before it was sent.
email.renderingfailureA template variable could not be rendered.
email.deliverydelayDelivery is being retried after a temporary failure.

One open can be recorded twice

Two independent things detect an open: Sendly's tracking pixel and the provider's own open tracking. They used to record it under two different names, so a workflow saw whichever half it had named. Both now record email.opened, and clicks likewise record email.clicked — which means one message can fire the trigger more than once, because both detectors can see the same open. A workflow on these names should be written to tolerate that. If you are counting opens, read the message's own opens field rather than counting events.

The two lists spell the same events differently

A webhook subscribes to email.delivered; a workflow triggers on email.delivery. Same for email.bounced against email.bounce, and email.complained against email.complaint. The names come from different places and neither list is going to silently change under a running integration, so check the list you are actually using rather than assuming the other one's spelling.

Names you make up

Two more kinds of trigger name exist, and neither is on a fixed list:

  • Segment membership. A segment called "VIP Users" produces segment.vip-users.entry and segment.vip-users.exit. The slug is derived from the segment's name, so renaming the segment renames its events.
  • Your own events. POST /api/v1/events records any name you give it, and a workflow can trigger on it. This is how an integration turns something that happened in another system into something Sendly can act on.

A workflow trigger on a name nothing ever records is not an error — it simply never fires. That is the failure mode this page exists to prevent.

On this page