Event

trigger.customer_io_event
TriggerCRM & salesconnection requiredruns in-engine

Registers a reporting webhook in the tenant's Customer.io workspace on publish and starts one run per delivered event, verified against X-CIO-Signature.

Start a run when Customer.io reports a message or subscription event (bounce, click, unsubscribe…).

Connection

Required
Yes — the node will not save without one
Auth type
API key
Providers
Customer.io
Secret shape
{"app_api_key", "webhook_signing_key"}
Config it needs
region
Resolved by
config.connection_id, else node.connection_id
Note
Two credentials, and they are not interchangeable: the App API key creates and deletes the reporting webhook, and the workspace's webhook signing key is what signs every delivery. Customer.io shows the signing key only in the UI (Data & Integrations → Integrations → Reporting Webhooks) and returns it from no API, so it has to be stored on the connection as 'webhook_signing_key'. Publishing also needs MANTLE_APP_PUBLIC_BASE_URL set to a URL Customer.io can reach.

Configuration

3 fields, none required. A dotted path is a nested object and name[] an array of objects — the editor renders the same tree.

FieldTypeRequiredDefaultConstraintsExample
events
Which events to report. Customer.io accepts only the names listed, and every one of them starts a run — subscribing to a whole channel is how a workflow written for bounces starts firing on opens.
arrayNo["email_bounced"]1–72 characters; array of string—
full_resolution
Report every open and click rather than only the first of each per message. Off by default, and it multiplies runs: a newsletter opened four times by one person is four events with this on.
booleanNofalse——
with_content
Include the rendered message body in *_sent events. Off by default — it puts the message a customer received into the run's payload.
booleanNofalse——

Example configuration

Every value below is the contract’s own example or default — nothing invented.

{
  "events": [
    "email_bounced"
  ],
  "full_resolution": false,
  "with_content": false
}

Output

One shape.

customer.io event

The flattened reporting-webhook event. data's own keys vary by object_type and metric, so the shape is open below the declared fields.

Extra keys beyond the ones listed can appear.

FieldTypeExample
event_id
Customer.io's id for the event. Also the idempotency key: a retry carries the same id, so a redelivery joins the run it already started instead of starting a second. The ingress remembers a key for 24 hours while Customer.io retries for up to seven days, so a retry that lands after that window can still start a fresh run.
string01E4C4CT6YDC7Y5M7FE1GWWPQJ
event_type
object_type and metric joined — email_bounced, sms_delivered, customer_unsubscribed. The same spelling the subscription uses, so this is what to branch on when the trigger subscribes to several.
stringemail_bounced
object_type
What the event is about: email, sms, push, in_app, slack, whatsapp, webhook, or customer for a subscription change.
stringemail
metric
What happened to it: sent, delivered, opened, clicked, bounced, failed, converted, subscribed, unsubscribed…
stringbounced
timestamp
When the event happened, Unix seconds.
number1613063089
occurred_at
The same instant as an ISO-8601 UTC string.
string—
customer_id
Customer.io's internal id for the person, when the event is about one. Empty on events that are not.
string—
email_address
The address the message went to, lifted out of data for the common case. Empty for non-email events.
string—
identifiers
Every way this person can be addressed — id, email, cio_id — which is what the customer_io.* action nodes take.
object—
delivery_id
The message this event belongs to. Every event for one send shares it, so it is how opens and clicks are tied back to the send.
string—
data
Customer.io's own object for the event. Its keys depend on object_type and metric (a bounce carries failure_message, a click carries href), which is why this shape is open.
object—
payload
The delivery exactly as Customer.io sent it, for anything the fields above do not lift out.
object—
{
  "customer_id": "0200000001",
  "data": {
    "action_id": 12,
    "campaign_id": 3,
    "customer_id": "0200000001",
    "delivery_id": "RAECAAFwnUSuJIY1Jts2i9BR8p4AAAAA",
    "email_address": "buyer@example.com",
    "failure_message": "550 5.1.1 user unknown",
    "identifiers": {
      "cio_id": "03000001",
      "email": "buyer@example.com",
      "id": "42"
    },
    "recipient": "buyer@example.com",
    "subject": "Your receipt"
  },
  "delivery_id": "RAECAAFwnUSuJIY1Jts2i9BR8p4AAAAA",
  "email_address": "buyer@example.com",
  "event_id": "01E4C4CT6YDC7Y5M7FE1GWWPQJ",
  "event_type": "email_bounced",
  "identifiers": {
    "cio_id": "03000001",
    "email": "buyer@example.com",
    "id": "42"
  },
  "metric": "bounced",
  "object_type": "email",
  "occurred_at": "2021-02-11T17:04:49Z",
  "payload": {
    "event_id": "01E4C4CT6YDC7Y5M7FE1GWWPQJ",
    "metric": "bounced"
  },
  "timestamp": 1613063089
}

Notes

  • Publishing creates the reporting webhook in Customer.io; unpublishing, disabling or archiving deletes it. A workflow that is off is off at Customer.io too.
  • One reporting webhook covers every event this trigger subscribes to — unlike most providers, Customer.io needs no subscription per event type.
  • Each delivery is verified against the workspace signing key over 'v0:{timestamp}:{body}' before any run starts; an unsigned or mis-signed POST is refused with 401.
  • Customer.io times a delivery out after 4 seconds and then retries with backoff for seven days, holding later events behind the failed one. Redeliveries are deduplicated on event_id for 24 hours.
  • An EU workspace is served from api-eu.customer.io; that comes from the connection's 'region', never from this node.

See Event run in a workflow.

In a technical demo we add the Customer.io connection, drop the node on the canvas and let Workflow Health pre-flight it before the first real run.