# Customer.io

> Drive Customer.io from a workflow: create and update people, track the events that set automations off, read a person's profile, segments, activity and every message they have been sent, own manual segments and their membership. Works with Customer.io accounts in either region.

App · Marketing Automation · 18 actions. Web page: https://docs.lodol.com/docs/integrations/customerio

## Actions

### Add people to a segment

Put people into a manual segment, up to 1000 at a time. Only manual segments are listed, because a data-driven segment's members are decided by its conditions and Customer.io refuses to change them. Everyone in the list has to be the same kind of identifier - Customer.io ignores the ones that are not, without reporting it.

**Inputs**

- Manual segment (`segment_id`, text, required): The manual segment to change. Only manual segments are listed: Customer.io refuses membership changes on a data-driven segment, because its members are decided by its conditions.
- People (`identifiers`, list, required): The people to change, up to 1000 per step. They all have to be the same kind of identifier as the field below says - Customer.io silently ignores the ones that are not.
- Identifier type (`identifier_type`, text): Which kind of identifier the list above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `count` (number)
- `identifier_type` (text)
- `identifiers` (list)
- `ok` (true/false)
- `segment_id` (number)

**Example output**

```json
{
  "count": 1,
  "identifier_type": "email",
  "identifiers": [
    "person@example.com"
  ],
  "ok": true,
  "segment_id": 42
}
```

### Count a segment's members

How many people are in one segment. Cheaper than listing them, and the right way to make a workflow wait for a segment to fill up. Membership changes are not instant, so a count taken immediately after adding people can still be the old one.

**Inputs**

- Segment (`segment_id`, text, required): The segment to read. Pick one from the list, or paste a segment ID or the Customer.io URL of the segment.

**Outputs**

- `count` (number)
- `segment_id` (number)

**Example output**

```json
{
  "count": 128,
  "segment_id": 42
}
```

### Create a manual segment

Make an empty manual segment - a list you decide the members of, rather than one Customer.io works out from conditions. Add people to it with 'Add people to a segment'. Data-driven segments can only be created in Customer.io itself, because they are their conditions.

**Inputs**

- Name (`name`, text, required): What to call the segment in Customer.io.
- Description (`description`, text): What the segment is for, shown beside it in Customer.io.

**Outputs**

- `segment` (object)

**Example output**

```json
{
  "segment": {
    "created_at": 1757808000,
    "deduplicate_id": "42:1757808000",
    "description": "People who started a trial this week",
    "id": 42,
    "name": "Trial signups",
    "progress": null,
    "state": "finished",
    "tags": [],
    "type": "manual",
    "updated_at": 1757808000
  }
}
```

### Create or update a person

Save a person and their attributes in Customer.io - their email, plan, company, anything you want to segment or personalise by later. Customer.io creates the person if it has not seen this identifier before, so there is no separate 'create'. One caveat worth knowing: if the person named above and the email or ID below belong to two different people, Customer.io answers 200 and then records an Attribute Update Failure instead of applying the change - so change one identifier at a time.

**Inputs**

- Person (`identifier`, text, required): The person to write to, named the way your workspace identifies people - usually their ID or their email address. Customer.io creates the person if it has not seen this value before.
- Identifier type (`identifier_type`, text): Leave this alone unless the value above is a Customer.io ID (cio_id), which has to be sent in a different form. Everything else is read using your workspace's own identifier setting. One of: `workspace_default` (Whatever your workspace identifies people by), `cio_id` (Customer.io ID (cio_id)).
- Email address (`email`, text): The person's email address. Set this even when your workspace identifies people by ID - it is what Customer.io sends email to.
- ID (`person_id`, text): The person's own ID in your system. Setting it on a person you named by email is how you give them one; changing an ID a person already has only works when you name them by their Customer.io ID above.
- Attributes (`attributes`, object): Everything else to save on the person, as name and value pairs. Customer.io stores text, numbers and true/false, up to 300 attributes per person.
- Signed up (`created_at`, date and time): When this person first became a customer. Customer.io shows it on the profile and segments can use it.
- Unsubscribed (`unsubscribed`, true/false): Turn on to unsubscribe this person from every message. Leave blank to change nothing.
- Anonymous ID (`anonymous_id`, text): The cookie or device ID this person browsed under before they signed up, so their earlier activity joins this profile.
- Only update an existing person (`update_only`, true/false): Turn on when you know the person already exists. It stops a burst of near-simultaneous steps creating two profiles for the same person.
- When this change happened (`timestamp`, date and time): Use when you are replaying something that already happened, so a later update cannot be overwritten by an earlier one that arrives after it.

