Skip to content
Inkbox

Inkbox

BlogContactDocs
GuidesAPI Reference

Ctrl K

GuidesAPI Reference

Jump to

Texts

List, search, and manage SMS and MMS text messages for your phone numbers, and send outbound SMS. MMS messages include media attachments returned as presigned URLs.

All text endpoints are scoped to a phone number: /numbers/{phone_number_id}/texts/...

Path parameters

ParameterTypeDescription
phone_number_idUUIDUnique identifier of the phone number

Send text POST

POST /numbers/{phone_number_id}/texts

Send an outbound SMS from one of your phone numbers. The message starts in delivery_status: "queued"; final delivery state is reported via webhook.

Preconditions

  • Local numbers only. Only local (10-digit) numbers can send SMS today — toll-free numbers are receive-only.
  • Sender warm-up. When you provision a new local number, the underlying 10DLC campaign takes around 10–15 minutes to register downstream. The number's sms_status field reports "pending" while that's in flight; calls to send during that window return 409 with error sender_sms_pending. Once sms_status becomes "ready", the number is ready to send.
  • Recipient opt-in. Recipients have to opt in before you can text them: they send START to any number in your organization. Sending to a recipient who hasn't opted in returns 403 with error recipient_not_opted_in. If they later send STOP, future sends to them return 403 recipient_opted_out. Sending to another active phone number that lives in the same organization is allowed without an explicit opt-in.
  • Contact rules configured on the sending number still apply on top of the consent check.

Rate limits

A phone number on Inkbox's default 10DLC campaign can send at most 20 outbound SMS per rolling 24-hour window. Registering your own brand and campaign lifts this cap to the carrier-assigned tier — see 10DLC registration for the full setup. Every send response — both success and failure — includes the standard rate-limit headers so you can pace your traffic:

HeaderDescription
X-RateLimit-LimitMaximum outbound SMS allowed per number per 24 hours (20 on the default campaign)
X-RateLimit-RemainingRemaining sends in the current window
X-RateLimit-ResetISO 8601 timestamp at which the oldest send in the window will fall off
Retry-AfterSeconds until at least one slot frees up (only on 429 responses)

Request body

FieldTypeRequiredDescription
tostringYesRecipient phone number in E.164 format (for example +15167251294)
textstringYesMessage body, 1--1600 characters. Must contain at least one non-whitespace character

Request example

JSONJSON

Response (201)

JSONJSON

Error responses

StatusDescription
400Phone number not active
403recipient_not_opted_in — recipient has not texted START to a number in your organization
403recipient_opted_out — recipient texted STOP and can no longer be messaged
403Send blocked by a contact rule on the sending number
404Phone number not found
409sender_sms_pending — local number's 10DLC registration is still propagating (typically clears within 10–15 minutes of provisioning)
409Sending number is not eligible to send SMS (for example, a toll-free number)
422Invalid request body
42924-hour send limit reached on this number; respect the Retry-After header

List texts GET

GET /numbers/{phone_number_id}/texts

List text messages for a phone number, newest first. Excludes deleted messages.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Number of results (1--200)
offsetinteger0Pagination offset
is_readbooleanFilter by read state. Omit for all messages
is_blockedbooleanFilter by blocked state. true returns only blocked rows, false returns only non-blocked rows, and omitting it applies the caller's default visibility

Identity-scoped API keys never see contact-rule-blocked texts, regardless of is_blocked. Admin API keys and human sessions see blocked and non-blocked texts by default; use is_blocked=true for an admin-side blocked listing.

Response (200)

JSONJSON

Error responses

StatusDescription
403Phone number belongs to a different organization
404Phone number not found or released

Get text GET

GET /numbers/{phone_number_id}/texts/{text_id}

Get a single text message by ID.

Path parameters

ParameterTypeDescription
text_idUUIDUnique identifier of the text message

Response (200)

JSONJSON

MMS messages have type: "mms" and a media array. Each media item includes a content_type, size in bytes, and a presigned url that expires after 1 hour.

Error responses

StatusDescription
404Text not found, wrong phone number, or wrong organization

Update text PATCH

PATCH /numbers/{phone_number_id}/texts/{text_id}

Update a text message. Use this to mark messages as read or to delete them.

Path parameters

ParameterTypeDescription
text_idUUIDUnique identifier of the text message

Request body

FieldTypeRequiredDescription
is_readbooleanNoMark as read (true) or unread (false)
statusstringNoSet to "deleted" to delete the message. No other status value is accepted

