Webhooks - Getting Started

Webhooks - Getting Started


A custom webhook can pass data to just about any public API on the internet. You can use it to send a text message, update a CRM or take just about any action on a customer that you'd want to do.

With a little trial and error, you should be able to connect Customer.io to another service you’re using. This guide will give you some basics to help you get started.

Creating a webhook action

In the workflow, you can choose a Webhook item and drag and drop it into your campaign. After doing so, click the item to edit it, then click Add Request to go into the message composer.

image.png

HTTP Request Types

Customer.io webhook actions support 4 common HTTP request types for RESTful APIs:

  • GET
  • POST
  • PUT
  • DELETE

The one you use is dependent on what the API you’re using is expecting. POST is most likely to be used and is the default.

Request URL

Next to your request type you will add the request URL that you want us to send the data to.

If your API requires Basic Authentication, you’ll add the username and password to the request like: https://user:pass@api.example.com

Headers

You can customize the headers that Customer.io sends with each request in order to support things like:

  • Specifying the Content-Type
  • Supporting other types of Authentication
  • Setting other specific headers required for a specific API

Content-Type

By default, we pre-fill: Content-Type: application/json

Other example Content-Type values are:

  • x-www-form-urlencoded
  • text/plain
  • text/xml

Note, we recommend working with APIs using Content-Type: application/json for readability whenever possible.

Structuring content for a webhook (JSON)

If you’re using Content-Type: application/json, you’ll want to make sure you’re using fully formed JSON.

A good place to test this is:

http://jsonlint.com/

A simple example for valid JSON is:

{
    "id":"1",
    "email":"win@customer.io"
}

You’d create something like that by putting this text in to the editor:

{
    "id":"{{customer.id}}",
    "email":"{{customer.email}}"
}

image.png

A slightly more advanced example is:

{
    "customer": 
    {{ customer | replace: "=>", ":"}}
}

That will output the entire customer object in JSON format.

Structuring content for a webhook (Form encoded)

If you want to send a form encoded webhook, you’ll set the Content-Type header as: x-www-form-urlencoded

Then, the body needs to be valid form encoded text. Something like:

id=1&email=win@customer.io&custom_attribute=value

You’d create something like that by putting this text in to the editor:

id={{customer.id}}&email={{customer.email}}&custom_attribute={{customer.another_attribute}}

The downside of form encoded is that it’s a bit harder to structure and read since there are no line breaks and separation other than the "&" characters that join everything together.

Response

When sending requests to an endpoint, you can choose to set attributes on people based on the response data. This allows you to retrieve data from an endpoint to then use in the content of your messages down the road. To do this, while editing the request in the composer, go to the 'Response' tab and click the 'Set up an attribute' button.
webhook_response__set_up_an_attribute

From here, select the attribute that you'd like to set a new value for using the dropdown. Then, use the response variable and Liquid to define the value in the code editing component. Here are a few examples of things you might do with the webhook response:

After creating a new lead in your CRM, sync the lead_id returned in the response with your Customer.io lead
webhook_response_example__leadid

Increment the lifetime_value of a person based on their purchases
webhook_response_example__lifetimevalue

Processing Speed

Webhook actions for campaigns are sent using the same queue as our email deliveries, which handles a maximum of 600 concurrent requests as quickly as possible. This maximum throughput is shared with other customers on the same shard as your account, so you may not see the maximum throughput for your requests, especially during peak times. The actual amount will depend on system load at the time the webhook notifications are being sent.

Timeouts and Failures

We have a 4 second timeout and if we get a 408, 409, 429, or 5xx response code in that period, 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. If all retries fail, the Attribute Update will not execute, and the profile will move to the next step of the workflow.

If you wish to temporarily block our servers, you can look up the current set of IP addresses we use via this API endpoint.

Note: If a webhook is configured to set attributes with the response and the call fails, the attribute update will not execute, and the profile will move to the next step of the workflow.

Testing your requests