**Outputs**

- `attributes_set` (number)
- `deleted` (true/false)
- `event` (text)
- `event_type` (text)
- `identifier` (text)
- `ok` (true/false)
- `suppressed` (true/false)

**Example output**

```json
{
  "attributes_set": 3,
  "identifier": "person@example.com",
  "ok": true
}
```

### Delete a person

Remove a person and everything Customer.io holds about them. This does not stop them coming back: any later step that writes to the same identifier creates the person again, which is usually what you want, and occasionally a surprise. Use 'Suppress a person' instead when the identifier must never be usable again.

**Inputs**

- Person (`identifier`, text, required): The person to write to, named the way your workspace identifies people - usually their ID or their email address. Customer.io creates the person if it has not seen this value before.
- Identifier type (`identifier_type`, text): Leave this alone unless the value above is a Customer.io ID (cio_id), which has to be sent in a different form. Everything else is read using your workspace's own identifier setting. One of: `workspace_default` (Whatever your workspace identifies people by), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `attributes_set` (number)
- `deleted` (true/false)
- `event` (text)
- `event_type` (text)
- `identifier` (text)
- `ok` (true/false)
- `suppressed` (true/false)

**Example output**

```json
{
  "deleted": true,
  "identifier": "person@example.com",
  "ok": true
}
```

### Find people by email

Look people up by email address and get their Customer.io ID back. This is the step that turns something a person typed into an identifier the rest of Customer.io can address, and it is worth using even when you already have an ID - a cio_id works whatever your workspace identifies people by. Several profiles can share an email, so the answer is a list.

**Inputs**

- Email address (`email`, text, required): The email address to search for.

**Outputs**

- `count` (number)
- `email` (text)
- `results` (list)

**Example output**

```json
{
  "count": 1,
  "email": "person@example.com",
  "results": [
    {
      "cio_id": "d9c1f0a2b3",
      "email": "person@example.com",
      "id": "user-1024"
    }
  ]
}
```

### Get a person

Read everything Customer.io holds on one person: their identifiers, every attribute, when each was last changed, their devices, and whether they are unsubscribed. Note that Customer.io returns every attribute as text, including the ones you sent as numbers or true/false.

**Inputs**

- Person (`customer_id`, text, required): The person to read, as their ID, email address, phone number or Customer.io ID. 'Find people by email' returns the cio_id, which every workspace can be addressed by.
- Identifier type (`identifier_type`, text): Which kind of identifier the field above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `phone` (Phone number), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `customer` (object)
- `customer_id` (text)
- `id_type` (text)

**Example output**

```json
{
  "customer": {
    "attributes": {
      "email": "person@example.com",
      "id": "user-1024",
      "plan": "pro"
    },
    "devices": [],
    "id": "user-1024",
    "identifiers": {
      "cio_id": "d9c1f0a2b3",
      "email": "person@example.com",
      "id": "user-1024"
    },
    "timestamps": {
      "email": 1757808000,
      "plan": 1757808100
    },
    "unsubscribed": false
  },
  "customer_id": "person@example.com",
  "id_type": "email"
}
```

### List a person's activity

What one person has done and what has happened to them, newest first - events, page views, attribute changes, and every open, click and bounce. Customer.io guarantees the last 30 days. Filter by the kind of activity, and by event or attribute name for the two kinds that have one.

**Inputs**

- Person (`customer_id`, text, required): The person to read, as their ID, email address, phone number or Customer.io ID. 'Find people by email' returns the cio_id, which every workspace can be addressed by.
- Identifier type (`identifier_type`, text): Which kind of identifier the field above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `phone` (Phone number), `cio_id` (Customer.io ID (cio_id)).
- Kind of activity (`activity_type`, text): Only activity of this kind. The list holds the ones most workflows filter on; Customer.io has around 130 in total, and any of them can be typed in.
- Event or attribute name (`name`, text): Narrow further to one event name, or one attribute name when the kind above is an attribute change.
- Continue from (`start`, text): Read the next page. Pass the 'next' value from a previous run of this step; leave blank for the first page.
- How many (`limit`, number): How many activities to return, 1-1000. Customer.io defaults to 10. From 1 to 1000.

**Outputs**

- `activities` (list)
- `count` (number)
- `customer_id` (text)
- `id_type` (text)
- `next` (text)

**Example output**

