# Send one SMS from a CRM

> Strict single-message endpoint for CRM and automation webhooks. Flat 202 response, required idempotency, sandbox mode and managed live activation.
> Source: https://docs.23telecom.co.uk/sms/integration-send/

Instructions for LLMs: This is one page of the 23 Telecom messaging API docs
(SMS today; more channels planned). Base URL: https://restlink23telecom.com/api/v1,
auth via the X-API-Key header. Match errors on the error_code field, never on
description text. Full docs: https://docs.23telecom.co.uk/llms-full.txt · Schemas: https://docs.23telecom.co.uk/openapi.yaml

Use this endpoint when a CRM or automation platform needs one simple webhook
that sends one SMS and can safely retry after a timeout.

  You can validate the contract immediately with a sandbox `sk_test_...` key.
  When you are ready to launch, your 23 Telecom account manager enables the
  exact workspace and confirms the production key. Existing `/sms/send` and
  `/sms/send-individual` clients are unaffected.

`POST /api/v1/integrations/sms/send` (permission: `sms.send`)

## Request

Send a strict JSON object with three fields and one stable idempotency key:

```
POST https://restlink23telecom.com/api/v1/integrations/sms/send
Header: X-API-Key: <your key>
Header: Idempotency-Key: crm-event-20260718-001
```
*(The web page shows this example in cURL, Node.js, Python, PHP, Ruby, Java, Go and .NET.)*

| Value | Rule |
| --- | --- |
| `X-API-Key` | Required restricted key with `sms.send`. JWT is not accepted |
| Idempotency | Send exactly one source: `Idempotency-Key` (generic clients, 1–128 characters using letters, numbers, `_`, `-`, `.`, `:`) or Customer.io's automatic `X-CIO-Idempotency-Key` |
| `to` | One E.164 phone number, for example `+447700900123` |
| `message` | Non-empty, maximum 4096 UTF-8 bytes and 10 SMS segments |
| `sender_id` | 3–11 ASCII letters/numbers; cannot start with a number |

The full request body must be at most 32 KiB. Unknown fields, arrays and a
second JSON value are rejected. Do not send `X-Workspace-ID`: the API key is
already bound to the correct workspace.

## Response

```json title="202 Accepted"
{
  "status": "accepted",
  "message_id": "api_7_1784394012896569000_7c6d09d704f37e4b",
  "mode": "live"
}
```

Sandbox keys return the same shape with `mode: "sandbox"` and a `test_...`
message ID. Sandbox acceptance is a simulation and never creates a live SMS.

`accepted` means 23 Telecom durably recorded the live request for delivery. It
does **not** mean the handset received it. Use the returned `message_id` with
[delivery webhooks](https://docs.23telecom.co.uk/webhooks/delivery) or [message status](https://docs.23telecom.co.uk/sms/status).

## Safe retries

Create one `Idempotency-Key` for one logical SMS. If the request times out or
returns `5xx`, retry the exact same body with the same key.

Customer.io supplies `X-CIO-Idempotency-Key` automatically instead. Do not add
either idempotency header manually in Customer.io, and never send both sources.
They use separate internal namespaces, so one source cannot accidentally replay
the other.

- A completed retry returns the same `202` body and message ID with
  `Idempotent-Replayed: true`.
- The replay record is retained for 24 hours.
- Changing `to`, `message` or `sender_id` while reusing the key returns
  `409 IDEMPOTENCY_KEY_REUSED`.
- `409 IDEMPOTENCY_REQUEST_IN_PROGRESS` includes `Retry-After`; wait and retry.
- The legacy `X-Idempotency-Key` is not accepted on this endpoint.

## Production activation

1. Complete the sandbox test with a dedicated `sk_test_...` key.
2. Send your account manager the workspace and CRM/platform name.
3. Your account manager enables integration sending for the workspace and
   confirms the restricted production key.
4. Replace only the key with the confirmed `sk_prod_...` key; the URL and body
   stay the same.

If live access is not enabled, the endpoint returns
`403 INTEGRATION_NOT_ENABLED` and creates no SMS.