> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Direct send: one-off messages, batch or single

> The Outbound direct-send chooser — a three-step CSV batch wizard for one recipient list, or a contact picker that prefills a channel composer for one contact — without building a campaign.

# Direct send: one-off messages, batch or single

Some sends are not campaigns. A support follow-up to one customer, a one-time notification to a finite list — no named audience, no schedule, no per-variant analytics to justify a campaign object. **Outbound → Direct send** is the entry point for those sends. It is a chooser page with two paths:

* **Send to a list (CSV)** — the batch SMS wizard at Messages → Batch SMS: upload a recipient list, render a template per row, review cost, and send everything in one batch.
* **Send to one contact** — a picker that searches your contacts, shows every channel the contact is reachable on, and opens that channel's composer with the recipient prefilled.

Both paths run the same suppression, opt-out, and consent enforcement as a campaign. The difference is bookkeeping: a direct send writes message history rows and nothing else — no campaign object, no draft lifecycle, no analytics rollup.

## When direct send instead of a campaign

| Situation                                                                                 | Use                        |
| ----------------------------------------------------------------------------------------- | -------------------------- |
| One message to one contact, now                                                           | Direct send → one contact  |
| A finite list messaged once, no reuse                                                     | Direct send → CSV batch    |
| The audience is a live segment evaluated at send time                                     | Campaign                   |
| You need A/B variants, holdouts, a launch/approval lifecycle, or per-campaign attribution | Campaign                   |
| The same send will recur on a schedule                                                    | Campaign with a recurrence |

If a recurring weekly CSV run or per-variant measurement appears, the send has outgrown direct send — move it to a campaign and follow [Send a campaign end-to-end](/guides/campaign-end-to-end).

## The chooser page

Open **Outbound → Direct send**. Two cards lead:

1. **Send to a list (CSV)** links straight to the batch wizard — the next section covers it.
2. **Send to one contact** opens the contact picker.

Below the cards, a shortcut row jumps directly into the SMS, WhatsApp, or Email composer if you already know the channel and intend to address it yourself.

### Single contact: pick a contact, choose a channel

The **Send to one contact** card opens a picker:

1. Search your contacts by name, phone, or email.
2. Select a contact. The picker lists every identifier on the contact — a contact with both a phone number and an email shows both — and offers every channel it can route to: SMS for a phone number, Email for an email address.
3. Choose the channel and continue. The picker routes to that channel's composer with the recipient prefilled: `/messages/sms?to=<phone>&contactId=<id>` or `/messages/email?to=<email>&contactId=<id>`. The `to` parameter prefills the To field; `contactId` records which contact row you came from.

A contact with no phone number and no email is not selectable — the picker labels it "no reachable channel" and disables the row.

WhatsApp does not accept a prefilled recipient from this picker; reach it from the WhatsApp shortcut on the chooser page (WhatsApp sends need a connected WABA sender).

### Batch: CSV to a finished send

The **Send to a list (CSV)** card opens **Messages → Batch SMS**, a three-step wizard:

1. **Upload** — drop a `.csv` (or paste numbers directly), or load recipients from an existing contact list.
2. **Preview** — review the per-row rendered message, segment counts, and the cost breakdown resolved per destination.
3. **Send** — the wizard submits the whole batch as a single `POST /messages/batch` request and reports each recipient's outcome.

The full review, pricing, and failure-retry walkthrough is in [Batch SMS: send a one-off message to many recipients](/guides/messages-batch-sms). The sections below cover the parts that matter most when you arrive through direct send.

## CSV rules for batch sends

The wizard's Upload step understands three recipient sources — CSV, pasted numbers, or a saved contact list — and only one source is active at a time: choosing a second source replaces the first rather than combining both. The CSV contract:

* **One phone column is required.** The header row is auto-detected. Recognized phone-column headers include `phone`, `phone_number`, `to`, `number`, `mobile`, `telephone`, and `tel`. Recipients are E.164 numbers; whitespace, dashes, and parentheses are stripped before validation.
* **Per-row message column switches to per-row mode.** If the CSV has a `message`, `body`, `text`, `content`, `sms`, or `sms_body` header, every row carries its own body and the shared compose step is skipped. Otherwise the wizard applies one shared template with `{{variable}}` placeholders, and your extra CSV columns (for example `name`) bind those variables per row.
* **Invalid and duplicate rows are excluded, not fatal.** A partial number like `+123` is flagged and dropped; duplicates are merged with a count. Excluded rows are never priced and never sent — the review footnote discloses exactly how many were skipped.
* **Rejections stay per-row.** A post-upload rejection (validation, quota, sender-validation, country gate set in your compliance controls) flips only that row to `failed`; the rest of the batch still sends.

