> ## 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.

# Resend a failed outbound message from the Inbox thread

> When an outbound bubble in an Inbox thread lands in a terminal failure state, a per-bubble Resend action re-dispatches it through the same routing stack. Covers when the button appears, what the retry does, and why resend is a manual, operator-gated step.

# Resend a failed outbound message from the Inbox thread

When an outbound reply fails — the carrier rejected it, the route returned no receipt, or the send bounced — the bubble in the Inbox thread shows its failure status in place of the usual delivery ticks. Each failed outbound bubble carries a **Resend** action that re-enqueues the message through the same send path a fresh reply would take, so an agent recovers a failed reply without opening a new compose window or touching the Messages log.

<Steps>
  <Step title="Understand what Resend does">
    Which bubbles offer it and what the retry re-dispatches.
  </Step>

  <Step title="Read the failure before re-sending">
    Pair the bubble's failure reason with the DLR outcome classification.
  </Step>

  <Step title="Click Resend on the bubble">
    One click, optimistic in-flight state, toast on completion.
  </Step>

  <Step title="Warn-first, do-not-auto-resend">
    The design pattern: the platform flags, the operator decides.
  </Step>
</Steps>

## 1. What the Resend action does

Open a conversation in **Inbox** and find the outbound bubble showing a failure status — `failed`, `undelivered`, `rejected`, or `bounced` are the terminal failure states the platform treats as recoverable. Beneath the bubble, a **Resend** button appears next to the failure reason. Clicking it re-enqueues the message through `POST /messages/:id/retry`, the same public retry endpoint the Messages log uses, and the bubble shows a per-bubble spinner while the request is in flight. *Screenshot placeholder: failed outbound bubble with the Resend action under the failure reason line.*

The retry dispatches the original body to the original recipient over the same channel, through the platform's standard routing — outbound exits via the Devotel softswitch exactly as a first send does. A wallet pre-flight runs before dispatch, so a retry on an empty balance refuses cleanly instead of failing at the provider. The new attempt is a normal send: it bills, it emits the same webhook events a fresh send emits, and it lands as its own row in the [Delivery Log](/guides/delivery-log), so the thread's outbound history keeps both the failed attempt and its retries.

The button is gated on the exact failure set the retry endpoint accepts, so it never offers an action the server would reject:

* **Inbound bubbles never offer Resend** — the customer owns sending on inbound rows.
* **`expired`, `deleted`, and `cancelled` rows never offer Resend** — those are settled or admin-terminal states, not recoverable failures.
* **A delivered email the recipient later reported as spam renders as delivered**, so it offers no Resend — re-sending to a complaining recipient is exactly what you don't want.

When the retry endpoint agrees the status isn't retryable, it refuses with a client error rather than half-sending anything, and the toast tells you the retry didn't go.

## 2. Read the failure before re-sending

Resend recovers a failed send; it doesn't fix the reason the send failed. Before clicking, read the failure reason line under the bubble — the bubble renders the provider's error in plain language when the channel returned one — and decide whether re-dispatching the same body to the same address has a chance.

The failure classes split the same way the [DLR outcomes monitoring](/guides/dlr-outcomes-monitoring) guide splits its WARN classifications:

* **Genuinely transient** — a provider-side blip, a route that missed its receipt window and aged to `undelivered`, a temporary carrier rejection. Resend is the right answer; the second attempt usually lands.
* **List or content problems** — an invalid number (`rejected` with an invalid-MSISDN reason), a suppressed recipient, content the route refuses. Resend re-sends the same body to the same address, so fix the contact or the body first; a plain retry repeats the failure.
* **No-receipt WARN lanes** — on lanes where receipts are structurally thin (Viber/WhatsApp aging, Meta DM), a row that aged to `undelivered` on the safety net's own window can still be corrected by a late genuine receipt. Check the [Delivery Log](/guides/delivery-log) for a correcting `delivered` before you resend, or the customer receives the message twice.

## 3. Click Resend on the bubble

On the failed bubble, click **Resend**. The button switches to an in-flight spinner while the retry request runs, so a second click can't fan out a duplicate dispatch. On success a toast confirms the retry was initiated and the thread's message list refreshes — the new attempt starts at the pre-dispatch states and advances to `sent` once the provider accepts it, then on to a terminal state as receipts arrive or the no-receipt window closes.

If the retry fails — the conversation closed, the balance pre-flight refused, the provider rejected at dispatch — the toast shows the failure and the original bubble keeps its failed state, so nothing is ever half-sent. Retry again after the underlying cause is fixed.

## 4. Warn-first, do-not-auto-resend

The design is deliberately manual. The platform surfaces the failure — the red failure glyph, the plain-language reason line, the WARN classification in your logs — but it never re-dispatches on its own. A blind automatic retry would double-message customers whose "failed" row was actually a late receipt, would re-send to recipients who complained, and would burn wallet balance repeating failures that need a content or list fix, not a resend. The operator reads the failure, decides, and clicks — **Resend** is the affordance that makes that decision one action instead of a copy-paste into a new compose window.

## Compliance

Resend is a tenant-owned control: which agent clicks it and when is your policy. The retry runs through the same per-send compliance gates a first send runs — consent, suppression, and quiet-hours are evaluated on dispatch, so a resend to a recipient who opted out since the first attempt refuses instead of sending. Outbound delivery stays within the Devotel softswitch contract described in [DLR and MO gateway pipeline](/concepts/dlr-and-mo-pipeline) — nothing on this page sends traffic anywhere new.

## See also

* [DLR outcomes monitoring](/guides/dlr-outcomes-monitoring) — the WARN classification this page's "read before resending" decision leans on.
* [Delivery Log](/guides/delivery-log) — where both the failed attempt and the retry land as rows.
* [Pending replies — the supervisor approval queue](/guides/inbox-pending-replies) — the other operator-gated outbound control in the Inbox.
* [Inbox setup](/guides/inbox-setup) — channels, routing, and the workspace the thread lives in.
* [Inbox API](/api-reference/inbox) — the endpoint surface the per-bubble action belongs to.