If you'd like to test the format of your requests before pointing them at the correct API, you could use a service like Webhook.site. A URL is automatically generated on Webhook.site which you then paste in to Customer.io as the request URL. We strongly recommend only using test data with any third-party service you do not have a trusted relationship with.

More ideas & examples

For all of the following examples, you must create an account at the partner's site first in order to use them in a webhook request.

Create a Zendesk Ticket

With webhooks, you can create a ticket in Zendesk. Here's an example where someone canceled their account and provided feedback. We use the event and feedback to create a ticket in Zendesk.
Request Header: https://[YOUR-EMAIL-ADDRESS]:[YOUR-PASSWORD]@[YOUR-ZENDESK-SUBDOMAIN].zendesk.com/api/v2/tickets.json
Request Body:

{
    "ticket": {
        "subject": "{{customer.company_name}} has canceled their account.",
        "comment": { "body":"{{event.feedback}}" },
        "requester": { "name":"{{customer.firstName"}} {{customer.lastName"}},"email":"{{customer.email}}"
        }
    }
}

You can find more Zendesk webhooks and available fields here.

Send Data to Zapier

Zapier is one of the most flexible integrations we have and you might want to use it to do things like:

  • Add data to a google sheet
  • Follow a person on twitter when they enter the segment “Has twitter name”
  • Add a ticket in Jira when a user does the event “bug_reported”
  • Send new paid accounts an invitation to review your service on Trustpilot

To start, go to your Zapier account and create a new Zap. Choose the “Webhooks” Trigger App and then select “Catch Hook.” You don’t need to set any options, so click continue if you see that screen. Then copy the Webhook URL.

In Customer.io, you would add the Zapier Webhook URL to a webhook action like so, below and send the customer and/or event to Zapier as json.
image.png
Now that your data is flowing in to Zapier, you can complete the rest of their process and hook Customer.io data up to any one of their integrations.

Create a Trello Card with Customer.io

Use webhooks to create a Trello card. In this example, we create a task to schedule a call with a new user.
Request Header: https://api.trello.com/1/cards?key=YOUR-API-KEY&token=YOUR-TOKEN
Request Body:

{
    "name": "Schedule call with {{customer.name}}",
    "idList":"{{the id of the list you're adding to}}",
    "due":"null",
    "desc":"The customer can be reached at {{customer.email}}."
}

You can find more Trello endpoints and available fields here.

Send an NPS survey with Promoter.io and Customer.io

Use Promoter.io to send an NPS survey to customers based on attributes and events stored in Customer.io. For instance, you could use a webhook to trigger a Promoter.io survey to customers after their third purchase. For a more comprehensive list of endpoints and attributes, you can view Promoter’s API Docs.

Start mailing Lob postcards with Customer.io

Send a postcard to customers with a Lob webhook!
Request Header: https://[API-KEY]:@api.lob.com/v1/postcards
Request Body:

{
    "description":          "What a fancy postcard",
    "to": {
        "name":             "{{ customer.first_name }} {{ customer.last_name }}",
        "address_line1":    "{{ customer.address_1 }}",
        "address_line2":    "{{ customer.address_2 }}",
        "address_city":     "{{ customer.city }}",
        "address_state":    "{{ customer.State }}",
        "address_zip":      "{{ customer.zip }}",
        "address_country":  "US"
    },
    "from": {
        "name":             "Your Company",
        "address_line1":    "123 Main St",
        "address_line2":    "Ste 300",
        "address_city":     "Portland",
        "address_state":    "OR",
        "address_zip":      "97205",
        "address_country":  "US"
    },
    "front":                "http://userimg.customeriomail.com/WimaKyKwRvusmPIsxsUm_Ian1.jpg",
    "back":                 "<html style='padding: 1in; font-size: 18;'>Hi {{ customer.first_name }}, Thanks for being our customer!</html>"
}

If you’re trying to send a letter or a check, more endpoints are in the Lob documentation.

Start sending data with IFTTT

IFTTT is a great option for connecting to devices, web apps, or services for things like:

  • Turn on a light in your office when you get a new “plan_enterprise” user
  • Create a calendar event to follow up users who enter the “Signed Up” segment
  • Email to your success team when a user triggers “payment_failed”