Request example

JSONJSON

Response (200)

Returns the updated TextMessage object.

Error responses

StatusDescription
404Text not found, wrong phone number, or wrong organization
422Invalid status value. Only "deleted" is accepted

Search texts GET

GET /numbers/{phone_number_id}/texts/search

Full-text search across text message bodies for a phone number. Results are ranked by relevance and exclude deleted messages.

Query parameters

ParameterTypeDefaultDescription
qstringSearch query (required, 1--500 characters)
limitinteger50Number of results (1--200)
is_blockedbooleanFilter by blocked state. true searches only blocked rows, false searches only non-blocked rows, and omitting it applies the caller's default visibility

Identity-scoped API keys never see contact-rule-blocked texts in search results. Admin API keys and human sessions see everything by default; pass is_blocked=false to exclude blocked spam from search results or is_blocked=true to search only blocked rows.

Response (200)

Returns a list[TextMessage] matching the query.

Error responses

StatusDescription
403Phone number belongs to a different organization
404Phone number not found or released
422Missing or invalid q parameter

List conversations GET

GET /numbers/{phone_number_id}/texts/conversations

List conversation summaries — one row per remote phone number, ordered by most recent message, with the latest message preview and unread count.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Number of results (1--200)
offsetinteger0Pagination offset
is_blockedbooleanFilter by blocked state of messages. true summarizes blocked rows only, false summarizes non-blocked rows only, and omitting it applies the caller's default visibility

With is_blocked=false, latest previews, ordering, unread counts, and totals are computed from non-blocked rows only, so blocked-only counterparties drop out. Identity-scoped API keys never see blocked rows in conversation summaries.

Response (200)

JSONJSON

Error responses

StatusDescription
403Phone number belongs to a different organization
404Phone number not found or released

Get conversation GET

GET /numbers/{phone_number_id}/texts/conversations/{remote_number}

Get all messages exchanged with a specific remote number, newest first. The remote_number can be an E.164 phone number (for example +15167251294) or a short code (for example 76934).

Path parameters

ParameterTypeDescription
remote_numberstringRemote party's phone number or short code

Query parameters

ParameterTypeDefaultDescription
limitinteger50Number of results (1--200)
offsetinteger0Pagination offset

Identity-scoped API keys see only non-blocked rows in the thread. Admin API keys and human sessions see blocked and non-blocked rows merged inline, with each row tagged by is_blocked.

Response (200)

Returns a list[TextMessage] for the conversation.

Error responses

StatusDescription
403Phone number belongs to a different organization
404Phone number not found or released

Update conversation PATCH

PATCH /numbers/{phone_number_id}/texts/conversations/{remote_number}

Bulk-update the read state for all non-deleted messages in a conversation.

Path parameters

ParameterTypeDescription
remote_numberstringRemote party's phone number or short code

Request body

FieldTypeRequiredDescription
is_readbooleanYesMark all messages as read (true) or unread (false)

Request example

JSONJSON

Response (200)

JSONJSON

Returns updated_count: 0 when no messages needed updating. That is not an error.

Error responses

StatusDescription
403Phone number belongs to a different organization
404Phone number not found or released
422Missing or invalid is_read

Text message object

FieldTypeDescription
idstring (UUID)Message ID
directionstring"inbound" or "outbound"
local_phone_numberstringYour Inkbox number (E.164)
remote_phone_numberstringThe other party's number or short code
textstring | nullMessage body. Null for MMS-only messages
typestring"sms" or "mms"
mediaarray | nullMedia attachments (MMS only). Each item has content_type, size, and url
is_readbooleanWhether the message has been read
delivery_statusstring | nullFor outbound messages: "queued", "delivered", "delivery_failed", or "delivery_unconfirmed". Null for inbound
originstringHow the message was created. "user_initiated" for messages sent via the API
error_codestring | nullStable error code if delivery failed
error_detailstring | nullHuman-readable detail accompanying error_code
sent_atstring (ISO 8601) | nullWhen the message was handed off for delivery
delivered_atstring (ISO 8601) | nullWhen delivery was confirmed
failed_atstring (ISO 8601) | nullWhen delivery failed
is_blockedbooleanWhether the message was rejected by a contact rule or by default-block in whitelist mode. Identity-scoped API keys never receive rows where this is true
created_atstring (ISO 8601)Creation timestamp
updated_atstring (ISO 8601)Last update timestamp

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Texts