```json
{
  "activities": [
    {
      "customer_id": "user-1024",
      "customer_identifiers": {
        "cio_id": "d9c1f0a2b3",
        "email": "person@example.com",
        "id": "user-1024"
      },
      "data": {
        "amount": 4900
      },
      "id": "01H9Z4K0QK7QW3N9VXY2M8B4TS",
      "name": "invoice_paid",
      "timestamp": 1757808000,
      "type": "event"
    }
  ],
  "count": 1,
  "customer_id": "person@example.com",
  "id_type": "email"
}
```

### List a person's deliveries

Everything Customer.io has sent one person, newest first, with the metrics on each. Without a date range it returns the last six months. The timestamps say when a delivery was created in Customer.io, which is not always when it went out.

**Inputs**

- Person (`customer_id`, text, required): The person to read, as their ID, email address, phone number or Customer.io ID. 'Find people by email' returns the cio_id, which every workspace can be addressed by.
- Identifier type (`identifier_type`, text): Which kind of identifier the field above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `phone` (Phone number), `cio_id` (Customer.io ID (cio_id)).
- Channel (`delivery_type`, text): Only deliveries on this channel. One of: `email`, `webhook`, `twilio` (SMS (Twilio)), `whatsapp`, `slack`, `push` (Push notification), `in_app` (In-app message), `live_notification` (Live notification).
- Only deliveries that were (`metric`, text): Only deliveries that reached this state - sent, opened, bounced and so on. One of: `attempted`, `sent`, `delivered`, `opened`, `clicked`, `converted`, `bounced`, `spammed` (Marked as spam), `unsubscribed`, `dropped`, `failed`, `undeliverable`.
- Include drafts (`drafts`, true/false): Also return deliveries that were drafted rather than sent.
- From (`start_ts`, date and time): The earliest delivery to return. Without a window Customer.io returns the last six months. The timestamp is when the delivery was created, not when it was sent.
- To (`end_ts`, date and time): The latest delivery to return.
- Continue from (`start`, text): Read the next page. Pass the 'next' value from a previous run of this step; leave blank for the first page.
- How many (`limit`, number): How many deliveries to return, 1-1000. Customer.io defaults to 50. From 1 to 1000.

**Outputs**

- `count` (number)
- `customer_id` (text)
- `id_type` (text)
- `messages` (list)
- `next` (text)

**Example output**

```json
{
  "count": 1,
  "customer_id": "person@example.com",
  "id_type": "email",
  "messages": [
    {
      "broadcast_id": null,
      "campaign_id": 7,
      "created": 1757808000,
      "customer_id": "user-1024",
      "customer_identifiers": {
        "cio_id": "d9c1f0a2b3",
        "email": "person@example.com",
        "id": "user-1024"
      },
      "id": "01H9Z4K0QK7QW3N9VXY2M8B4TS",
      "metrics": {
        "delivered": 1757808004,
        "sent": 1757808001
      },
      "newsletter_id": null,
      "recipient": "person@example.com",
      "subject": "Your invoice",
      "type": "email"
    }
  ]
}
```

### List a person's segments

The segments one person currently belongs to, manual and data-driven alike. Useful as a condition: check whether someone is in 'Churn risk' before doing anything about it.

**Inputs**

- Person (`customer_id`, text, required): The person to read, as their ID, email address, phone number or Customer.io ID. 'Find people by email' returns the cio_id, which every workspace can be addressed by.
- Identifier type (`identifier_type`, text): Which kind of identifier the field above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `phone` (Phone number), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `count` (number)
- `customer_id` (text)
- `id_type` (text)
- `segments` (list)

**Example output**

```json
{
  "count": 1,
  "customer_id": "person@example.com",
  "id_type": "email",
  "segments": [
    {
      "description": "People who started a trial this week",
      "id": 42,
      "name": "Trial signups"
    }
  ]
}
```

### List a segment's members

One page of the people in a segment, as their identifiers. Read from Customer.io's 'identifiers' rather than its parallel 'ids' list, because a member with no ID appears in that one as an empty string and would be lost. Pass the 'next' value back in to page on.

**Inputs**

- Segment (`segment_id`, text, required): The segment to read. Pick one from the list, or paste a segment ID or the Customer.io URL of the segment.
- Continue from (`start`, text): Read the next page. Pass the 'next' value from a previous run of this step; leave blank for the first page.
- How many (`limit`, number): How many members to return, 1-1000. Customer.io defaults to 1000. From 1 to 1000.

**Outputs**

- `count` (number)
- `identifiers` (list)
- `next` (text)
- `segment_id` (number)

**Example output**

```json
{
  "count": 1,
  "identifiers": [
    {
      "cio_id": "d9c1f0a2b3",
      "email": "person@example.com",
      "id": "user-1024"
    }
  ],
  "segment_id": 42
}
```