An example request that sends an email based on an event would look like this:

image.png

The event in the request header and the value1, value2, and value3 in the request body would then populate the email you had drafted in IFTTT.
image.png

Create a Help Scout conversation

Easily create Help Scout conversations from Customer.io. Example:

Request Header: https://[API-KEY]:@api.helpscout.net/v1/conversations.json
Request Body:

{
    "type": "email",
    "customer": {
        "email": "{{customer.email}}",
        "firstName":"{{customer.firstName}}",
        "lastName":"{{customer.lastName}}"
    },
    "subject": "Low NPS rating from customer {{customer.firstName}} {{customer.lastName}}",
    "mailbox": {
        "id": MAILBOX-ID
    },
    "tags": [
        "Customer.io"
    ],
    "status": "active",
    "createdAt": "{% assign current_time = 'now' %}{{current_time | date: "%F"}}",
    "threads": [
        {
            "type": "customer",
            "createdBy": {
                "email": "{{customer.email}}",
                "type": "customer",
                "firstName":"{{customer.firstName}}",
                "lastName":"{{customer.lastName}}"
            },
            "body": "{{customer.comment}} \n \n Rating: {{customer.NPS_rating}}",
            "status": "active",
            "createdAt": "{% assign current_time = 'now' %}{{current_time | date: "%F"}}"
        }
    ]
}

Replace MAILBOX-ID with your own and adapt any attributes to your own data. customer, subject, mailbox, and threads are mandatory fields.

Please be aware that free plans don’t allow API access, and only owners and administrators are able to create API keys.

Create a Lead in Close.io

Close.io is a streamlined sales platform that helps you close more deals. With built-in calling and automatic email tracking, you can focus on selling rather than data entry. In our example, we’re going to show you how to send leads from Customer.io into Close.io, using our segment triggers. If you don’t already have an account, you can create one at Close.io. At any point, you can read all about adding a lead to Close.io via their API. Their docs include details on custom fields, give you example data, and more.

The simplest case is to push a lead into Close.io for every signup that enters Customer.io.
Request Header: https://YOUR-API-KEY@app.close.io/api/v1/lead/
Request Body:

{
  "name": "{{customer.company}}",
  "url": "{% if customer.company_url.size > 0 %}{{customer.company_url}}{%else %}mycompany.com{% endif %}",
  "description": "{{customer.bio}}",
  "contacts": [
    {
      "name": "{{customer.first_name}} {{customer.last_name}}",
      "title": "{{customer.jobTitle}}",
      "emails": [
        {
          "type": "office",
          "email": "{{customer.email}}"
        }
      ],
      "phones": [
        {
          "type": "office",
          "phone": "{{customer.phone}}"
        }
      ]
    }
  ],
  "custom": {
    "Source": "{% if customer.source.size > 0 %}{{customer.source}}{%else %}Unknown{% endif %}"
  },
  "addresses": [
    "{{customer.address}}"
  ]
}

Send a WhatsApp Message Through Twilio

You can send Twilio SMS messages in campaigns with the SMS workflow action. WhatsApp messages work a little differently. In order to send one through Twilio in Customer.io, you will need to use a webhook.

Before you're able to send a WhatsApp message, you will need to create a new template in Twilio and have it approved as described in their documentation. Once you're approved, you can build a webhook that looks like the following:

Request Header: https://api.twilio.com/2010-04-01/Accounts/[YOUR_SID_HERE]/Messages.json

Content-Type: application/x-www-form-urlencoded
Authorization: Basic [YOUR_AUTH_TOKEN_HERE]
Request Body:

Body=[YOUR_URL_ENCODED_MESSAGE_HERE]
&To=whatsapp%3A{{customer.phone|escape}}
&From=whatsapp%3A[YOUR_WHATSAPP_NUMBER_HERE]

whats app webhook

Find more real world examples, take a look at some of our recipes.

Was this article helpful?