Download OpenAPI specification:
The Connext REST API lets you programmatically manage subscribers, send messages, schedule blasts, and view delivery logs for your organization.
All endpoints return JSON and use standard HTTP methods (GET, POST, PATCH, DELETE) with RESTful URL paths.
Every request must include an API key in the Authorization header:
Authorization: Bearer cnxt_your_api_key_here
API keys are scoped to the user who created them. A key inherits the user's organization and permissions — it can only access data within that organization and is limited to the actions the user is allowed to perform.
From the API Key page (accessible via the profile dropdown) you can:
The API returns standard HTTP status codes:
| Status | Meaning |
|---|---|
200 |
Success |
201 |
Resource created |
204 |
Resource deleted (no body) |
400 |
Bad request — missing or invalid parameters |
401 |
Unauthorized — invalid or missing API key |
403 |
Forbidden — valid key but insufficient permissions |
404 |
Not found — resource doesn't exist or is outside your organization |
405 |
Method not allowed |
500 |
Server error |
Error responses include a JSON body:
{
"message": "Description of what went wrong"
}
201 with the created resource.200 with the updated resource.204 with no body.200 with an operation result.List endpoints (GET /subscribers, GET /schedules, GET /logs) accept limit and offset query parameters.
GET /v1/subscribers?limit=25&offset=0
| keyword | string Search across name, phone, email, address |
| group | string Filter by group number |
| sort | string Enum: "phone" "email" "first" "last" |
| order | string Enum: "asc" "desc" |
| limit | integer Default: 10 |
| offset | integer Default: 0 |
[- {
- "id": 0,
- "first": "string",
- "last": "string",
- "phone": "string",
- "type": "sms",
- "enabled": true,
- "address": "string",
- "city": "string",
- "state": "string",
- "zip": "string",
- "email": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "groups": [
- 0
], - "phone_blocked": true,
- "email_blocked": true
}
]| phone required | string^\d{10}$ |
string <email> | |
| first | string |
| last | string |
| address | string |
| city | string |
| state | string |
| zip | string |
| enabled | boolean |
| type | string Enum: "sms" "phone" |
| groups | Array of integers (GroupMembership) An array of group numbers (not IDs) |
{- "phone": "string",
- "email": "user@example.com",
- "first": "string",
- "last": "string",
- "address": "string",
- "city": "string",
- "state": "string",
- "zip": "string",
- "enabled": true,
- "type": "sms",
- "groups": [
- 0
]
}{- "id": 0,
- "first": "string",
- "last": "string",
- "phone": "string",
- "type": "sms",
- "enabled": true,
- "address": "string",
- "city": "string",
- "state": "string",
- "zip": "string",
- "email": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "groups": [
- 0
]
}| id required | integer |
| phone | string^\d{10}$ |
string <email> | |
| first | string |
| last | string |
| address | string |
| city | string |
| state | string |
| zip | string |
| enabled | boolean |
| type | string Enum: "sms" "phone" |
| groups | Array of integers (GroupMembership) An array of group numbers (not IDs) |
{- "phone": "string",
- "email": "user@example.com",
- "first": "string",
- "last": "string",
- "address": "string",
- "city": "string",
- "state": "string",
- "zip": "string",
- "enabled": true,
- "type": "sms",
- "groups": [
- 0
]
}{- "id": 0,
- "first": "string",
- "last": "string",
- "phone": "string",
- "type": "sms",
- "enabled": true,
- "address": "string",
- "city": "string",
- "state": "string",
- "zip": "string",
- "email": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "groups": [
- 0
]
}| recipient required | string 10-digit phone number or email address |
{- "recipient": "string"
}{- "recipient": "string",
- "type": "phone",
- "reason": "string",
- "created_at": "2019-08-24T14:15:22Z"
}Removes blocklist entries for the recipient from your account only (global entries are never affected). Only self-removable reasons can be cleared here: manual (entries you added), invalid (auto-added for an unreachable/bad number), and blocked (auto-added for a carrier block). Opt-out (stop) and email complaint/bounce entries can't be removed via the API — use the removal-request flow instead. This endpoint is idempotent: it returns 204 even when nothing matched.
| recipient required | string 10-digit phone number or email address to unblock |
| reason | string Enum: "manual" "invalid" "blocked" Optional. Remove only entries with this reason. Omit to remove every self-removable entry for the recipient. |
{- "recipient": "string",
- "reason": "manual"
}{- "message": "string"
}Targets groups (groups), individual recipients (recipients), or both — at least one is required. A recipient need not be a subscriber of the account.
Supports file attachments via multipart/form-data. When uploading files, send the JSON parameters in a form field named body and attach files in fields prefixed with media (for SMS/email) or audio (for audio blasts).
| types required | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
| message | string |
| subject | string Email subject line |
| ivr | integer or null ID of the IVR flow to play on outbound audio calls. Omit/null/0 for no IVR. |
| shorten_links | boolean Default: false |
| email_template_id | integer or null If set and |
| from | string^[0-9]{10}$ 10-digit number to send from. Must be a provisioned number on this account. Omit to use the account's primary number. |
Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string | |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| recipients | Array of strings <= 500 items Individual recipients, whether or not they are subscribers of this account. A value containing |
{- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "ivr": 0,
- "shorten_links": false,
- "email_template_id": 0,
- "from": "string",
- "groups": [
- 0
], - "dnc": [
- 0
], - "recipients": [
- "string"
]
}{- "message": "string"
}Sends a preview to the one to five recipients you name — typically yourself — so you can see the message as it will arrive. Groups are not accepted here; use /blasts/send to reach an audience.
Supports the same file upload options as /blasts/send — use multipart/form-data with a body field and file fields prefixed with media or audio.
| types required | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
| message | string |
| subject | string Email subject line |
| ivr | integer or null ID of the IVR flow to play on outbound audio calls. Omit/null/0 for no IVR. |
| shorten_links | boolean Default: false |
| email_template_id | integer or null If set and |
| from | string^[0-9]{10}$ 10-digit number to send from. Must be a provisioned number on this account. Omit to use the account's primary number. |
| recipients required | Array of strings [ 1 .. 5 ] items Who to send the preview to — at least one, at most five. A value containing |
{- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "ivr": 0,
- "shorten_links": false,
- "email_template_id": 0,
- "from": "string",
- "recipients": [
- "string"
]
}{- "message": "string"
}| types required | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string | |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| recipients | Array of strings <= 500 items Individual recipients to price alongside |
| message | string |
| has_media | boolean |
| shorten_links | boolean |
{- "types": [
- "sms"
], - "groups": [
- 0
], - "dnc": [
- 0
], - "recipients": [
- "string"
], - "message": "string",
- "has_media": true,
- "shorten_links": true
}{- "cost": 0
}[- {
- "id": 0,
- "title": "string",
- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "voice_fallback": true,
- "files": [
- {
- "url": "string",
- "name": "string",
- "type": "string",
- "size": 0,
- "key": "string"
}
], - "groups": [
- 0
], - "dnc": [
- 0
], - "shorten_links": true,
- "ivr": 0,
- "email_template_id": 0
}
]Supports file attachments via multipart/form-data. Send the JSON parameters in a body form field and attach files in fields prefixed with media or audio. Same limits as /blasts/send.
| title required | string non-empty |
| types required | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
| message | string |
| subject | string |
| voice_fallback | boolean |
Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string | |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| shorten_links | boolean Default: false |
| ivr | integer or null ID of the IVR flow this template plays. Null for none. |
| email_template_id | integer or null Id of an email template owned by this organization. Stored on the
blast template so that re-loading it restores the selected email
template. Send |
{- "title": "string",
- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "voice_fallback": true,
- "groups": [
- 0
], - "dnc": [
- 0
], - "shorten_links": false,
- "ivr": 0,
- "email_template_id": 0
}{- "id": 0,
- "title": "string",
- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "voice_fallback": true,
- "files": [
- {
- "url": "string",
- "name": "string",
- "type": "string",
- "size": 0,
- "key": "string"
}
], - "groups": [
- 0
], - "dnc": [
- 0
], - "shorten_links": true,
- "ivr": 0,
- "email_template_id": 0
}Supports file attachments via multipart/form-data. Same format as template creation.
| id required | integer |
| title | string non-empty |
| types | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
| message | string |
| subject | string |
| voice_fallback | boolean |
Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string | |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| shorten_links | boolean Default: false |
| ivr | integer or null ID of the IVR flow this template plays. Null for none. |
| email_template_id | integer or null Id of an email template owned by this organization. Stored on the
blast template so that re-loading it restores the selected email
template. Send |
| files | Array of strings URLs of files to retain on the template. Each entry must match a URL already on
the template — send |
{- "title": "string",
- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "voice_fallback": true,
- "groups": [
- 0
], - "dnc": [
- 0
], - "shorten_links": false,
- "ivr": 0,
- "email_template_id": 0,
- "files": [
- "string"
]
}{- "id": 0,
- "title": "string",
- "types": [
- "sms"
], - "message": "string",
- "subject": "string",
- "voice_fallback": true,
- "files": [
- {
- "url": "string",
- "name": "string",
- "type": "string",
- "size": 0,
- "key": "string"
}
], - "groups": [
- 0
], - "dnc": [
- 0
], - "shorten_links": true,
- "ivr": 0,
- "email_template_id": 0
}| keyword | string Search in title or message |
| limit | integer Default: 10 |
| offset | integer Default: 0 |
[- {
- "id": 0,
- "title": "string",
- "subject": "string",
- "message": "string",
- "groups": [
- 0
], - "dnc": [
- 0
], - "types": [
- "sms"
], - "active": true,
- "next": "2019-08-24T14:15:22Z",
- "media": [
- "string"
], - "every": 0,
- "frequency": "minutes",
- "remaining": 0,
- "days": 0,
- "email_template_id": 0
}
]Supports file attachments via multipart/form-data. Same upload format and limits as /blasts/send.
| startDate required | string <date> |
| startTime required | string^\d{1,2}:\d{2}(:\d{2})?$ HH:MM format |
| title required | string non-empty |
| types required | Array of strings (MessageTypes) non-empty Items Enum: "sms" "voice" "email" "audio" |
required | Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| message | string |
| subject | string |
| ivr | integer or null ID of the IVR flow to play on outbound audio calls. Omit/null/0 for no IVR. |
| shorten_links | boolean Default: false |
| frequency | string Enum: "minutes" "hours" "days" "weeks" "months" Makes the schedule recurring |
| every | integer >= 1 Interval for recurrence. Required if frequency is set, and rejected with 400 if it is not. |
| remaining | integer >= 1 Max number of iterations |
| days | integer [ 0 .. 127 ] Day-of-week bitmap, only valid alongside frequency; sending one without a frequency is rejected with 400. A one-time schedule has no cadence to roll to an allowed day, so a day mask on one would leave a schedule that can never fire. |
| email_template_id | integer or null Persisted on the schedule row. Resolved at send time (late binding): edits to the underlying email template take effect on the next firing. |
| from | string^[0-9]{10}$ 10-digit number to send from. Must be a provisioned number on this account. Omit to use the account's primary number. |
{- "startDate": "2019-08-24",
- "startTime": "string",
- "title": "string",
- "types": [
- "sms"
], - "groups": [
- 0
], - "dnc": [
- 0
], - "message": "string",
- "subject": "string",
- "ivr": 0,
- "shorten_links": false,
- "frequency": "minutes",
- "every": 1,
- "remaining": 1,
- "days": 127,
- "email_template_id": 0,
- "from": "string"
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "message": "string",
- "groups": [
- 0
], - "dnc": [
- 0
], - "types": [
- "sms"
], - "active": true,
- "next": "2019-08-24T14:15:22Z",
- "media": [
- "string"
], - "every": 0,
- "frequency": "minutes",
- "remaining": 0,
- "days": 0,
- "email_template_id": 0
}| id required | integer |
| message | string |
| subject | string |
| title | string |
Array of integers or string (GroupNumbers) Groups a message targets: an array of group numbers (not IDs), or the
string | |
| dnc | Array of integers (GroupMembership) An array of group numbers (not IDs) |
| every | integer >= 1 Only valid on a recurring schedule. every, frequency and days are validated against the row as it will be AFTER the patch is applied, so any of the three sent alone is checked against the schedule's current values for the other two. |
| frequency | string Enum: "minutes" "hours" "days" "weeks" "months" Repeat unit. Setting one on a one-time schedule makes it recurring, and requires every in the same request. The reverse is not expressible: this enum has no empty-string member, so a recurring schedule cannot be turned back into a one-time one through the API. |
| remaining | integer |
| active | integer Enum: 0 1 |
| days | integer [ 0 .. 127 ] Day-of-week bitmap. Only valid on a recurring schedule. |
| startDate | string <date> Must be paired with startTime |
| startTime | string^\d{1,2}:\d{2}(:\d{2})?$ Must be paired with startDate |
| email_template_id | integer or null Send |
{- "message": "string",
- "subject": "string",
- "title": "string",
- "groups": [
- 0
], - "dnc": [
- 0
], - "every": 1,
- "frequency": "minutes",
- "remaining": 0,
- "active": 0,
- "days": 127,
- "startDate": "2019-08-24",
- "startTime": "string",
- "email_template_id": 0
}{- "id": 0,
- "title": "string",
- "subject": "string",
- "message": "string",
- "groups": [
- 0
], - "dnc": [
- 0
], - "types": [
- "sms"
], - "active": true,
- "next": "2019-08-24T14:15:22Z",
- "media": [
- "string"
], - "every": 0,
- "frequency": "minutes",
- "remaining": 0,
- "days": 0,
- "email_template_id": 0
}| keyword | string Search in username or message |
| limit | integer Default: 10 |
| offset | integer Default: 0 |
[- {
- "username": "string",
- "id": 0,
- "id_schedule": 0,
- "id_poll": 0,
- "message": "string",
- "date": "2019-08-24T14:15:22Z",
- "types": [
- "sms"
], - "media": [
- "string"
], - "count": 0,
- "recipients": 0,
- "groups": [
- 0
], - "dnc": [
- 0
], - "details": {
- "sms": 0,
- "mms": 0,
- "voice": 0,
- "email": 0,
- "amd": 0,
- "segments": 0,
- "delivered": 0,
- "queued": 0,
- "sent": 0,
- "failed": 0
}
}
]| id required | integer |
| keyword | string Filter by recipient (phone/email) or matched subscriber name |
| status | string Enum: "queued" "sent" "delivered" "failed" "clicked" |
| limit | integer Default: 10 |
| offset | integer Default: 0 |
| getClicks | string Value: "true" Include click counts per recipient |
[- {
- "recipient": "string",
- "name": "string",
- "type": "sms",
- "received": "2019-08-24T14:15:22Z",
- "status": 0,
- "clicks": 0
}
]Every individual message for the account, newest first — inbound replies as well as outbound sends, and non-blast traffic (keyword auto-replies, one-offs) as well as blasts. One row per recipient per message. Contrast with /logs, which returns one aggregated row per blast, and /logs/{id}, which returns the recipients of a single blast.
| keyword | string Filter by recipient (phone/email) or matched subscriber name |
| message_id | string Return only the message with this id — the |
| direction | string Enum: "in" "out" Restrict to inbound or outbound; omit for both |
| dateFrom | string <date> Inclusive lower bound on message date (YYYY-MM-DD) |
| dateTo | string <date> Inclusive upper bound on message date (YYYY-MM-DD) |
| types | string Comma-separated channel filter, e.g. |
| limit | integer Default: 10 Maximum rows to return (capped at 500) |
| offset | integer Default: 0 |
[- {
- "message_id": "string",
- "recipient": "string",
- "name": "string",
- "date": "2019-08-24T14:15:22Z",
- "type": "sms",
- "message": "string",
- "status": "queued",
- "received": "2019-08-24T14:15:22Z",
- "direction": "in"
}
]Sends one message to one recipient — an order confirmation, an appointment
reminder, a password reset. Use /blasts/send to reach an audience.
The recipient does not have to be a subscriber of your account, and the
send is not recorded as a blast, so transactional traffic never appears in
/logs. It does open a conversation thread in the portal's chat inbox, so
a reply from the recipient reaches your staff.
Subject to the account's daily per-channel limit, which this shares with every other send; a message to a blocked recipient is refused.
| to required | string The recipient — a 10-digit phone number, or an email address when |
| type | string Default: "sms" Enum: "sms" "email" Channel to send on. |
| message required | string non-empty |
| subject | string Subject line for an email send. It is not transmitted on an SMS — there it is only quoted onto the chat thread record — so leave it off for SMS. |
| from | string^[0-9]{10}$ 10-digit number to send from. Must be a provisioned number on this account. Omit to continue on the number this conversation last used, falling back to the account's primary. Ignored on an email send. |
{- "to": "string",
- "type": "sms",
- "message": "string",
- "subject": "string",
- "from": "string"
}{- "message": "string",
- "message_id": "string"
}| name required | string^\S+$ Group name. Cannot contain spaces (subscribers text |
| number | integer Auto-assigned if omitted |
| private | boolean Default: false |
{- "name": "string",
- "number": 0,
- "private": false
}{- "id": 0,
- "name": "string",
- "number": 0
}| id required | integer |
| name required | string^\S+$ Group name. Cannot contain spaces (subscribers text |
| number required | integer |
| private | boolean |
{- "name": "string",
- "number": 0,
- "private": true
}{- "id": 0,
- "name": "string",
- "number": 0
}Buys the first number available in the requested area code and adds it to your organization. This is the API equivalent of the portal's two-step search-then-request flow, collapsed into one call for integrations that have no UI to drive.
Purchasing is off by default. It is limited to an allowlist of
organizations maintained by Connext; every account that is not on it gets
403. Contact support to have it enabled.
A successful purchase charges a $5 purchase fee to the default card on
file (any account balance is applied first) and begins the number's monthly
rental. At most one number per hour may be bought on an organization —
a second attempt inside that hour returns 429, as does a request that
arrives while another purchase on the same organization is still running.
A number that was bought and then released still counts against the hour.
The number comes back with status: 1 (ordering). Carrier provisioning and
campaign registration complete out of band over the following minutes, and
the number cannot send until its status reaches 3 — poll GET /numbers
to watch it advance through 2 (campaign pending) to 3 (ready to send).
Buying a number also restarts the organization's 30-day number-change cooldown, which runs from the most recent number acquired.
| area_code required | string^[0-9]{3}$ The 3-digit North American area code to buy in, as a string. |
| label | string <= 50 characters Optional name for the number, returned by |
{- "area_code": "string",
- "label": "string"
}{- "phone": "string",
- "status": 0
}Gives a number back to the carrier and removes it from your organization. This is free and immediate: no fee is charged, and no payment method is required — an organization whose sending is currently disabled can still release a number, since handing one back only reduces what it costs to run.
Like buying, releasing is restricted to organizations Connext has enabled
for multiple numbers, and returns 403 for any other account.
Your organization's primary number cannot be released, which also means an organization can never release its last remaining number. Change the primary from the portal first if you need to give that one up.
Releasing is permanent. The number goes back into the carrier's pool, it stops receiving, and any message history recorded against it stays on the organization.
Because it is permanent, a number is not released while work is still
pointing at it: if messages are queued to go out from it, or scheduled
blasts are set to send from it, the request is refused with 409 and
nothing changes. Let the queue finish, and move or delete those schedules,
then try again. Messages already delivered never block a release.
| phone required | string The number to release. Non-digit characters are stripped before it is matched, so |
{- "message": "string"
}