Keep a batch to one message theme. When the rows stop resembling one another — different purposes, different opt-in bases — that is two batches, or a campaign.

## Retries: idempotency and remapping

The batch is submitted as one `POST /messages/batch` call; failures come back as per-row outcomes, never as a silent whole-batch loss:

* **Every recipient is persisted before it is attempted.** Each recipient becomes a message row first — a rejected row is visible in the failed-recipients table immediately with its reason, not dropped. The response is `200` when every recipient succeeded and `207 (Multi-Status)` when at least one failed alongside at least one success.
* **Retry failed rows only.** The failed-recipients table lists each row with a remapped, friendly reason and the raw machine-readable `error_code` as a badge. For carrier-side or transient failures, the messaging retry policy applies server-side — retry the failed recipients; already-sent rows are not re-sent when you re-submit the batch envelope with the same idempotency behaviour.
* **Batch envelope rate limit.** One batch is one request, capped at 30 batch envelopes per minute per tenant (`X-RateLimit-Bucket: messages-batch` on the response headers tells your SDK when to back off). The per-recipient cost — carrier throughput, frequency caps, quota — is enforced inside the send pipeline, not by this limit.

## Permissions and limits per channel

Direct send is a send, so it is gated like every other send in the workspace:

* **Role.** Sending — from the batch wizard, the single-contact composer, or the API — requires an owner, admin, or developer role. Members with a read-only (viewer / light-seat) role cannot fire a direct send.
* **API key scope.** API-driven sends need a key minted with the `messages:write` scope; a read-only key is rejected with 403.
* **Per-channel limits.** `POST /messages/batch` accepts up to 10,000 recipients per call (resolved per tenant) across `sms`, `whatsapp`, `email`, `rcs`, `viber`, `instagram`, `messenger`, `line`, and `telegram`. The dashboard batch wizard drives SMS; the same route handles the other channels over the API.
* **Sender and channel setup.** SMS needs a sender — an owned number, an alphanumeric sender ID, or a sender pool. Email needs a verified sending address. WhatsApp needs a connected WABA sender. A contact with no reachable identifier for the channel (for example an SMS-only contact sent to the Email composer) has nothing to address — the composer starts empty.
* **Wallet and attestation.** The batch wizard's confirm step is gated on a wallet check and a compliance attestation that recipients are authorized and opt-outs honored.

## How direct send relates to campaigns

Both surfaces end at the same send pipeline. What a campaign adds is everything around the send:

|           | Direct send                                  | Campaign                                    |
| --------- | -------------------------------------------- | ------------------------------------------- |
| Audience  | A CSV / paste list or one contact            | A saved segment or list, resolved at launch |
| Schedule  | Optional one-off `scheduled_at` on the batch | Recurrence, launch window, journey steps    |
| Variants  | None                                         | A/B tests, holdouts                         |
| Approvals | Attestation only                             | Optional supervisor approval gate           |
| Tracking  | Per-row delivery in message history          | Campaign stats, goals, attribution          |

Guardrails do not relax because a send is one-off. Direct sends pass through the same tenant controls as campaign sends:

* **Suppression lists and channel-level opt-outs** are checked per recipient — a suppressed or opted-out recipient is held back either way (see [Opt-out lists and suppression](/guides/opt-out-lists)).
* **Frequency caps** count a direct send toward the recipient's budget (see [Frequency caps](/guides/frequency-caps)).
* **Quiet hours and send gating** defer or block sends inside a recipient-local quiet window, direct send or campaign alike (see [Quiet hours configuration](/guides/quiet-hours-configuration)).

All of these are controls you own at tenant level — configure them, and direct send respects them exactly as a campaign does.

## See also

* [Batch SMS: send a one-off message to many recipients](/guides/messages-batch-sms) — the wizard's review, pricing, and failure-retry mechanics in full
* [Send and receive messages](/guides/send-receive-messages) — the per-channel composer the contact picker opens
* [Send a campaign end-to-end](/guides/campaign-end-to-end) — when the send has outgrown direct send
* [Outbound goals, approvals, and direct send](/guides/outbound-goals-approvals-direct-send) — the approval gate and goal attribution a campaign adds on top
* [Message scheduling](/guides/message-scheduling) — one-off `scheduled_at` semantics on batches
