Formatting API-Triggered Broadcasts

When you trigger a broadcast, you can send data to personalize your message or override your audience. This page helps you understand the format of that data and how to set up complex recipient groups.

Providing custom data

You’ll send custom data using our API or our libraries. You can also see sample data in our Composer preview.

Here’s a basic example of what some custom data might look like in your request.

{
  "data": {
    "headline": "Roadrunner spotted in Albuquerque!",
    "date": "January 24, 2018",
    "text": "We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  }
}

Overriding Recipients

You can set the audience for an API-triggered broadcast in the UI—which is useful when your audience always meets the same conditions.

But you might want to define a custom audience when you trigger your broadcast. For example, you might send “Breaking News” notifications to different groups of users, but the same content layout. We support a complex set of audience filters, so you can broadcast to a specific group of people. We’ve provided a few basic examples below.

 You can nest and and or filters`

Nest filters to create complex filters where you have different sets of and and or criteria that a person must meet to receive your broadcast.

The “And” filter is an array of objects, where each object represents criteria for your audience. Each object must be true for a person to receive the broadcast. You can nest other compound filters—or or not—to set up complex audience conditions.

{
  "recipients": {
    "and": [
      {
        "attribute": {
          "field": "first_name",
          "operator": "exists"
        }
      },
      {
        "attribute": {
          "field": "likes_baseball",
          "operator": "eq",
          "value": true
        }
      }
    ]
  }
}
      • field string
        Required The name of the attribute you want to filter against.
      • operator string
        Required Determine how to evaluate criteria against the field—exists returns results if a person in the audience has the attribute; eq returns results if the audience has the attribute and the attribute has the value you specify.

        Accepted values:eq,exists

      • value string
        The value you want to match for this attribute. You must include a value if you use the eq operator.
    • not
      Returns results if a condition is false. While and/or support an array of items, not supports a single filter object.
      • and array of [ objects ]
        Match all conditions to return results.
    • or array of [ objects ]
      Returns results matching any conditions.
      • id integer
        The ID of the segment you want to return people from.

The “Or” filter is an array of objects where each object represents criteria for your audience. At least one object in the array must be true for a person to receive the broadcast. You can nest other compound filters—and or not—to set up complex audience conditions.

{
  "recipients": {
    "or": [
      {
        "segment": {
          "id": 4
        }
      },
      {
        "attribute": {
          "field": "likes_baseball",
          "operator": "eq",
          "value": true
        }
      }
    ]
  }
}
    • and array of [ objects ]
      Returns results matching all conditions.
      • field string
        Required The name of the attribute you want to filter against.
      • operator string
        Required Determine how to evaluate criteria against the field—exists returns results if a person in the audience has the attribute; eq returns results if the audience has the attribute and the attribute has the value you specify.

        Accepted values:eq,exists

      • value string
        The value you want to match for this attribute. You must include a value if you use the eq operator.
    • not
      Returns results if a condition is false. While and/or support an array of items, not supports a single filter object.
      • and array of [ objects ]
        Match all conditions to return results.
      • id integer
        The ID of the segment you want to return people from.

A condition that, if true, excludes people from your audience. The not filter is an object, but can take a complex filter, like and or or.

{
  "recipients": {
    "not": {
      "and": [
        {
          "segment": {
            "id": 3
          }
        },
        {
          "attribute": {
            "field": "likes_baseball",
            "operator": "eq",
            "value": true
          }
        }
      ]
    }
  }
}
    • and array of [ objects ]
      Returns results matching all conditions.
      • field string
        Required The name of the attribute you want to filter against.
      • operator string
        Required Determine how to evaluate criteria against the field—exists returns results if a person in the audience has the attribute; eq returns results if the audience has the attribute and the attribute has the value you specify.

        Accepted values:eq,exists

      • value string
        The value you want to match for this attribute. You must include a value if you use the eq operator.
    • not
      Returns results if a condition is false. While and/or support an array of items, not supports a single filter object.
      • and array of [ objects ]
        Match all conditions to return results.
    • or array of [ objects ]
      Returns results matching any conditions.
      • id integer
        The ID of the segment you want to return people from.

A ID of a segment that people must belong to.

{
  "recipients": {
    "segment": {
      "id": 3
    }
  }
}
  • id integer
    The ID of the segment you want to return people from.

Filter your audience based on an attribute value. In this case, you’ll provide:

  • field: the name of the attribute
  • operator: One of exists (true if a person has a value) or eq (true if a person matches a value).
  • value: Required if you use the eq operator. The value a person’s attribute must equal (eq) for the condition to be true.
{
  "recipients": {
    "attribute": {
      "field": "likes_baseball",
      "operator": "eq",
      "value": true
    }
  }
}
  • field string
    Required The name of the attribute you want to filter against.
  • operator string
    Required Determine how to evaluate criteria against the field—exists returns results if a person in the audience has the attribute; eq returns results if the audience has the attribute and the attribute has the value you specify.

    Accepted values:eq,exists

  • value string
    The value you want to match for this attribute. You must include a value if you use the eq operator.

Specify recipients with segments

Find your segment ID You’ll need the numerical ID for each segment you’d like to target. This can be found in the UI by hovering over the segment info icon in the Segment Overview:

image.png
image.png

Or on the individual segment page:

image.png
image.png

Then, you can use it to define or override recipients with JSON that looks like this:

{
  "data": {
    "headline": "Roadrunner spotted in Albuquerque!",
    "date": "January 24, 2018",
    "text": "We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "recipients": {
    "segment": {
          "id": 3
        }
  }
}

Using multiple segment IDs

Here, you’ll need to format a boolean expression of segment IDs in JSON, like this:

"recipients": {
  "or": [
    {
      "segment": {
        "id": 3
      }
    },
    {
      "segment": {
        "id": 4
      }
    }
  ]
}

This would target people who belong to either segment 7 or 8. Use and if you’d like to target people in both segments.

Specify recipients with attributes

In addition to segment IDs, you can also specify or override recipients with attribute conditions. These accept two operators: eq and exists. Note that you’ll need to separate the operator and value into separate entries!

{
  "data": {
    "headline": "Roadrunner spotted in Albuquerque!",
    "date": "January 24, 2018",
    "text": "We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "recipients": {
    "attribute": {
        "field": "interest",
        "operator": "eq",
        "value": "roadrunners"
    }
  }
}

If you need an is not equal or does not exist condition, use the not operator on an eq/exists attribute condition.. Here is an example with a not operator:

{
  "data": {
    "headline": "Roadrunner spotted in Albuquerque!",
    "date": "January 24, 2018",
    "text": "We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "recipients": {
    "not": {
      "attribute": {
        "field": "interest",
        "operator": "eq",
        "value": "roadrunners"
      }
    }
  }
}

Combining segments and attributes

Alternately, you can use a combination of segment and attribute conditions, using the general syntax above. Here’s an example of how to do that, with some simple data to go with it:

{
  "data":{
    "headline":"Roadrunner spotted in Albuquerque!",
    "date":"January 24, 2018",
    "text":"We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "recipients": {
    "and": [
      {
        "segment": {
          "id": 3
        }
      },
      {
        "or": [
          {
            "attribute": {
              "field": "interest",
              "operator": "eq",
              "value": "roadrunners"
            }
          },
          {
            "attribute": {
              "field": "state",
              "operator": "eq",
              "value": "NM"
            }
          },
          {
            "not":{
              "attribute": {
                "field": "species",
                "operator": "eq",
                "value": "roadrunners"
              }
            }
          }
        ]
      }
    ]
  }
}
}

Recipient List

In some situations it might be desirable to specify a list of recipients. These can be provided either through a list of profile ids or a list of email addresses.

Profile IDs

The list of profile ids is provided as a JSON array in the attribute ids.

  • You can send up to 10,000 ids in one API call. Sending more than that will result in an error is returned to the caller.
  • If any of the profile ids in this array do not correspond to an existing profile’s id attribute in Customer.io then the trigger API returns an error to the caller unless the boolean attribute id_ignore_missing is set to true, in which case the missing ids are ignored. Here’s an example of how to do that, with some simple data to go with it:
{
  "data":{
    "headline":"Roadrunner spotted in Albuquerque!",
    "date":"January 24, 2018",
    "text":"We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "ids": ["wiley", "roadrunner", "acme"],
  "id_ignore_missing": true
}

Email Addresses

The list of emails addresses is provided as a JSON array in the attribute emails.

  • You can send up to 10,000 emails in one API call. Sending more than that will result in an error is returned to the caller.
  • If any of the email addresses in this array do not correspond to an existing profile’s email attribute in Customer.io then the trigger API returns an error to the caller unless the boolean attribute email_ignore_missing is set to true, in which case missing emails are ignored. If the data that you are sending contains customers that might not exist in Customer.io application then this is the attribute to use.
  • If any of the email addresses in this array corresponds to multiple profile ids the trigger API returns an error to the caller unless the boolean attribute email_add_duplicates is set to true, in which case all matching customers are added as recipients. Warning: be careful as this means that the same email address will be mailed multiple times.

Here’s an example:

{
  "data":{
    "headline":"Roadrunner spotted in Albuquerque!",
    "date":"January 24, 2018",
    "text":"We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "emails": ["wiley@coyote.com", "road@runner.net", "support@acme.com"],
  "email_ignore_missing": true,
  "email_add_duplicates": true
}

To see the implication of email_add_duplicates and email_add_duplicates, for the sake of an example, let’s assume that your Customer.io account has multiple profiles that have the same value for their email attribute but different values for their id attribute.

  • If the email_ignore_missing is set to true then emails you included that are missing in your Customer.io account will be ignored.
  • If email_add_duplicates is set to true then multiple emails will be sent.

Let’s say you have the following data in your Customer.io account:

id: 1
email:  wiley@coyote.com

id: 2
email:  wiley@coyote.com

id: 3
email:  john@coyote.com

And you send the following JSON data as part of your API call:

{
  "data":{
    "headline":"Roadrunner spotted in Albuquerque!",
    "date":"January 24, 2018",
    "text":"We've received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
  },
  "emails": ["wiley@coyote.com", "john@coyote.com", "matt@coyote.com"],
  "email_ignore_missing": true,
  "email_add_duplicates": true
}

In that case a total of three emails will be sent. Two to wiley@coyote.com and one to john@coyote.com. Whereas matt@coyote.com will be ignored.

Including custom data

If you want to specify a list of recipients but also include custom data for them (for example, a voucher code), you can include a per_user_data attribute (for up to 10,000 recipients) or a data_file_url attribute. Custom data included in this way is available in the {{trigger.<attribute_name>}} space when building your message content, in exactly the same way as data provided in the global data block specified above. If an attribute is specified in both the global block and in the custom block, the value from the custom block will be used for each customer for which it is provided.

  • If per_user_data or data_file_url is specified, the recipients, ids, and emails fields must not be present in the API request.
  • per_user_datashould contain an array of JSON objects where each object contains an identifier (id or email depending on your workspace settings) and data values. Below is an example using per_user_data.

 IMPORTANT: Remove linebreaks and collapse per_user_data

You must collapse/uglify your per_user_data to prevent errors, as in the example below.

{
    "data": {
        "headline": "Roadrunner spotted in Albuquerque!",
        "date": 1511315635,
        "text": "We received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
    },
    "per_user_data":[{"id":"wiley","data":{"voucher_code":"FESwYm"}},{"email":"road@runner.net","data":{"voucher_code":"cYm6XJ"}}]
}

For data_file_url, the URL provided must be an http or https URL. We recommend using an https server for hosting any files containing sensitive customer information. If the file server requires user/password authentication, the values for those must be provided in the URL, like this: https://user:pass@myserver.com/myfile. The URL must point at a file that contains one json map per line, with each of those maps being either {"id":xxxx,"data":xxxx} or {"email":xxxx,"data":xxxx}. We will download and process the file from the URL, and progress for that process will be visible in the status, with the following new fields:

  • found_per_user_data - whether per_user_data was found in the data file
  • per_user_data_position - the position to which we have processed (in bytes) in the data file
  • per_user_data_error_count - the number of errors recorded so far while processing the data file

Here is an example using data_file_url:

{
    "data": {
        "headline": "Roadrunner spotted in Albuquerque!",
        "date": 1511315635,
        "text": "We received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!"
    },
    "data_file_url": "https://s3.amazonaws.com/awesometown/upsell_runners.json"
}

and this is what you’d see when checking the status for the trigger:

{
    "id": "5-37",
    "campaign_id": 5,
    "created_at": 1552523326,
    "recipients_filter": "{\"segment\":{\"id\":80}}",
    "data": "{\n        \"headline\": \"Roadrunner spotted in Albuquerque!\",\n        \"date\": 1511315635,\n        \"text\": \"We received reports of a roadrunner in your immediate area! Head to your dashboard to view more information!\"\n    }",
    "processed_at": 1552523331,
    "recipients_count": 3000,
    "workflow_action_ids": [],
    'per_user_data_position': 16100,
    'found_per_user_data': True,
    'per_user_data_error_count': 0
}

If errors are encountered while processing the data file or the values from the per_user_data block, the GET API endpoint provides a way to page through the list of errors using the start and limit request parameters. If a request returns a non-zero next attribute, specifying that value as the start value in the next request will return the next page of errors.

Example:

{
    "errors": [
        "line 1: couldn't parse json data",
        "line 2: couldn't parse json data",
        "line 3: couldn't parse json data",
        "line 4: couldn't parse json data",
        "line 5: couldn't parse json data",
        "line 6: couldn't parse json data",
        "the following ids are missing: coyottee, crocodile"
    ],
    "next": 0
}

If there are no errors found while processing the file, the broadcast will start automatically as soon as processing of the file has been completed. If the data file or the per_user_data block may contain ids that are not tracked in Customer.io or emails that don’t correspond to profiles that are tracked in Customer.io, you may specify the id_ignore_missing or email_ignore_missing fields in the request to allow the broadcast to ignore the errors and allow the broadcast to continue. The email_add_duplicates flag may also be used. Once again, be careful with this option, as it means that the same person may receive multiple copies of the broadcast.

Copied to clipboard!
  Contents
Is this page helpful?