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
Parameter
Type
Description
phone_number_id
UUID
Unique 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:
Header
Description
X-RateLimit-Limit
Maximum outbound SMS allowed per number per 24 hours (20 on the default campaign)
X-RateLimit-Remaining
Remaining sends in the current window
X-RateLimit-Reset
ISO 8601 timestamp at which the oldest send in the window will fall off
Retry-After
Seconds until at least one slot frees up (only on 429 responses)
Request body
Field
Type
Required
Description
to
string
Yes
Recipient phone number in E.164 format (for example +15167251294)
text
string
Yes
Message body, 1--1600 characters. Must contain at least one non-whitespace character
Request example
JSON
Response (201)
JSON
Error responses
Status
Description
400
Phone number not active
403
recipient_not_opted_in — recipient has not texted START to a number in your organization
403
recipient_opted_out — recipient texted STOP and can no longer be messaged
403
Send blocked by a contact rule on the sending number
404
Phone number not found
409
sender_sms_pending — local number's 10DLC registration is still propagating (typically clears within 10–15 minutes of provisioning)
409
Sending number is not eligible to send SMS (for example, a toll-free number)
422
Invalid request body
429
24-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
Parameter
Type
Default
Description
limit
integer
50
Number of results (1--200)
offset
integer
0
Pagination offset
is_read
boolean
—
Filter by read state. Omit for all messages
is_blocked
boolean
—
Filter 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)
JSON
Error responses
Status
Description
403
Phone number belongs to a different organization
404
Phone 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
Parameter
Type
Description
text_id
UUID
Unique identifier of the text message
Response (200)
JSON
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
Status
Description
404
Text 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
Parameter
Type
Description
text_id
UUID
Unique identifier of the text message
Request body
Field
Type
Required
Description
is_read
boolean
No
Mark as read (true) or unread (false)
status
string
No
Set to "deleted" to delete the message. No other status value is accepted
Request example
JSON
Response (200)
Returns the updated TextMessage object.
Error responses
Status
Description
404
Text not found, wrong phone number, or wrong organization
422
Invalid 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
Parameter
Type
Default
Description
q
string
—
Search query (required, 1--500 characters)
limit
integer
50
Number of results (1--200)
is_blocked
boolean
—
Filter 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
Status
Description
403
Phone number belongs to a different organization
404
Phone number not found or released
422
Missing 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
Parameter
Type
Default
Description
limit
integer
50
Number of results (1--200)
offset
integer
0
Pagination offset
is_blocked
boolean
—
Filter 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)
JSON
Error responses
Status
Description
403
Phone number belongs to a different organization
404
Phone 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
Parameter
Type
Description
remote_number
string
Remote party's phone number or short code
Query parameters
Parameter
Type
Default
Description
limit
integer
50
Number of results (1--200)
offset
integer
0
Pagination 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.
Bulk-update the read state for all non-deleted messages in a conversation.
Path parameters
Parameter
Type
Description
remote_number
string
Remote party's phone number or short code
Request body
Field
Type
Required
Description
is_read
boolean
Yes
Mark all messages as read (true) or unread (false)
Request example
JSON
Response (200)
JSON
Returns updated_count: 0 when no messages needed updating. That is not an error.
Error responses
Status
Description
403
Phone number belongs to a different organization
404
Phone number not found or released
422
Missing or invalid is_read
Text message object
Field
Type
Description
id
string (UUID)
Message ID
direction
string
"inbound" or "outbound"
local_phone_number
string
Your Inkbox number (E.164)
remote_phone_number
string
The other party's number or short code
text
string | null
Message body. Null for MMS-only messages
type
string
"sms" or "mms"
media
array | null
Media attachments (MMS only). Each item has content_type, size, and url
is_read
boolean
Whether the message has been read
delivery_status
string | null
For outbound messages: "queued", "delivered", "delivery_failed", or "delivery_unconfirmed". Null for inbound
origin
string
How the message was created. "user_initiated" for messages sent via the API
error_code
string | null
Stable error code if delivery failed
error_detail
string | null
Human-readable detail accompanying error_code
sent_at
string (ISO 8601) | null
When the message was handed off for delivery
delivered_at
string (ISO 8601) | null
When delivery was confirmed
failed_at
string (ISO 8601) | null
When delivery failed
is_blocked
boolean
Whether 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