Email Webhooks send email performance data from Customer.io to a URL you specify in order to receive information about events as they occur in real time. Customer.io sends the information as JSON in an HTTP POST.
To begin receiving HTTP calls from Customer.io:
Log in and choose Integrations from the left panel.
Look under Streaming Data Out.
Press the Get Started button next to Email Activity Webhook.
Enter the URL for the Webhook Endpoint at which you would like to receive the event notifications. The URL can be either an HTTP or HTTPs URL (HTTPs is generally preferred for protecting customer information).
Select the event notifications you want to monitor and click Save Changes at the bottom right of the page.
You may use a service like webhook.site to inspect HTTP requests before pointing them at your own servers. Note the following warning:
Adding a URL to any endpoint will cause us to start sending potentially sensitive data to that URL right away. The information we send comes directly from the data you store in the same workspace as the settings you are updating. Testing tools provided by untrusted third parties should only be used with dummy/test data that is stored in a test/sandbox workspace in order to prevent leaking your real customer data to the providers of those services.
To send a test event to your webhook endpoint, press Send Test. Once sent you will see a green checkmark to the right of the button.
By registering a URL with Customer.io, you can be notified when the following events occur:
customer_subscribed: customer has been re-subscribed.
customer_unsubscribed: customer has been unsubscribed.
email_attempted: we’ve attempted to send this but weren’t successful. Retrying…
email_bounced: receiving server for email could not or would not accept the email
email_clicked: customer clicked through a link in the email
email_converted: customer entered/exited the segment set as conversion segment
email_delivered: email successfully delivered to the receiving server
email_drafted: email you asked for approval before sending is ready for approval
email_dropped: email was suppressed because customer bounced or reported your emails as spam previously
email_failed: email had an error as we tried to render it for delivery. A common scenario is the matching customer is missing an attribute you’ve used in the email content.
email_opened: email was opened by one of your customers
email_sent: email has been sent from our servers
email_spammed: email was marked as spam by the customer
email_unsubscribed: the customer clicked the unsubscribe link on this email
To only receive specific events, select just those that interest you:
If you have a specific request for an event not listed here that you would like to be notified of, please contact us.
Customer.io Webhooks are HTTP POST requests encoded in JSON. The requests have a User Agent header containing “Customer.io Web Hooks x.x” where “x.x” is the version number.
The JSON body contains a general top-level section included in all webhook requests, as well as a “data” attribute, which contains data specific to the type of event.
Below is an example of an HTTP request for any of the email related events:
An example of an HTTP request for any customer related events:
template_id: internal attribute, each email inside a campaign can have multiple template ids depending on the changes made over time. You can view it in the UI by filtering for a specific email under Email Log. For example: https://fly.customer.io/env/51831/email_logs?campaign=139744&template=343216
timestamp: date and time when the event took place in unix (seconds since epoch) format
attachments: specific to event-triggered emails with small attachments (e.g. .ics files)
customer: all the attributes associated with your user
Timeouts and Failures
We have a 4 second timeout and if we don’t get a successful (200) response in that period, or if anything but a 200 success code is returned, Customer.io will retry sending the notification several times with exponential backoff. We keep retrying up to a max of 10 times over a period of approximately 7 hours.
Securely Verifying Requests
For security purposes, every email webhook is delivered with an X-CIO-Signature header. This signature is generated by combining your webhook signing key with the body of webhook request using a standard HMAC-SHA256 hash. You can find the signing key on the Email Activity Webhook integration page in your account settings. (This is the same page where you enter your webhook endpoint.)
To validate a signed request, first you’ll need to retrieve the X-CIO-Timestamp header sent with the webhook request, and the body of the request. Combine the version number, timestamp and body delimited by colons to form a string in the form v0:<timestamp>:<body> (the version number is always v0). Using HMAC SHA256, hash the string using your webhook signing secret as the hash key. Compare this value to the value of the X-CIO-Signature header sent with the request to confirm that the request originated with Customer.io.
Do webhooks contain the email body? No, we only send the attributes mentioned above under “List of Webhook Attributes”.
How can I secure webhooks? To secure webhooks, you can add basic authentication in the link (e.g. http://username:email@example.com).
How do you identify each message that is going out? Each message sent from Customer.io has an email_id unique identifier that is also part of the default unsubscribe link: https://track.customer.io/unsubscribe/MjYyMTI6Fs_YAmQAAnMAFeEaAU2YoV7tFRoYVh6HYAFzOjIyOTkwMQA=
To view a particular message the UI, go to the Email Log page, open any email and then inside the URL replace the part after email_logs/ with the email_id you’re interested in. For example https://fly.customer.io/env/26212/email_logs/MjYyMTI6Fs_YAmQAAnMAFeEaAU2YoV7tFRoYVh6HYAFzOjIyOTkwMQA=
The email_id is also displayed under the Metadata details in the right-hand column of the page.
Can I specify which campaign(s) get forwarded to an external webhook? No. If you want to monitor only a specific campaign, you’ll need to handle the logic on your end to filter out unwanted webhook events based on their campaign_id.
Can I get a webhook when a customer gets added to a segment? From our end, there isn’t a direct way to retrieve segment membership. One solution, though, would be to create a segment-triggered campaign based on the segment you’re interested in, set the email inside to “Queue Draft” and then monitor the email_drafted events for that campaign_id on your end.
Do you send an event for each click performed by a user? The email_clicked event is unique, so it only gets triggered the first time someone clicks your email.
Is there a way to rate limit webhooks? No, right now you always get one event per action (sent, opened, clicked, etc.). Unfortunately for larger mailing that can mean thousand of messages pretty quickly.