---
title: "Send an outbound SMS (queued; delivered asynchronously)"
method: POST
path: "/v1/sms/send"
tags: ["sms"]
---

# Send an outbound SMS (queued; delivered asynchronously)

`POST /v1/sms/send`

## Request body

- SendSmsRequest — Body for ``POST /v1/sms/send``. ``agent_id`` is required — the outbound-context helper enforces both agent-↔-number authorization and the org's destination-country allowlist. Conversation + session are resolved (or created) server-side from the ``from``/``to`` pair so callers stay stateless. ``idempotency_key`` is optional but strongly recommended: when supplied, a repeat POST with the same key claims the same durable operation instead of dispatching a second send. Omit only for truly fire-once flows.
  - `from_number` string, required — Sender E.164
  - `to` string, required — Recipient E.164
  - `body` string, required
  - `agent_id` string, uuid, required — Authorized agent for outbound sends.
  - `context_variables` object, nullable — Optional seed values for the agent's typed context variables, applied once at session bootstrap. Each key must be a variable declared on the agent or one of its bound workflows; values are coerced to the variable's type/enum (unknown key or uncoercible value → 422). System vars are frozen on-file; derived seeds satisfy the collection gate.
  - `media_urls` string[]
  - `idempotency_key` string, nullable — Alphanumeric + dash/underscore, 1-120 chars. Used to claim a durable operation so repeat POSTs with the same key are deduped.

## Response `202`

Successful Response

- SendSmsResponse — Response from ``POST /v1/sms/send``. Returns the routing context the caller (typically the shared brain) can use to correlate this send with the broader conversation state. Echoes the ``idempotency_key`` the caller supplied (or null) so clients can log it and retry safely with the same value. ``operation_id`` is the durable ``SmsOutboundOperation.id`` (ENG-846) — a stable handle for downstream status/observability tooling (ENG-849) to poll delivery state without re-deriving it from conversation rows. A retried request with the same ``idempotency_key`` gets back the SAME ``operation_id``.
  - `operation_id` string, uuid, required
  - `session_id` string, uuid, required
  - `end_user_id` string, uuid, required
  - `idempotency_key` string, nullable, required

## Other responses

- `400` — Bad request
- `401` — Authentication required
- `409` — idempotency_key already used with a different request (destination, body, media, or agent)
- `422` — Validation Error

---

[API](https://skmtc.net/oneloop-hq/apis/feather-api.md) · [All operations](https://skmtc.net/oneloop-hq/apis/feather-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/oneloop-hq/feather-api/revisions/5a5597ebb2d6/schema)
