> ## 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 recipe: one message to one contact, no campaign

> A task-focused run-through of Outbound → Direct send — when to bypass campaigns, how to pick the channel and recipient, template vs ad-hoc body, who can approve a gated launch, where the audit trail lands, and how to read CHANNEL_NOT_CONFIGURED from the console vs the API.

# Direct send recipe: one message to one contact, no campaign

This recipe walks one complete pass through **Outbound → Direct send**: deciding that the send should not be a campaign, picking the contact and channel, choosing a stored template or an ad-hoc body, understanding the approval chain, and reading the audit record afterward. The fuller coordinates — CSV semantics, batch idempotency, template lifecycle — live in the [Direct send reference](/guides/outbound-direct-send) and the [goals/approvals/direct-send guide](/guides/outbound-goals-approvals-direct-send); this page is the operator's decision loop.

## 1. When to bypass campaign machinery

Direct send earns its name when none of the campaign apparatus applies to the message. Pick direct send when:

* **A template fix is worth shipping tonight, not next sprint.** A corrected reminder or a follow-up phrased fresh reaches one contact now; a campaign draft → launch → audience-resolve round trip adds bookkeeping a single send never benefits from.
* **Your backend sends transactional system events.** Order-confirmation receipts, appointment reminders, status page updates — one-off events with a natural recipient, not an evaluated segment. A campaign would spend its audience-resolution machinery on a single-ID list anyway.
* **A support or ops agent answers one customer.** The agent's desktop needs "send this person a note," not a draft campaign detached from the conversation. Direct send keeps the message in the same message-history ledger as the conversation.

Prefer a campaign when the audience is a live segment resolved at launch, when A/B variants or holdouts matter, when the same send recurs on a schedule, or when launch needs supervisor approval at audience scale — see [Outbound goals, approvals, and direct send](/guides/outbound-goals-approvals-direct-send) for the gate's thresholds. Prefer sandbox magic numbers (`+15005550000`-range recipients) when you are testing integration shape, not messaging a person.

## 2. Choosing the channel and recipient

Open **Outbound → Direct send** and click **Send to one contact**. The picker searches contacts by name, phone, or email and lists every reachable identifier on the row (both the phone and the email, when both exist).

1. Search, then pick a contact.
2. The picker shows every channel the contact is reachable on — SMS for a phone number, Email for an email address, WhatsApp when a WABA sender is connected — with the exact identifier each would address.
3. Confirm the channel; the picker routes to that channel's composer with the recipient prefilled (`/messages/sms?to=<phone>&contactId=<id>` — the `to` prefills the To field, `contactId` records which contact row you came from).

A contact with no reachable identifier is disabled in the list and labeled "no reachable channel" — fix the contact row rather than type an address into the composer, so history attaches to the contact.

## 3. Template vs ad-hoc body

The composer you land in accepts two body strategies, and which one you pick decides whether next week's identical message drifts:

* **Stored template** — saved once under **Outbound → Templates**, then picked from the composer. Pick this when the body will recur (order-note updates, appointment reminders, support follow-ups). Reuse stops copy drift: every send renders the same approved version, and edits re-enter any approval the channel needs (WhatsApp templates re-enter Meta review; most other channels stay `active`).
* **Ad-hoc body** — typed in the composer's freeform field. Pick this when the body is genuinely one-off (a support answer, a one-time correction, a sandbox check). On SMS, the UI flags any unresolved `{{variable}}` placeholders before send — replace them; shipping literal `{{...}}` to a customer is an avoidable failure.

Template mechanics (approval states, variable systems, per-channel shapes) are covered in [Outbound templates](/guides/outbound-templates).

## 4. Approvals and roles

Direct send is a send, gated like every send:

* **Send permission.** Firing from the console picker, from a channel composer, or over `POST /messages/send` requires the owner, admin, or developer role. A viewer/light-seat member can browse the chooser page but the send action rejects.
* **API scope.** An API key minted with `messages:write` is required; read-only keys return 403.
* **The launch gate does not move to direct send.** Campaign-scene approval gates (`require_approval_default`, `min_recipients_for_approval`) are a campaign property; the dual-control step for a support agent's one-off note is conversation ownership, not a campaign gate. When the send looks like it needs an approval chain — anything customer-facing at audience scale — it has outgrown direct send; run it as a gated campaign (see [Outbound goals, approvals, and direct send](/guides/outbound-goals-approvals-direct-send)).

