Customer.io Track Customers API

Add, modify, suppress, or unsuppress people (referred to as "customers" in our APIs). You can also use these endpoints to set attributes on people.

Operations 8

PUT /api/v1/customers/{identifier} Add or update a customer #
DELETE /api/v1/customers/{identifier} Delete a customer #
PUT /api/v1/customers/{identifier}/devices Add or update a customer device #
DELETE /api/v1/customers/{identifier}/devices/{device_id} Delete a customer device #
POST /api/v1/customers/{identifier}/suppress Suppress a customer profile #
POST /api/v1/customers/{identifier}/unsuppress Unsuppress a customer profile #
POST /unsubscribe/{delivery_id} Custom unsubscribe handling #
POST /api/v1/merge_customers Merge duplicate people #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/customer-io-track-customers-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

customer-io-track-customers-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  version: 1.0.0
  title: Customer.io Track Track Customers API
  description: "# Overview\n\nOur Track API provides ways to send real-time customer data to your Customer.io workspace including customer identification and event tracking.\n\n# Use our Postman collection\n\nWe've generated a Postman collection to help you get started with our APIs.\n\nIf you fork this collection, you might want to disable the *Watch original collection* option. We automatically update our Postman collection whenever we release changes to our documentation, even if we don't change our APIs—which happens daily! Rather than being flooded with Postman notifications, you can check out our [Release Notes](/release-notes/) for updates to our APIs.\n\n**NOTE**: Postman endpoints default to our US APIs. If you're in our European (EU) region, you'll need to add `-eu` to the server variables (`track_api_url` and `app_api_url`).\n\n[<img src=\"https://run.pstmn.io/button.svg\" alt=\"Run In Postman\" style=\"width: 128px; height: 32px;\">](https://god.gw.postman.com/run-collection/23697545-0f7ae1e8-8177-46fc-808a-2fd363dd52b9?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D23697545-0f7ae1e8-8177-46fc-808a-2fd363dd52b9%26entityType%3Dcollection%26workspaceId%3Db886877f-fc09-475f-84fe-6221a98f4d18#?env%5BCustomer.io%20API%20Environment%5D=W3sia2V5IjoidHJhY2tfYXBpX3VybCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiJ0cmFjay5jdXN0b21lci5pbyIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiYXBwX2FwaV91cmwiLCJ0eXBlIjoiZGVmYXVsdCIsInZhbHVlIjoiYXBpLmN1c3RvbWVyLmlvIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJzaXRlX2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiYXBpX2tleSIsInR5cGUiOiJzZWNyZXQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiYmVhcmVyIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiYnJvYWRjYXN0X2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiaW1wb3J0X2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiZW1haWxfYWRkcmVzcyIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6InN1cHByZXNzaW9uX3R5cGUiLCJ0eXBlIjoiZGVmYXVsdCIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb2xsZWN0aW9uX2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5Ijoic25pcHBldF9uYW1lIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5Ijoid2ViaG9va19pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6InNlbmRlcl9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImV4cG9ydF9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im1lc3NhZ2VfaWQiLCJ0eXBlIjoiZGVmYXVsdCIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJzZWdtZW50X2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibmV3c2xldHRlcl9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImNvbnRlbnRfaWQiLCJ0eXBlIjoiZGVmYXVsdCIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjYW1wYWlnbl9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImFjdGlvbl9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImN1c3RvbWVyX2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoidHJhbnNhY3Rpb25hbF9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6InRyaWdnZXJfaWQiLCJ0eXBlIjoiZGVmYXVsdCIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJmb3JtX2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiaWRlbnRpZmllciIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImRldmljZV9pZCIsInR5cGUiOiJkZWZhdWx0IiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImRlbGl2ZXJ5X2lkIiwidHlwZSI6ImRlZmF1bHQiLCJ2YWx1ZSI6IiIsImVuYWJsZWQiOnRydWV9XQ==)\n\n# Server addresses: US and EU\nCustomer.io hosts services in the United States (US) and European Union. Select the appropriate server address for your region.\n\n| Region | Server Address |\n| :-- | :-- |\n| US | https://track.customer.io |\n| EU | https://track-eu.customer.io |\n\nNote that if your account is in the EU region and you send traffic to our US endpoints, we'll redirect it accordingly but this traffic still passes through US servers and data could be logged in the US.\n\n# Authentication \n\nYou can find all of your API authentication information in your [Account Settings](https://fly.customer.io/settings/api_credentials). Our Tracking API uses HTTP basic authorization. The App API uses bearer authorization, and you can generate tokens supporting different scopes. Each operation in this document references the authorization header it requires.\n\n# v1 vs v2 APIs\n\nMost of the time, when we talk about *The Track API*, we're talking about the v1 API because the v2 API isn't used in any of our libraries and rarely used in libraries built by third parties; it's much more common that you'd encounter the v1 API.\n\nIf you're integrating with Customer.io using one of our libraries, or a third party customer data platform (CDP) like Segment or Rudderstack, you'll be using the v1 API.\n\nThe v2 API is newer and supports two important features that the v1 API doesn't natively support: objects and batching. But, if you're integrating directly with our API, we suggest you use the [Pipelines API](/integrations/api/cdp/). The Pipelines API supports both objects, batching, *and* all of our newest integrations and libraries are based on it.\n\n# Rate Limits\n\nThe Track API has a rate limit of 1000 requests per second for both active data integrations and historical backfill scripts. This limit applies to both our v1 and v2 APIs. \n\nWhile this rate is not strictly enforced, consistently exceeding it may lead to throttling or dropped data, especially during periods of high system load. If we detect a sustained high volume that could impact other customers, we may contact you to help adjust your integration or, in rare cases, temporarily block requests.\n\n**Rate limits are subject to change. We may adjust these thresholds to ensure stable performance for all customers.**\n\nBelow are the payload size limits for the Track API. If any of these limits are too restrictive for your needs, contact support to let us know your situation as we may be able to accommodate special circumstances. \n\n## Customer limits\n\nThese limits apply to people and their attributes, often referred to as \"customers\" in our APIs.\n\n| Data Type | Limit | Description |\n| -- | -- | -- |\n| ID | 150 bytes | Max length of a person's ID value |\n| Attribute Name | 150 bytes | Max length of each attribute name |\n| Attribute Value | 1000 bytes | Max length of attribute values |\n| Unique attributes | 300 | Max number of attributes allowed per person or Identify call |\n\n## Object and relationship limits\n\nObjects (groups) and relationships between people and objects can have their own attributes. Their limits are similar to people (customers).\n\n| Data Type | Limit | Description |\n| -- | -- | -- |\n| Object ID | 150 bytes | Max length of a object's ID |\n| Attribute Names | 150 bytes | Max length of each attribute name |\n| Attribute Values | 1000 bytes | Max length of attribute values |\n| Unique attributes | 300 | Max number of attributes allowed per object or relationship |\n| Total attribute size | 100 Kilobytes | Max size of all attributes associated with an object or relationship |\n\n## Track API Event limits\n\nThese limits apply to events that you'll send with the `/v1/track` call.\n\n| Data Type | Limit | Description |\n| -- | -- | -- |\n| Event Name | 100 bytes | Max length of each event name |\n| Event Data | 100000 bytes | Max length of each event data |\n\n\n## v2 API Limits\n\nThe v2 API has two endpoints, both of which have limits on the total size of requests. \n* `/entity` is limited to requests 32kb or smaller.\n* `/batch` is limited to requests 500kb or smaller.\n  \n  Each of the requests within a batch must also be 32kb or smaller.\n"
