SMS Opt-Ins
Per-recipient SMS consent state for your organization. Consent is keyed by (your org, recipient phone number) — a single recipient can have a different consent state across organizations, but shares one consent state across all phone numbers within your org.
Inkbox automatically updates this registry from inbound STOP / START keywords. These endpoints let you:
- Read the current consent state for one recipient, or list the rows for your org.
- Write consent state directly — but only when your org is on its own active, customer-managed 10DLC campaign. Orgs on the Inkbox-default campaign share consent state across the campaign pool and can't override it programmatically.
Auth. All endpoints require an admin API key, or you can manage opt-in state from the Inkbox Console. Writes additionally require your org to be on its own active, customer-managed 10DLC campaign — see Write access below.
Available on all three distribution paths: the examples below show direct HTTP, the Python SDK (inkbox.sms_opt_ins), the TypeScript SDK (inkbox.smsOptIns), and the CLI (inkbox sms-opt-in).
The opt-in object
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier of the consent row |
organization_id | string | Your organization ID |
receiver_number | string | Recipient phone number in E.164 (for example +15551234567) |
status | string | "opted_in" or "opted_out" |
source | string | How this transition was captured — see Source values |
opted_in_at | string | null | ISO 8601 timestamp of the most recent opt-in; null when status is "opted_out" |
opted_out_at | string | null | ISO 8601 timestamp of the most recent opt-out; null when status is "opted_in" |
created_at | string | ISO 8601 timestamp of the first time consent state was recorded for this recipient |
updated_at | string | ISO 8601 timestamp of the most recent transition |
Source values
| Value | Meaning |
|---|---|
sms | Inbound STOP / START keyword from the recipient |
api | Recorded by your integration calling Opt in / Opt out |
Write access
The write endpoints (POST .../opt-in and POST .../opt-out) are restricted to organizations on their own active, customer-managed 10DLC campaign. The reason: organizations on the Inkbox-default campaign share consent state with every other org on the same campaign, so a programmatic override from one customer would change the consent surface for others.
Once your own brand and campaign are registered and active (see 10DLC registration), both write endpoints unlock automatically. Until then they return 409 with error customer_campaign_required — the read endpoints work either way.
Overrides and precedence
The write endpoints do not enforce a precedence rule between sms-sourced and api-sourced consent. The latest write is what gates outbound sends, regardless of source. In particular, a POST .../opt-in call will succeed even when the row's current state is (status: "opted_out", source: "sms") — i.e. a recipient who texted STOP. The full transition history is preserved per-row in the audit log, so reviewers can always reconstruct when each source touched a recipient.
Because the API will accept an override of a prior STOP, you own the legitimacy of any opt-in you write through it. Inkbox expects you to have a fresh, documented consent artifact (signup form, paper waiver, recorded conversation, etc.) for every opt-in you record this way. The same applies to API opt-outs that override an earlier API opt-in.
List opt-ins GET
GET /sms-opt-insList the consent rows for your organization, ordered by most recently updated first.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | — | Filter by "opted_in" or "opted_out". Omit to return both. |
limit | integer | 50 | Number of results (1--200) |
offset | integer | 0 | Pagination offset |
Response (200)
Code examples
Get opt-in GET
GET /sms-opt-ins/{receiver_number}Look up the consent state for one recipient under your organization.
Path parameters
| Parameter | Type | Description |
|---|---|---|
receiver_number | string | Recipient phone number in E.164 (for example +15551234567) |
Response (200)
Returns the opt-in object for the recipient.
Error responses
| Status | Description |
|---|---|
| 400 | invalid_receiver_number — receiver_number is not valid E.164 |
| 404 | opt_in_not_found — no consent row exists for this recipient under your org |
Code examples
Opt in recipient POST
POST /sms-opt-ins/{receiver_number}/opt-inMark a recipient as opted in. Use this when you've captured consent through your own channel (a signup form, an in-product flow, a paper waiver, etc.) and want the server-side consent gate to reflect that.
Each call appends an audit event with source: "api" and updates the row's status to "opted_in".
Path parameters
| Parameter | Type | Description |
|---|---|---|
receiver_number | string | Recipient phone number in E.164 |
Response (200)
Returns the updated opt-in object.
Error responses
| Status | Description |
|---|---|
| 400 | invalid_receiver_number — receiver_number is not valid E.164 |
| 409 | customer_campaign_required — your org is not on its own active, customer-managed 10DLC campaign; see Write access |
Code examples
Opt out recipient POST
POST /sms-opt-ins/{receiver_number}/opt-outMark a recipient as opted out. Use this to honor an opt-out you collected outside of STOP (for example, by phone or email) so the server-side send gate immediately refuses further texts to this recipient under your org.
Each call appends an audit event with source: "api" and updates the row's status to "opted_out".
Path parameters
| Parameter | Type | Description |
|---|---|---|
receiver_number | string | Recipient phone number in E.164 |
Response (200)
Returns the updated opt-in object.
Error responses
| Status | Description |
|---|---|
| 400 | invalid_receiver_number — receiver_number is not valid E.164 |
| 409 | customer_campaign_required — your org is not on its own active, customer-managed 10DLC campaign; see Write access |