### List automations

Every automation in the workspace - what Customer.io's API still calls a campaign - with its state, what starts it and what it does. Read-only on purpose: automations cannot be started through the API, so the way a workflow sets one off is to track the event or set the attribute it waits for.

**Inputs**: None.

**Outputs**

- `campaigns` (list)
- `count` (number)

**Example output**

```json
{
  "campaigns": [
    {
      "actions": [
        {
          "id": 11,
          "type": "email"
        }
      ],
      "active": true,
      "created": 1757721600,
      "deduplicate_id": "7:1757808000",
      "description": "Three emails over the first week",
      "filter_segment_ids": [],
      "id": 7,
      "name": "Welcome series",
      "state": "running",
      "tags": [
        "lifecycle"
      ],
      "type": "event",
      "updated": 1757808000
    }
  ],
  "count": 1
}
```

### List deliveries

One page of everything Customer.io has sent, newest first, filtered by channel, outcome, automation or date. Each delivery carries a 'metrics' object whose entries mark what happened to it. Without a date range the window is the last six months. Pass the 'next' value back in to page on.

**Inputs**

- Channel (`delivery_type`, text): Only deliveries on this channel. One of: `email`, `webhook`, `twilio` (SMS (Twilio)), `whatsapp`, `slack`, `push` (Push notification), `in_app` (In-app message), `live_notification` (Live notification).
- Only deliveries that were (`metric`, text): Only deliveries that reached this state - sent, opened, bounced and so on. One of: `attempted`, `sent`, `delivered`, `opened`, `clicked`, `converted`, `bounced`, `spammed` (Marked as spam), `unsubscribed`, `dropped`, `failed`, `undeliverable`.
- Automation (`campaign_id`, text): Only deliveries from this automation. Pick one from the list or paste its ID.
- Newsletter ID (`newsletter_id`, text): Only deliveries from this newsletter.
- Action ID (`action_id`, text): Only deliveries from one step of an automation. 'List automations' returns these under 'actions'.
- Include drafts (`drafts`, true/false): Also return deliveries that were drafted rather than sent.
- Include tracked responses (`get_tracked_responses`, true/false): Also return the links each recipient clicked and when.
- From (`start_ts`, date and time): The earliest delivery to return. Without a window Customer.io returns the last six months. The timestamp is when the delivery was created, not when it was sent.
- To (`end_ts`, date and time): The latest delivery to return.
- Continue from (`start`, text): Read the next page. Pass the 'next' value from a previous run of this step; leave blank for the first page.
- How many (`limit`, number): How many deliveries to return, 1-1000. Customer.io defaults to 50. From 1 to 1000.

**Outputs**

- `count` (number)
- `messages` (list)
- `next` (text)

**Example output**

```json
{
  "count": 1,
  "messages": [
    {
      "broadcast_id": null,
      "campaign_id": 7,
      "created": 1757808000,
      "customer_id": "user-1024",
      "customer_identifiers": {
        "cio_id": "d9c1f0a2b3",
        "email": "person@example.com",
        "id": "user-1024"
      },
      "id": "01H9Z4K0QK7QW3N9VXY2M8B4TS",
      "metrics": {
        "delivered": 1757808004,
        "sent": 1757808001
      },
      "newsletter_id": null,
      "recipient": "person@example.com",
      "subject": "Your invoice",
      "type": "email"
    }
  ]
}
```

### List segments

Every segment in the workspace with its ID, type and size state. 'type' says whether a segment is manual - the only kind whose membership the API can change.

**Inputs**: None.

**Outputs**

- `count` (number)
- `segments` (list)

**Example output**

```json
{
  "count": 1,
  "segments": [
    {
      "created_at": 1757808000,
      "deduplicate_id": "42:1757808000",
      "description": "People who started a trial this week",
      "id": 42,
      "name": "Trial signups",
      "progress": null,
      "state": "finished",
      "tags": [],
      "type": "manual",
      "updated_at": 1757808000
    }
  ]
}
```

### Remove people from a segment

Take people out of a manual segment, up to 1000 at a time. Unlike adding, this needs the people to have an ID attribute: Customer.io cannot remove someone from a manual segment through the API if your workspace identifies people only by email and they have never been given an ID.

**Inputs**

