openapi: 3.2.0 info: version: 1.0.0 title: Customer.io App Messages API description: Our App API provides ways to trigger messages and retrieve information about people, campaigns, broadcasts, and more. servers: - url: https://api.customer.io description: The base URL for broadcasts, transactional messages, and data-retrieval APIs. These endpoints use bearer authorization, and require a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). - url: https://api-eu.customer.io description: The base URL for broadcasts, transactional messages, and data-retrieval APIs (EU region). These endpoints use bearer authorization, and require a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). tags: - name: Messages description: Return information about message and webhook "deliveries"—the instance of a message or webhook intended for an individual recipient. paths: /v1/messages: servers: - url: https://api.customer.io description: This API uses bearer authorization, requiring a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). parameters: - name: start in: query required: false description: The token for the page of results you want to return. Responses contain a `next` property. Use this property as the `start` value to return the next page of results. schema: type: string - name: limit in: query required: false description: The maximum number of results you want to retrieve per page. schema: type: integer default: 50 maximum: 1000 - name: type in: query required: false description: The type of item you want to return metrics for. When empty, the response contains metrics for all possible types. schema: type: string enum: - email - webhook - twilio - whatsapp - slack - push - in_app - live_notification - name: metric in: query required: false description: Determines the metric(s) you want to return. schema: type: string enum: - attempted - sent - delivered - opened - clicked - converted - bounced - spammed - unsubscribed - dropped - failed - undeliverable - name: drafts in: query required: false description: If true, your request returns drafts rather than active/sent messages. schema: type: boolean - name: campaign_id in: query required: false description: The campaign you want to filter for. schema: type: integer - name: newsletter_id in: query required: false description: The newsletter you want to filter for. schema: type: integer - name: action_id in: query required: false description: The action you want to filter for. schema: type: integer - name: start_ts in: query required: false description: The beginning timestamp for your query. schema: type: integer format: unix timestamp - name: end_ts in: query required: false description: The ending timestamp for your query. schema: type: integer format: unix timestamp - name: get_tracked_responses in: query required: false description: If true, the response includes `tracked_responses` for each message—an object containing tracked response option names for in-app survey responses. schema: type: boolean default: false get: summary: List messages operationId: listMessages security: - Bearer-Auth: [] description: 'Return a list of deliveries, including metrics for each delivery, for messages in your workspace. The request body contains filters determining the deliveries you want to return information about. Use the `start_ts` and `end_ts` parameters to find messages within a time range. We limit your requests to 6 months. If your request doesn''t include `start_ts` and `end_ts` parameters, we''ll return the most recent 6 months of deliveries. If `start_ts` is greater than 6-months before `end_ts`, we only send back 6 months of data. If only `end_ts` is specified, we return 6 months of data before this timestamp. If only `start_ts` is specified, we then set the `end_ts` to the current time and deliver 6 months of data prior to this timestamp. Timestamps reflect when deliveries were created in our system, not when they were actually sent to recipients. There may be a delay between creation and sending.' tags: - Messages responses: '200': description: Returns an array of message objects. content: application/json: schema: type: object properties: messages: type: array description: Each object in the array describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. items: x-scalar-ignore: true description: Describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. allOf: - x-scalar-ignore: true type: object description: Describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. properties: id: x-scalar-ignore: true description: The identifier for a delivery—the instance of a message intended for an individual recipient. type: string readOnly: true example: dgOq6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: x-scalar-ignore: true type: string readOnly: true description: An identifier in the format `id:timestamp` where the id is for the object you're working with (Campaigns, Deliveries, Exports, Identities, Newsletters, Segments, and Templates), and the timestamp is the last time the object was updated. example: 15:1492548073 message_template_id: x-scalar-ignore: true description: The identifier of the message template used to create a message. type: integer readOnly: true deprecated: true customer_id: x-scalar-ignore: true type: - string - 'null' description: The ID of a customer profile, analogous to a "person" in the UI. If your workspace supports multiple identifiers (email and ID), this value can be null. example: '42' customer_identifiers: x-scalar-ignore: true type: object description: Identifiers for the person in a response—`id`, `cio_id`, and `email`. Unset `id` or `email` values are `null`. We recommend this object over the less descriptive `customer_id`. This object doesn't include `phone`, even if your workspace uses phone numbers as an identifier; look for the person's `phone` attribute instead. required: - email - id - cio_id properties: email: type: - string - 'null' format: email description: A person's email address, if set. example: test@example.com id: type: - string - 'null' description: A person's unique ID, if set. This is the same as the `customer_id` if present. example: 2 cio_id: x-scalar-ignore: true type: string description: A unique identifier set by Customer.io, used to reference a person if you want to update their identifiers. example: a3000001 recipient: x-scalar-ignore: true description: The recipient address for an action. type: string example: '{{customer.email}}' subject: x-scalar-ignore: true type: string description: The subject line for an `email` action. example: Did you get that thing I sent you? metrics: x-scalar-ignore: true type: object description: Metrics for an individual instance of a message; each item in the object represents the timestamp when a message achieved a particular metric. This object only contains metrics that have been recorded. properties: bounced: type: integer description: The timestamp when the message `bounced`. clicked: type: integer description: The timestamp when the message was `clicked`. human_clicked: type: integer description: The number of `clicked` messages excluding machine clicks. This metric is reliable starting April 20, 2025. [Learn more](/journeys/metrics/analytics/#delivery-metrics). prefetch_clicked: type: integer description: The number of `clicked` messages attributed to machines. This metric is reliable starting April 20, 2025. converted: type: integer description: The timestamp when the message was `converted`. created: type: integer description: The timestamp when the message was `created`. delivered: type: integer description: The timestamp when the message was `delivered`. drafted: type: integer description: The timestamp when the message was `drafted`. dropped: type: integer description: The timestamp when the message was `dropped`. failed: type: integer description: The timestamp when the message `failed`. opened: type: integer description: The timestamp when the message was `opened`. human_opened: type: integer description: The number of `opened` messages excluding machine opens. This metric is reliable starting March 20, 2025. [Learn more](/journeys/metrics/analytics/#delivery-metrics). prefetch_opened: type: integer description: The number of `opened` messages attributed to machines. This metric is reliable starting March 20, 2025. sent: type: integer description: The timestamp when the message was `sent`. spammed: type: integer description: The timestamp when the message was marked as spam. undeliverable: type: integer description: The timestamp when the message became `undeliverable`. unsubscribed: type: integer description: The timestamp when a person unsubscribed based on this message. created: x-scalar-ignore: true type: integer format: unix timestamp description: The date time when the referenced ID was created. example: 1552341937 readOnly: true failure_message: type: - string - 'null' description: Explains why a message failed, if applicable. campaign_id: oneOf: - x-scalar-ignore: true description: The identifier for a campaign. type: integer example: 5 - type: 'null' action_id: x-scalar-ignore: true description: The identifier for an action. type: integer readOnly: true example: 96 parent_action_id: x-scalar-ignore: true type: integer description: The ID of the parent action, if the action occurred within a campaign and has a parent (like a randomized split, etc). example: 1 readOnly: true newsletter_id: oneOf: - x-scalar-ignore: true description: The identifier for a newsletter. type: integer example: 10 - type: 'null' content_id: x-scalar-ignore: true description: The identifier for a message in a newsletter. Newsletters can have multiple content IDs (for multi-language messages or A/B tests). type: integer readOnly: true example: 1 broadcast_id: oneOf: - x-scalar-ignore: true type: integer description: The identifier for a broadcast. example: 2 - type: 'null' trigger_event_id: x-scalar-ignore: true type: string description: The id of the event that triggered an event-triggered campaign (not an API-triggered broadcast). example: 21E4C3CT6YDC7Y4N7FE1GWWABC forgotten: type: boolean description: If true message contents are not retained by Customer.io. tracked_responses: type: object description: Tracked in-app survey responses, keyed by response option name. Present only when `get_tracked_responses` is `true`. additionalProperties: type: object properties: id: type: integer description: The identifier for the tracked response. ts: type: integer description: A unix timestamp representing when the response was tracked. example: cool-button: id: 1 ts: 1715769600 cool-button-2: id: 2 ts: 1715769600 - type: object properties: type: x-scalar-ignore: true description: The type of message or action for a delivery, campaign action, or related object. Includes channels that newsletters do not support (for example, `slack` and `whatsapp`). type: string enum: - email - webhook - twilio - push - in_app - slack - whatsapp - live_notification readOnly: true example: email example: id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek=:1619137768 msg_template_id: 43 action_id: 215 parent_action_id: null customer_id: null recipient: person@example.com subject: Did you get that thing I sent you? metrics: delivered: 1619137768 sent: 1619137768 created: 1619137767 failure_message: null newsletter_id: null content_id: null campaign_id: 23 broadcast_id: null trigger_event_id: null type: email forgotten: false examples: email: summary: An email message value: messages: - id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek=:1619137768 msg_template_id: 43 action_id: 215 parent_action_id: null customer_id: null recipient: person@example.com subject: Did you get that thing I sent you? metrics: delivered: 1619137768 sent: 1619137768 created: 1619137767 failure_message: null newsletter_id: null content_id: null campaign_id: 23 broadcast_id: null trigger_event_id: null type: email forgotten: false in-app: summary: An in-app message with tracked survey responses value: messages: - id: bX2r7YZq8RCAAB5_DGopeWY8nGlEcSGv8fl= deduplicate_id: bX2r7YZq8RCAAB5_DGopeWY8nGlEcSGv8fl=:1715769500 msg_template_id: 87 action_id: 312 parent_action_id: null customer_id: user_2048 recipient: user_2048 subject: null metrics: opened: 1715769550 sent: 1715769500 created: 1715769500 failure_message: null newsletter_id: null content_id: null campaign_id: 45 broadcast_id: null trigger_event_id: null type: in_app forgotten: false tracked_responses: how-satisfied: id: 1 ts: 1715769560 would-recommend: id: 2 ts: 1715769565 '400': description: The request was malformed. '429': description: Your request is over the 10-per-second limit. x-codeSamples: - lang: Shell + Curl source: "curl --request GET \\\n --header 'Authorization: Bearer REPLACE_BEARER_TOKEN' \\\n --url https://api.customer.io/v1/messages" - lang: Node + Native source: "const http = require(\"https\");\n\nconst options = {\n \"method\": \"GET\",\n \"hostname\": \"api.customer.io\",\n \"port\": null,\n \"path\": \"/v1/messages\",\n \"headers\": {}\n};\n\nconst req = http.request(options, function (res) {\n const chunks = [];\n\n res.on(\"data\", function (chunk) {\n chunks.push(chunk);\n });\n\n res.on(\"end\", function () {\n const body = Buffer.concat(chunks);\n console.log(body.toString());\n });\n});\n\nreq.end();" - lang: Ruby + Native source: 'require ''uri'' require ''net/http'' require ''openssl'' url = URI("https://api.customer.io/v1/messages") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(url) response = http.request(request) puts response.read_body' - lang: Python + Python3 source: 'import http.client conn = http.client.HTTPSConnection("api.customer.io") conn.request("GET", "/v1/messages") res = conn.getresponse() data = res.read() print(data.decode("utf-8"))' - lang: Go + Native source: "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.customer.io/v1/messages\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" /v1/messages/{message_id}: servers: - url: https://api.customer.io description: This API uses bearer authorization, requiring a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). parameters: - name: message_id in: path required: true description: The identifier of a message. schema: type: string - name: get_tracked_responses in: query required: false description: If true, the response includes `tracked_responses` for each message—an object containing tracked response option names for in-app survey responses. schema: type: boolean default: false get: summary: Get a message operationId: getMessage security: - Bearer-Auth: [] description: Return a information about, and metrics for, a delivery—the instance of a message intended for an individual recipient person. tags: - Messages responses: '200': description: Returns a message object. content: application/json: schema: type: object description: Describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. properties: message: x-scalar-ignore: true description: Describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. allOf: - x-scalar-ignore: true type: object description: Describes an individual message delivery. The object contains keys for all possible parents of the message (`newsletter_id`, `broadcast_id`, etc) but only the parents of the delivery are populated. Other parent IDs are null. properties: id: x-scalar-ignore: true description: The identifier for a delivery—the instance of a message intended for an individual recipient. type: string readOnly: true example: dgOq6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: x-scalar-ignore: true type: string readOnly: true description: An identifier in the format `id:timestamp` where the id is for the object you're working with (Campaigns, Deliveries, Exports, Identities, Newsletters, Segments, and Templates), and the timestamp is the last time the object was updated. example: 15:1492548073 message_template_id: x-scalar-ignore: true description: The identifier of the message template used to create a message. type: integer readOnly: true deprecated: true customer_id: x-scalar-ignore: true type: - string - 'null' description: The ID of a customer profile, analogous to a "person" in the UI. If your workspace supports multiple identifiers (email and ID), this value can be null. example: '42' customer_identifiers: x-scalar-ignore: true type: object description: Identifiers for the person in a response—`id`, `cio_id`, and `email`. Unset `id` or `email` values are `null`. We recommend this object over the less descriptive `customer_id`. This object doesn't include `phone`, even if your workspace uses phone numbers as an identifier; look for the person's `phone` attribute instead. required: - email - id - cio_id properties: email: type: - string - 'null' format: email description: A person's email address, if set. example: test@example.com id: type: - string - 'null' description: A person's unique ID, if set. This is the same as the `customer_id` if present. example: 2 cio_id: x-scalar-ignore: true type: string description: A unique identifier set by Customer.io, used to reference a person if you want to update their identifiers. example: a3000001 recipient: x-scalar-ignore: true description: The recipient address for an action. type: string example: '{{customer.email}}' subject: x-scalar-ignore: true type: string description: The subject line for an `email` action. example: Did you get that thing I sent you? metrics: x-scalar-ignore: true type: object description: Metrics for an individual instance of a message; each item in the object represents the timestamp when a message achieved a particular metric. This object only contains metrics that have been recorded. properties: bounced: type: integer description: The timestamp when the message `bounced`. clicked: type: integer description: The timestamp when the message was `clicked`. human_clicked: type: integer description: The number of `clicked` messages excluding machine clicks. This metric is reliable starting April 20, 2025. [Learn more](/journeys/metrics/analytics/#delivery-metrics). prefetch_clicked: type: integer description: The number of `clicked` messages attributed to machines. This metric is reliable starting April 20, 2025. converted: type: integer description: The timestamp when the message was `converted`. created: type: integer description: The timestamp when the message was `created`. delivered: type: integer description: The timestamp when the message was `delivered`. drafted: type: integer description: The timestamp when the message was `drafted`. dropped: type: integer description: The timestamp when the message was `dropped`. failed: type: integer description: The timestamp when the message `failed`. opened: type: integer description: The timestamp when the message was `opened`. human_opened: type: integer description: The number of `opened` messages excluding machine opens. This metric is reliable starting March 20, 2025. [Learn more](/journeys/metrics/analytics/#delivery-metrics). prefetch_opened: type: integer description: The number of `opened` messages attributed to machines. This metric is reliable starting March 20, 2025. sent: type: integer description: The timestamp when the message was `sent`. spammed: type: integer description: The timestamp when the message was marked as spam. undeliverable: type: integer description: The timestamp when the message became `undeliverable`. unsubscribed: type: integer description: The timestamp when a person unsubscribed based on this message. created: x-scalar-ignore: true type: integer format: unix timestamp description: The date time when the referenced ID was created. example: 1552341937 readOnly: true failure_message: type: - string - 'null' description: Explains why a message failed, if applicable. campaign_id: oneOf: - x-scalar-ignore: true description: The identifier for a campaign. type: integer example: 5 - type: 'null' action_id: x-scalar-ignore: true description: The identifier for an action. type: integer readOnly: true example: 96 parent_action_id: x-scalar-ignore: true type: integer description: The ID of the parent action, if the action occurred within a campaign and has a parent (like a randomized split, etc). example: 1 readOnly: true newsletter_id: oneOf: - x-scalar-ignore: true description: The identifier for a newsletter. type: integer example: 10 - type: 'null' content_id: x-scalar-ignore: true description: The identifier for a message in a newsletter. Newsletters can have multiple content IDs (for multi-language messages or A/B tests). type: integer readOnly: true example: 1 broadcast_id: oneOf: - x-scalar-ignore: true type: integer description: The identifier for a broadcast. example: 2 - type: 'null' trigger_event_id: x-scalar-ignore: true type: string description: The id of the event that triggered an event-triggered campaign (not an API-triggered broadcast). example: 21E4C3CT6YDC7Y4N7FE1GWWABC forgotten: type: boolean description: If true message contents are not retained by Customer.io. tracked_responses: type: object description: Tracked in-app survey responses, keyed by response option name. Present only when `get_tracked_responses` is `true`. additionalProperties: type: object properties: id: type: integer description: The identifier for the tracked response. ts: type: integer description: A unix timestamp representing when the response was tracked. example: cool-button: id: 1 ts: 1715769600 cool-button-2: id: 2 ts: 1715769600 - type: object properties: type: x-scalar-ignore: true description: The type of message or action for a delivery, campaign action, or related object. Includes channels that newsletters do not support (for example, `slack` and `whatsapp`). type: string enum: - email - webhook - twilio - push - in_app - slack - whatsapp - live_notification readOnly: true example: email example: id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek=:1619137768 msg_template_id: 43 action_id: 215 parent_action_id: null customer_id: null recipient: person@example.com subject: Did you get that thing I sent you? metrics: delivered: 1619137768 sent: 1619137768 created: 1619137767 failure_message: null newsletter_id: null content_id: null campaign_id: 23 broadcast_id: null trigger_event_id: null type: email forgotten: false examples: email: summary: An email message value: message: id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= deduplicate_id: ag1q6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek=:1619137768 msg_template_id: 43 action_id: 215 parent_action_id: null customer_id: null recipient: person@example.com subject: Did you get that thing I sent you? metrics: delivered: 1619137768 sent: 1619137768 created: 1619137767 failure_message: null newsletter_id: null content_id: null campaign_id: 23 broadcast_id: null trigger_event_id: null type: email forgotten: false in-app: summary: An in-app message with tracked survey responses value: message: id: bX2r7YZq8RCAAB5_DGopeWY8nGlEcSGv8fl= deduplicate_id: bX2r7YZq8RCAAB5_DGopeWY8nGlEcSGv8fl=:1715769500 msg_template_id: 87 action_id: 312 parent_action_id: null customer_id: user_2048 recipient: user_2048 subject: null metrics: opened: 1715769550 sent: 1715769500 created: 1715769500 failure_message: null newsletter_id: null content_id: null campaign_id: 45 broadcast_id: null trigger_event_id: null type: in_app forgotten: false tracked_responses: how-satisfied: id: 1 ts: 1715769560 would-recommend: id: 2 ts: 1715769565 '404': description: The message does not exist. '429': description: Your request is over the 10-per-second limit. x-codeSamples: - lang: Shell + Curl source: "curl --request GET \\\n --header 'Authorization: Bearer REPLACE_BEARER_TOKEN' \\\n --url https://api.customer.io/v1/messages/{message_id}" - lang: Node + Native source: "const http = require(\"https\");\n\nconst options = {\n \"method\": \"GET\",\n \"hostname\": \"api.customer.io\",\n \"port\": null,\n \"path\": \"/v1/messages/%7Bmessage_id%7D\",\n \"headers\": {}\n};\n\nconst req = http.request(options, function (res) {\n const chunks = [];\n\n res.on(\"data\", function (chunk) {\n chunks.push(chunk);\n });\n\n res.on(\"end\", function () {\n const body = Buffer.concat(chunks);\n console.log(body.toString());\n });\n});\n\nreq.end();" - lang: Ruby + Native source: 'require ''uri'' require ''net/http'' require ''openssl'' url = URI("https://api.customer.io/v1/messages/%7Bmessage_id%7D") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(url) response = http.request(request) puts response.read_body' - lang: Python + Python3 source: 'import http.client conn = http.client.HTTPSConnection("api.customer.io") conn.request("GET", "/v1/messages/%7Bmessage_id%7D") res = conn.getresponse() data = res.read() print(data.decode("utf-8"))' - lang: Go + Native source: "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.customer.io/v1/messages/%7Bmessage_id%7D\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" /v1/messages/{message_id}/archived_message: servers: - url: https://api.customer.io description: This API uses bearer authorization, requiring a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). parameters: - name: message_id in: path required: true description: The identifier of a message. schema: type: string get: summary: Get an archived message operationId: getArchivedMessage security: - Bearer-Auth: [] description: Returns the archived copy of a delivery, including the message body, recipient, and metrics. This endpoint is limited to 100 requests per day. tags: - Messages responses: '200': description: Returns the archived message object. content: application/json: schema: type: object description: Describes an archived message delivery. properties: archived_message: x-scalar-ignore: true description: 'An archived message, including a complete message body. ' type: object properties: id: x-scalar-ignore: true description: The identifier for a delivery—the instance of a message intended for an individual recipient. type: string readOnly: true example: dgOq6QWq6QUBAAF4_CGoeVX7mFkDbRFu7ek= body: type: string description: The body of the variant. You cannot modify the body if you created it with our drag-and-drop editor. example:
\n