Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
version: 1.0.0
title: Customer.io App Sender Identities 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: Sender Identities
description: Return information about your senders—the addresses that you send messages from—including usage information for your different senders.
paths:
/v1/sender_identities:
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
- name: sort
in: query
description: Determine how you want to sort results, `asc` for chronological order and `desc` for reverse chronological order.
required: false
schema:
type: string
enum:
- asc
- desc
- name: hidden
in: query
required: false
description: If true, include hidden senders in the results.
schema:
type: boolean
get:
summary: List sender identities
operationId: listSenders
security:
- Bearer-Auth: []
description: Returns a list of senders in your workspace. Senders are who your messages are "from".
tags:
- Sender Identities
responses:
'200':
description: Returns an array of `sender_identities`.
content:
application/json:
schema:
type: object
properties:
sender_identities:
type: array
items:
x-scalar-ignore: true
type: object
description: Information about a sender.
properties:
id:
type: integer
description: The identifier of a sender.
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
name:
type: string
description: The name of the sender.
email:
type: string
description: The email address of the sender.
address:
type: string
description: The sender name and email address in the format `name <name@example.com>`.
template_type:
type: string
enum:
- email
- phone
description: The type of sender.
auto_generated:
type: boolean
description: If true, the sender is automatically generated by Customer.io.
phone:
type: string
description: The phone number of the sender, used for SMS senders.
hidden:
type: boolean
description: If true, the sender is hidden in the Customer.io UI.
example:
id: 4534
deduplicate_id: 4534:1478035647
name: Cher Ami
email: test@example.com
address: Cher Ami <test@example.com>
template_type: email
auto_generated: false
next:
x-scalar-ignore: true
type: string
description: Indicates the next page of results. Add `?start=<next_value>` to the request to get the next page of results.
'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/sender_identities"
- 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/sender_identities\",\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/sender_identities")
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/sender_identities")
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/sender_identities\"\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/sender_identities/{sender_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: sender_id
in: path
required: true
description: The identifier of a sender.
schema:
type: integer
get:
summary: Get a sender
operationId: getSender
security:
- Bearer-Auth: []
description: Returns information about a specific sender.
tags:
- Sender Identities
responses:
'200':
description: Returns the `sender_identity` you requested.
content:
application/json:
schema:
type: object
properties:
sender_identity:
x-scalar-ignore: true
type: object
description: Information about a sender.
properties:
id:
type: integer
description: The identifier of a sender.
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
name:
type: string
description: The name of the sender.
email:
type: string
description: The email address of the sender.
address:
type: string
description: The sender name and email address in the format `name <name@example.com>`.
template_type:
type: string
enum:
- email
- phone
description: The type of sender.
auto_generated:
type: boolean
description: If true, the sender is automatically generated by Customer.io.
phone:
type: string
description: The phone number of the sender, used for SMS senders.
hidden:
type: boolean
description: If true, the sender is hidden in the Customer.io UI.
example:
id: 4534
deduplicate_id: 4534:1478035647
name: Cher Ami
email: test@example.com
address: Cher Ami <test@example.com>
template_type: email
auto_generated: false
'404':
description: The sender 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/sender_identities/{sender_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/sender_identities/%7Bsender_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/sender_identities/%7Bsender_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/sender_identities/%7Bsender_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/sender_identities/%7Bsender_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/sender_identities/{sender_id}/used_by:
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: sender_id
in: path
required: true
description: The identifier of a sender.
schema:
type: integer
get:
summary: Get sender usage data
operationId: getSenderUsage
security:
- Bearer-Auth: []
description: Returns lists of the campaigns and newsletters that use a sender.
tags:
- Sender Identities
responses:
'200':
description: Returns arrays of campaigns and newsletters.
content:
application/json:
schema:
type: object
properties:
campaigns:
type: array
description: The campaigns that use the sender.
items:
type: integer
sent_newsletters:
type: array
description: The newsletters you've sent that used the sender.
items:
type: integer
draft_newsletters:
type: array
description: The newsletter drafts that are set up using the sender.
items:
type: integer
'404':
description: The sender 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/sender_identities/{sender_id}/used_by"
- 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/sender_identities/%7Bsender_id%7D/used_by\",\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/sender_identities/%7Bsender_id%7D/used_by")
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/sender_identities/%7Bsender_id%7D/used_by")
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/sender_identities/%7Bsender_id%7D/used_by\"\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}"
components:
securitySchemes:
Bearer-Auth:
type: http
scheme: bearer
description: 'The App API uses a bearer authentication scheme.
You can generate a bearer token, known as an **App API Key**, with a defined scope in [your account settings](https://fly.customer.io/settings/api_credentials?keyType=app). [Learn more about bearer authorization in Customer.io](/accounts/settings/managing-credentials).
'
ServiceAccount-Auth:
x-scalar-ignore: true
type: http
scheme: bearer
bearerFormat: sa_live_
description: 'Transactional send endpoints (`/v1/send/email`, `/v1/send/push`, `/v1/send/sms`, `/v1/send/in_app`, `/v1/send/inbox_message`) also accept a service-account bearer token, prefixed with `sa_live_`. Service-account tokens work across workspaces, so you must pass the target workspace as the `X-Workspace-Id` header on each request.
Service-account tokens are intended for testing and one-off sends—for example, using the Customer.io CLI with an AI agent like Claude to verify that a transactional message renders correctly before wiring it into your production backend. **For the production integration that triggers the message from your application, use an App API Key instead**: it''s workspace-scoped, easier to rotate, and has a smaller blast radius.
Service-account tokens are server-side credentials. Treat them like any API key—keep them in environment variables or a secret manager, and never embed them in client-side code, mobile apps, or other untrusted contexts.
'
bearerAuth:
type: http
scheme: bearer
description: API key passed as a Bearer token