- Manual segment (`segment_id`, text, required): The manual segment to change. Only manual segments are listed: Customer.io refuses membership changes on a data-driven segment, because its members are decided by its conditions.
- People (`identifiers`, list, required): The people to change, up to 1000 per step. They all have to be the same kind of identifier as the field below says - Customer.io silently ignores the ones that are not.
- Identifier type (`identifier_type`, text): Which kind of identifier the list above holds. Defaults to the ID your workspace identifies people by. One of: `id` (The ID you identify people by), `email` (Email address), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `count` (number)
- `identifier_type` (text)
- `identifiers` (list)
- `ok` (true/false)
- `segment_id` (number)

**Example output**

```json
{
  "count": 1,
  "identifier_type": "id",
  "identifiers": [
    "user-1024"
  ],
  "ok": true,
  "segment_id": 42
}
```

### Suppress a person

Permanently delete a person and block their identifier. This is not a soft flag: the profile is deleted, and every later API call or import that mentions the identifier is ignored without an error. Use it for a deletion request; use 'Create or update a person' with 'Unsubscribed' turned on for someone who just wants no more email.

**Inputs**

- Person (`identifier`, text, required): The person to write to, named the way your workspace identifies people - usually their ID or their email address. Customer.io creates the person if it has not seen this value before.
- Identifier type (`identifier_type`, text): Leave this alone unless the value above is a Customer.io ID (cio_id), which has to be sent in a different form. Everything else is read using your workspace's own identifier setting. One of: `workspace_default` (Whatever your workspace identifies people by), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `attributes_set` (number)
- `deleted` (true/false)
- `event` (text)
- `event_type` (text)
- `identifier` (text)
- `ok` (true/false)
- `suppressed` (true/false)

**Example output**

```json
{
  "identifier": "person@example.com",
  "ok": true,
  "suppressed": true
}
```

### Track an event

Record something a person did, which is how a workflow starts an automation in Customer.io - automations cannot be triggered through the API, they wait for an event, a segment or a date. Only events timestamped within the last 72 hours trigger one. Anything you put in 'Event data' can be used in the message; 'from_address', 'recipient' and 'reply_to' are reserved names that override the automation's own settings.

**Inputs**

- Person (`identifier`, text, required): The person to write to, named the way your workspace identifies people - usually their ID or their email address. Customer.io creates the person if it has not seen this value before.
- Event name (`name`, text, required): What happened, in your own words - 'invoice_paid', 'trial_started'. Reuse the same name every time so an automation can wait for it.
- Identifier type (`identifier_type`, text): Leave this alone unless the value above is a Customer.io ID (cio_id), which has to be sent in a different form. Everything else is read using your workspace's own identifier setting. One of: `workspace_default` (Whatever your workspace identifies people by), `cio_id` (Customer.io ID (cio_id)).
- Kind of event (`event_type`, text): A custom event by default. Page and screen views are Customer.io's own kinds; a screen view also needs the anonymous ID below. One of: `event` (A custom event), `page` (A page view), `screen` (A mobile screen view).
- Event data (`data`, object): Details about what happened, which the message can then use - an invoice number, an amount, a product name.
- Anonymous ID (`anonymous_id`, text): The device's anonymous ID. Required for a screen view; ignored otherwise.
- Idempotency key (`event_id`, text): A unique ID for this event. Send the same one again and Customer.io discards the duplicate, so a workflow that retries cannot send a message twice.
- When it happened (`timestamp`, date and time): Leave blank for now. An event older than 72 hours is recorded but will not trigger an automation.

**Outputs**

- `attributes_set` (number)
- `deleted` (true/false)
- `event` (text)
- `event_type` (text)
- `identifier` (text)
- `ok` (true/false)
- `suppressed` (true/false)

**Example output**

```json
{
  "event": "invoice_paid",
  "event_type": "event",
  "identifier": "person@example.com",
  "ok": true
}
```

### Unsuppress a person

Release a suppressed identifier so it can be used again. It does not bring the person back - the profile that was suppressed is gone - it only makes the identifier available to a later 'Create or update a person'.

**Inputs**

- Person (`identifier`, text, required): The person to write to, named the way your workspace identifies people - usually their ID or their email address. Customer.io creates the person if it has not seen this value before.
- Identifier type (`identifier_type`, text): Leave this alone unless the value above is a Customer.io ID (cio_id), which has to be sent in a different form. Everything else is read using your workspace's own identifier setting. One of: `workspace_default` (Whatever your workspace identifies people by), `cio_id` (Customer.io ID (cio_id)).

**Outputs**

- `attributes_set` (number)
- `deleted` (true/false)
- `event` (text)
- `event_type` (text)
- `identifier` (text)
- `ok` (true/false)
- `suppressed` (true/false)

**Example output**

```json
{
  "identifier": "person@example.com",
  "ok": true,
  "suppressed": false
}
```