servers:
- url: https://track.customer.io
  description: The base URL for the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
- url: https://track-eu.customer.io
  description: The base URL for the Track API (EU region). Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
tags:
- name: Track Customers
  x-displayName: Customers
  description: Add, modify, suppress, or unsuppress people (referred to as "customers" in our APIs). You can also use these endpoints to set attributes on people.
paths:
  /api/v1/customers/{identifier}:
    put:
      operationId: identify
      tags:
      - Track Customers
      summary: Add or update a customer
      parameters:
      - $ref: '#/components/parameters/track_customer_id'
      description: 'Adds or updates a person.


        If your request does _not_ include `cio_id` and the identifiers in the request body do not belong to a person, your request adds a person.


        If a person already exists with the identifier in the request path, your request updates that person. If the identifier in the path does not belong to a person but you use an identifier in your request body that _does_ belong to a person, your request updates the person and assigns them the identifier in the path.


        If the identifier in the path and request body belong to different people, your request may return `200 OK` but produce an *Attribute Update Failure* for the identifier in the payload.


        If you want to update a person''s identifiers after they are set, you must reference them using their `cio_id` in the format `cio_<cio_id_value>`—unless when updating an `email` with the [Allow updates to email using ID](/accounts/workspaces#update-email-with-id) setting enabled. You can get the `cio_id` value from the [App API](/api/#tag/Customers). If your request includes a `cio_id`, we''ll attempt to update that person, including any identifiers in the request. If the `cio_id` does not exist or belongs to a person who was deleted, we''ll drop the request.


        For workspaces using `email` as an identifier, `email` is case-insensitive. The addresses `person@example.com` and `PERSON@example.com` would represent the same person.


        **Tip**: If your workspace identifies people by both `email` and `id`, and you send an identify call with a new `id` but an `email` that already belongs to someone, we update the existing person rather than creating a new one. The existing person gets the new `id`. This is a common source of confusion during testing—if you''re generating new IDs but reusing the same email address, you''re updating one person repeatedly, not creating multiple people.

        '
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              description: 'The body of the request contains key-value pairs representing attributes that you want to assign to, or update for, a person.


                If your request body contains "identifiers" (like `id` or `email`), your request attempts to update that person. If the identifier in the path and identifiers in the request body belong to different people, your request will produce an *Attribute Update Failure*.

                '
              additionalProperties:
                x-additionalPropertiesName: Attributes
                description: Set attributes on customers. Attributes can have string, integer, or boolean values.
                oneOf:
                - type: string
                - type: integer
                - type: boolean
              properties:
                id:
                  type: string
                  description: A customer's ID. You can set a person's ID if you identify them by email (in the path); you can update this value if you identify a person by `cio_id`.
                email:
                  type: string
                  format: email
                  description: The email address of the customer.
                anonymous_id:
                  $ref: '#/components/schemas/anonymous_id'
                created_at:
                  type: integer
                  description: The Unix timestamp when the user was created.
                _timestamp:
                  type: integer
                  description: The Unix timestamp for when the attribute update occurred. This can be used to control the order of attribute updates when multiple requests are sent in rapid succession.
                _update:
                  type: boolean
                  description: 'If you perform multiple requests in rapid succession when you create a person, there''s a danger that you could create multiple profiles. If you know that a profile already exists and you want to update it, set `_update:true`, and Customer.io will _not_ create a new profile, even if the `identifier` in the path isn''t found.


                    If the identifiers in your path or request don''t belong to an existing person, the request produces a *Failed Attribute Change* event in your activity log.

                    '
                cio_relationships:
                  $ref: '#/components/schemas/v1_cio_relationships'
                unsubscribed:
                  type: boolean
                  description: If true, a person is unsubscribed from all messages. If false, or absent, a person is eligible to receive messages as determined by their `cio_subscription_preferences`. Like subscription preferences, this attribute is automatically set or updated when a person clicks the "unsubscribe" link in your emails. We support any case of true (i.e. TRUE, true, tRUe, etc.), 1, or "1" to represent unsubscribed. Any other value is considered “false”, or subscribed.
                cio_subscription_preferences:
                  description: Stores your audience's subscription preferences if you enable our [subscription center](/journeys/channels/subscriptions/center/) feature. These items are set automatically when people use the unsubscribe link in your messages, but you can set preferences outside the subscription flow. To update select topic preferences while preserving those set for other topics, use JSON dot notation `"cio_subscription_preferences.topics.topic_<topic ID>":<boolean>`.
                  type: object
                  properties:
                    topics:
                      type: object
                      description: Contains active topics in your workspace, named `topic_<id>`.
                      additionalProperties:
                        x-additionalPropertiesName: topic_<id>
                        description: Each property is a boolean named `topic_<id>`. Topic `id` values begin at `1` and increment for each new topic. You can find your topic ids in [Workspace Settings](https://fly.customer.io/workspaces/last/settings/subscription_center/topics) or by querying our [App API](https://customer.io/api/app/#operation/getTopics). For each boolean, `true` means that a person is subscribed to the topic; false means they are unsubscribed. An empty or missing value reverts to the default preference for the topic (opt-in or opt-out).
                        type: boolean
            example:
              email: customer@example.com
              created_at: 1361205308
              first_name: Bob
              plan: basic
              cio_relationships:
                action: add_relationships
                relationships:
                - identifiers:
                    object_type_id: '1'
                    object_id: 01H5Q5SZVQDJ71SBME2SMDXS88
                  relationship_attributes:
                    role: admin
                - identifiers:
                    object_type_id: '2'
                    object_id: 1171SBME
                  relationship_attributes:
                    role: viewer
              cio_subscription_preferences:
                topics:
                  topic_1: true
                  topic_2: true
                  topic_3: false
      responses:
        '200':
          $ref: '#/components/responses/200'
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - lang: json
        label: JSON
        source: "{\n  \"email\": \"customer@example.com\",\n  \"created_at\": 1361205308,\n  \"first_name\": \"Bob\",\n  \"plan\": \"basic\",\n  \"cio_relationships\": {\n    \"action\": \"add_relationships\",\n    \"relationships\": [\n      {\n        \"identifiers\": {\n          \"object_type_id\": \"1\",\n          \"object_id\": \"01H5Q5SZVQDJ71SBME2SMDXS88\"\n        },\n        \"relationship_attributes\": {\n          \"role\": \"admin\"\n        }\n      },\n      {\n        \"identifiers\": {\n          \"object_type_id\": \"2\",\n          \"object_id\": \"1171SBME\"\n        },\n        \"relationship_attributes\": {\n          \"role\": \"viewer\"\n        }\n      }\n    ]\n  },\n  \"cio_subscription_preferences\": {\n    \"topics\": {\n      \"topic_1\": true,\n      \"topic_2\": true,\n      \"topic_3\": false\n    }\n  }\n}"
      - label: Node.js (SDK)
        lang: javascript + Node.js
        source: "const { TrackClient, RegionUS } = require('customerio-node');\nlet cio = new TrackClient(siteId, apiKey, { region: RegionUS });\n\ncio.identify(5, {\n  email: 'customer@example.com',\n  created_at: 1361205308,\n  first_name: 'Bob',\n  plan: 'basic'\n});\n"
      - label: Ruby (SDK)
        lang: ruby
        source: "$customerio = Customerio::Client.new(\"YOUR SITE ID\", \"YOUR API SECRET KEY\", region: Customerio::Regions::US)\n\n$customerio.identify(\n  :id => 5,\n  :email => \"bob@example.com\",\n  :created_at => customer.created_at.to_i,\n  :first_name => \"Bob\",\n  :plan => \"basic\"\n)\n"
      - label: Python (SDK)
        lang: python
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          cio.identify(id="5", email=''customer@example.com'', name=''Bob'', plan=''premium'')

          '
      - label: Go (SDK)
        lang: go
        source: "track := customerio.NewTrackClient(\"YOUR SITE ID\", \"YOUR API SECRET KEY\", customerio.WithRegion(customerio.RegionUS))\n\nif err := track.Identify(\"5\", map[string]interface{}{\n  \"email\": \"bob@example.com\",\n  \"created_at\": time.Now().Unix(),\n  \"first_name\": \"Bob\",\n  \"plan\": \"basic\",\n}); err != nil {\n  // do something with error\n}\n"
    delete:
      parameters:
      - $ref: '#/components/parameters/track_customer_id'
      summary: Delete a customer
      operationId: delete
      description: 'Deleting a customer removes them, and all of their information, from Customer.io.


        **NOTE**: Calls that update customers by ID can also create a customer. If you send data to Customer.io through other means (like the Javascript snippet), after you delete a customer, you may accidentally recreate the customer. You cannot delete a customer using the Javascript snippet alone.

        '
      tags:
      - Track Customers
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      responses:
        '200':
          $ref: '#/components/responses/200'
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - label: Node.js (SDK)
        lang: javascript + Node.js
        source: 'const { TrackClient, RegionUS } = require(''customerio-node'');

          let cio = new TrackClient(siteId, apiKey, { region: RegionUS });


          // Depending on your workspace settings, the id (5) may be an email address.

          cio.destroy(5);

          '
      - label: Ruby (SDK)
        lang: ruby
        source: '$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", region: Customerio::Regions::US)


          // Depending on your workspace settings, the id (5) may be an email address.

          $customerio.delete(5)

          '
      - label: Python (SDK)
        lang: python
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          // Depending on your workspace settings, the customer_id may be an email address.

          cio.delete(customer_id="5")

          '
      - label: Go (SDK)
        lang: go
        source: "track := customerio.NewTrackClient(\"YOUR SITE ID\", \"YOUR API SECRET KEY\", customerio.WithRegion(customerio.RegionUS))\n\n// Depending on your workspace settings, the id (5) may be an email address.\nif err := track.Delete(\"5\"); err != nil {\n  // do something with error\n}\n"
  /api/v1/customers/{identifier}/devices:
    parameters:
    - $ref: '#/components/parameters/track_customer_id'
    put:
      operationId: add_device
      summary: Add or update a customer device
      description: Customers can have more than one device. Use this method to add iOS and Android devices to, or update devices for, a customer profile.
      tags:
      - Track Customers
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - device
              description: Define the device you want to add to the customer profile.
              properties:
                device:
                  $ref: '#/components/schemas/device_object'
      responses:
        '200':
          $ref: '#/components/responses/200'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - lang: json
        label: JSON
        source: "{\n  \"device\": {\n    \"id\": \"string\",\n    \"platform\": \"ios\"\n  }\n}"
      - label: Node.js (SDK)
        lang: javascript
        source: 'const { TrackClient, RegionUS } = require(''customerio-node'');

          let cio = new TrackClient(siteId, apiKey, { region: RegionUS });


          // Depending on your workspace settings, the id (5) may be an email address.

          cio.addDevice(5, "device_id", "ios", { primary: true });

          '
      - lang: Ruby
        source: '$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", region: Customerio::Regions::US)


          // Depending on your workspace settings, the id (5) may be an email address.

          $customerio.add_device(5, "my_ios_device_id", "ios")

          $customerio.add_device(5, "my_android_device_id", "android")

          '
      - lang: Python (3)
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          // Depending on your workspace settings, the customer_id may be an email address.

          cio.add_device(customer_id="1", device_id=''device_hash'', platform=''ios'', last_used=1514764800})

          '
      - lang: Go
        source: "track := customerio.NewTrackClient(\"YOUR SITE ID\", \"YOUR API SECRET KEY\", customerio.WithRegion(customerio.RegionUS))\n\n// Depending on your workspace settings, the id (5) may be an email address.\nif err := track.AddDevice(\"5\", \"messaging token\", \"android\", map[string]interface{}{\n  \"last_used\": time.Now().Unix(),\n}) err != nil {\n  // do something with error\n}\n"
  /api/v1/customers/{identifier}/devices/{device_id}:
    parameters:
    - $ref: '#/components/parameters/track_customer_id'
    - $ref: '#/components/parameters/device_id'
    delete:
      operationId: delete_device
      summary: Delete a customer device
      description: Remove a device from a customer profile. If you continue sending data about a device to Customer.io, you may inadvertently re-add the device to the customer profile.
      tags:
      - Track Customers
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      responses:
        '200':
          $ref: '#/components/responses/200'
        '400':
          description: Invalid or malformed request.
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      errors:
                        type: array
                        description: An array of errors.
                        items:
                          type: string
                          description: Error descriptions.
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - label: Node.js (SDK)
        lang: javascript
        source: 'const { TrackClient, RegionUS } = require(''customerio-node'');

          let cio = new TrackClient(siteId, apiKey, { region: RegionUS });


          // Depending on your workspace settings, the id (5) may be an email address.

          cio.deleteDevice(5, "device_token")

          '
      - lang: Ruby
        source: '$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", region: Customerio::Regions::US)


          // Depending on your workspace settings, the id (5) may be an email address.

          $customerio.delete_device(5, "my_device_token")

          '
      - lang: Python (3)
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          // Depending on your workspace settings, the customer_id may be an email address.

          cio.delete_device(customer_id="5", device_id=''device_hash'')

          '
      - lang: Go
        source: "track := customerio.NewTrackClient(\"YOUR SITE ID\", \"YOUR API SECRET KEY\", customerio.WithRegion(customerio.RegionUS))\n\n// Depending on your workspace settings, the id (5) may be an email address.\nif err := track.DeleteDevice(\"5\", \"messaging-token\"); err != nil {\n  // do something with error\n}\n"
  /api/v1/customers/{identifier}/suppress:
    parameters:
    - $ref: '#/components/parameters/track_customer_id'
    post:
      operationId: suppress
      summary: Suppress a customer profile
      description: 'Delete a customer profile and prevent the person''s identifier(s) from being re-added to your workspace. Any future API calls or operations referencing the specified ID are ignored. If you suppress a person in a workspace that identifies people by *email or ID* and both identifiers are set, both the person''s email and ID are suppressed.


        <div class="fly-panel bg-warning">

        <div class="fly-panel-body">

        <p class="callout-head text--bold text-warning mrg-t-none"><svg class="api-icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.4127 13.3333L9.18133 1.43333C8.95116 0.994094 8.49623 0.718884 8.00033 0.718884C7.50444 0.718884 7.04951 0.994094 6.81933 1.43333L0.587332 13.3333C0.370821 13.7467 0.386147 14.2431 0.627743 14.6423C0.869339 15.0415 1.30205 15.2854 1.76867 15.2853H14.2313C14.698 15.2854 15.1307 15.0415 15.3723 14.6423C15.6139 14.2431 15.6292 13.7467 15.4127 13.3333ZM7.33333 5.61533C7.33333 5.24714 7.63181 4.94867 8 4.94867C8.36819 4.94867 8.66667 5.24714 8.66667 5.61533V9.61533C8.66667 9.98352 8.36819 10.282 8 10.282C7.63181 10.282 7.33333 9.98352 7.33333 9.61533V5.61533ZM8.01466 13.2887H8.03333C8.29806 13.2844 8.54988 13.1735 8.73182 12.9812C8.91376 12.7888 9.01044 12.5312 9 12.2667C8.97854 11.7209 8.53019 11.2893 7.984 11.2887H7.96533C7.70125 11.2935 7.4502 11.4043 7.26865 11.5961C7.0871 11.788 6.99029 12.0447 7 12.3087C7.02073 12.8546 7.46838 13.2869 8.01466 13.2887Z" /></svg>&nbsp;This API permanently deletes people</p>

        <div class="text-warning"><p>Suppressing a person way deletes their profile <i>and</i> suppresses the identifier you reference in the path of this call, preventing you from re-adding a person using the same identifier (until you unsuppress the identifier). You cannot recover a profile after you suppress it. In general, should use this API sparingly—for GDPR/CCPA requests, etc. </p>

        <p>If you want to keep a record of a person but prevent them from receiving messages, you should set the person''s unsubscribed attribute (or use other attributes to represent complex subscription preferences) instead.</p></div>

        </div>

        </div>

        '
      tags:
      - Track Customers
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      responses:
        '200':
          $ref: '#/components/responses/200'
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - label: Node.js (SDK)
        lang: javascript
        source: 'const { TrackClient, RegionUS } = require(''customerio-node'');

          let cio = new TrackClient(siteId, apiKey, { region: RegionUS });


          // Depending on your workspace settings, the id (5) may be an email address.

          cio.suppress(5)

          '
      - lang: Ruby
        source: '$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", region: Customerio::Regions::US)


          // Depending on your workspace settings, the id (5) may be an email address.

          $customerio.suppress(5)

          '
      - lang: Python (3)
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          // Depending on your workspace settings, customer_id may be an email address.

          cio.suppress(customer_id="5")

          '
  /api/v1/customers/{identifier}/unsuppress:
    parameters:
    - $ref: '#/components/parameters/track_customer_id'
    post:
      operationId: unsuppress
      summary: Unsuppress a customer profile
      description: 'Unsuppressing a profile allows you to add the customer back to Customer.io. If you unsuppress a person in a workspace that identifies people by *email or ID* and the suppressed person had both an email and ID, both the person''s email and ID are unsuppressed.


        Unsuppressing a profile does not recreate the profile that you previously suppressed. Rather, it just makes the identifier available again. Identifying a person after unsuppressing them creates a new profile, with none of the history of the previously suppressed identifier.

        '
      tags:
      - Track Customers
      servers:
      - url: https://track.customer.io
        description: This endpoint is a part of the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password.
      security:
      - Tracking-API-Key: []
      responses:
        '200':
          $ref: '#/components/responses/200'
        '401':
          $ref: '#/components/responses/401'
      x-codeSamples:
      - lang: Ruby
        source: '$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", region: Customerio::Regions::US)


          // Depending on your workspace settings, the id (5) may be an email address.

          $customerio.unsuppress(5)

          '
      - lang: Python (3)
        source: 'from customerio import CustomerIO, Regions

          cio = CustomerIO(site_id, api_key, region=Regions.US)


          // Depending on your workspace settings, customer_id may be an email address.

          cio.unsuppress(customer_id="5")

          '
  /unsubscribe/{delivery_id}:
    parameters:
    - $ref: '#/components/parameters/delivery_id'
    post:
      operationId: unsubscribe
      summary: Custom unsubscribe handling
      description: 'This endpoint lets you set a global unsubscribed status outside of the subscription pathways

# --- truncated at 32 KB (49 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/customer-io/refs/heads/main/openapi/customer-io-track-customers-api-openapi.yml