## 5. Recording the audit and reference

Every direct send lands in three consumer-readable ledgers — verify after the send, not assume:

* **Message history** — the single contact's conversation gains a message row with its delivery status; `contactId` links it back to the contact picker selection.
* **Outbound activity** — the **Outbound → Activity** ledger lists the send with its origin (direct send vs campaign) and a per-send reference the reviewer quotes back.
* **Audit log** — tenant audit events record the operator who fired the send, the channel, and the approval-chain link when a gated campaign path was involved (for direct send the link is empty by design). Pull the reference from **Settings → Audit log** when a reviewer asks "who sent this and when."

## 6. Failure handling: reading `CHANNEL_NOT_CONFIGURED`

The most actionable failure a direct send can hit is the platform telling you the chosen channel has no provider credentials yet. `CHANNEL_NOT_CONFIGURED` surfaces differently depending on the entry point:

* **In the console composer**, the send fails with a 503 and the composer surfaces "Provider is not configured — add credentials in Admin → System Config → Credentials." You only see it if you clicked Send; the message row flips to `failed` with the reason attached and no wallet credit burns.
* **Over the API** (`POST /messages/send` or `/messages/batch`), the same failure returns **HTTP 503** with `error.code: "CHANNEL_NOT_CONFIGURED"` and `details.channel` naming the rejected channel. Do not retry programmatically — it is deterministic against the current credential set: either provision the channel credentials, or fall back to a channel the tenant does have (e.g. email when SMS is unowned).

The distinction matters in an ops loop: treat 503 `CHANNEL_NOT_CONFIGURED` as "fix setup, then re-send" and treat 4xx validation errors (a `422` on an invalid recipient, a `403` on a read-only key) as "fix the request." Neither charges the wallet.

## Worked example: an order-note update from a support agent

A customer calls support asking whether order 1042 shipped; the agent confirms from the order system that it has, and wants to send a one-off SMS closing the loop.

1. Open **Outbound → Direct send**, pick **Send to one contact**.
2. Search the customer by phone, pick the SMS channel (the picker labels the exact number it addresses).
3. The SMS composer opens with the recipient prefilled. Type the ad-hoc body — "Hi Ava, your order 1042 shipped today — tracking in your email." — or pick the stored `order-note-update` template to keep copy consistent. On SMS the composer flags unresolved `{{variable}}` tokens; the agent's one-off body is clean by construction.
4. Send. The message lands in the conversation's message history and the Outbound → Activity ledger with its send reference; the audit log records the agent identity, channel, and timestamp.
5. If the send returns 503 `CHANNEL_NOT_CONFIGURED`, the tenant's SMS sender is not provisioned — the agent hands the setup to an admin, and in the meantime re-sends the note over Email from the same picker (the contact's email address was a second reachable identifier).

If the same note shape starts shipping forty times a day, that is the signal to promote it from a per-agent habit to a programmatic send — at which point the [Direct send reference](/guides/outbound-direct-send)'s API sections and sandbox magic-number checks apply before production rollout.

## See also

* [Outbound → Direct send reference](/guides/outbound-direct-send) — CSV semantics, `POST /messages/batch` idempotency, rate limits, and per-channel setup
* [Outbound goals, approvals, and direct send](/guides/outbound-goals-approvals-direct-send) — the campaign approval gate this page deliberately bypasses
* [Outbound templates](/guides/outbound-templates) — stored-template lifecycle for the recurring-body path
* [Message history and conversation ledgers](/guides/send-receive-messages) — where a direct send reports its per-recipient status
* [First transactional email](/guides/first-transactional-email) — the closest per-channel setup recipe when `CHANNEL_NOT_CONFIGURED` appears (provision the sender, then re-send)
* [Troubleshooting: APAC channel inbound no-route](/troubleshooting/apac-channel-inbound-no-route) — the same deterministic-503 pattern on the inbound side
