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

# Inbound fax: route received faxes to email and the inbox

> Set up per-DID inbound fax routing, understand the receive-to-delivery lifecycle, secure your webhook consumer, and wire received faxes into flows and email archives.

# Inbound fax routing

The [Fax channel page](/channels/fax) covers outbound fax and shows the webhook payloads that arrive when a fax lands on one of your numbers. This guide covers the other half of inbound: how the receive path works end to end, and how routing per DID decides where a received fax goes — your webhook endpoint, email recipients, and the shared inbox.

**You will:**

1. [Publish an inbound address and pick up the event](#1-publish-an-inbound-address)
2. [Follow the delivery lifecycle](#2-the-delivery-lifecycle)
3. [Route per DID to email and the inbox](#3-route-per-did-to-email-and-the-inbox)
4. [Secure your webhook consumer](#4-secure-your-webhook-consumer)
5. [Plan for the failure modes that matter](#5-failure-modes)
6. [Wire a contact-to-flow-to-email-archive pattern](#6-example-wiring-flow-to-email-archive)

## Prerequisites

* A fax-capable number on your account (see [Buy numbers](/guides/buy-numbers) — inbound fax works with the same inventory).
* An API key from **Settings → API Keys** (a `dv_live_sk_…` live key) for the routing calls below.
* A public HTTPS endpoint if you want your own webhook consumer in addition to email/inbox routing.

## 1. Publish an inbound address

Point the carrier-side fax application webhook at Orbit's inbound endpoint: `POST https://api.orbit.devotel.io/webhooks/inbound/fax`. For the platform connection Orbit does this for you; for a dedicated (per-tenant) carrier connection, set the URL in the carrier portal. From then on, any fax sent to the DID arrives as a `fax.received` event with the sender's number, the receiving DID, and a media URL for the PDF:

```json theme={null}
{
  "data": {
    "event_type": "fax.received",
    "payload": {
      "from": "+14155552671",
      "to": "+18005551234",
      "media_url": "https://media.carrier.example/fax.pdf",
      "fax_id": "c4f6a1b2..."
    }
  }
}
```

The event is deduplicated on the carrier's `fax_id`, so a carrier-side replay does not create a second message record. Make sure the carrier connection you send from is fax-capable — a voice-only connection never fires `fax.received`, and that misconfiguration is invisible to Orbit.

## 2. The delivery lifecycle

Every inbound fax passes through the same pipeline, whether or not you configure routing:

1. **Verify.** The carrier's signature is checked before anything else. A rejected signature returns `401` and the fax is counted but never stored.
2. **Persist.** The fax is stored as a message record with the sender, recipient, and media URL. A `404` from the carrier's fax application (no fax-capable connection bound) drops the fax at this step.
3. **Route.** Routing is per DID. If the receiving DID has routing enabled, the PDF is fetched once (a bounded download with a short timeout) and fanned out to the configured destinations. If the PDF cannot be fetched, email recipients get the download link instead of an attachment.
4. **Acknowledge.** The pipeline never errors on a routing failure — worst case is a link-only email or a skipped inbox ticket, logged and visible in your delivery result. The fax record is already safe by that point.

Numbers without routing configured keep the default behaviour: store as a message record plus your tenant events, and nothing else.

## 3. Route per DID to email and the inbox

Per-DID routing lives on the number's detail view (**Dashboard → Numbers → \[your number]**), and the same config is available over the API:

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/numbers/NUM_ID/fax-routing \
  -H "X-API-Key: dv_live_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "forward_emails": ["accounting@acme.com"],
    "deliver_to_inbox": true,
    "archive_path": "acme/ap-invoices"
  }'
```

`NUM_ID` is the number's UUID — the same id you see on the number detail page.

| Field              | Purpose                                                                                                                                 |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`          | Master switch. When `false`, no routing runs.                                                                                           |
| `forward_emails`   | Up to 20 recipients; each receives the fax PDF as an attachment (or the download link if the PDF could not be fetched).                 |
| `deliver_to_inbox` | Opens an inbox ticket tagged with the sender, recipient DID, and the fax media link, so agents can triage faxes next to other channels. |
| `archive_path`     | A label like `acme/ap-invoices` stamped onto the ticket and the email body for your own filing convention.                              |

Read back the current config with `GET /api/v1/numbers/NUM_ID/fax-routing`; an unconfigured number returns the disabled defaults. Invalid shapes (a bad email address, more than 20 recipients) are rejected with `422` at write time rather than silently no-oping when a fax arrives.

## 4. Secure your webhook consumer

Beyond the per-DID email/inbox routing, received faxes also reach your own webhook endpoints through the tenant-wide event bus (the same mechanism as outbound status events). Whichever consumer you build:

* Verify the `X-Orbit-Signature` header and reject deliveries older than five minutes — the full verification recipe with code samples is in [Webhook security](/webhooks/security).
* Return `2xx` quickly; only 2xx counts as delivered, and retries continue for anything else.
* Use the event `data.id` to deduplicate on at-least-once delivery.

Subscribe to events per the [events catalogue](/webhooks/events) and inspect retries and failures in [Inspecting deliveries](/webhooks/inspecting-deliveries).

## 5. Failure modes

For **outbound** fax, a rejected attempt surfaces on `message.failed` with the carrier's own `error_code` / `error_message` passed through — busy, no answer, no fax tone, poor line quality (see [Common errors](/channels/fax) on the channel page).

For **inbound** routing, the failure modes that actually matter:

* **Invalid recipients at write time are rejected with `422`** — fix the config before a fax arrives.
* **PDF fetch failed** — the email goes out with the download link instead of an attachment. Delivery is still counted.
* **A recipient email send failed** — the remaining recipients still get the fax; the failure is logged.
* **No destinations configured** — the fax is still stored as a message record; routing is a no-op.
* **Untrusted signature on the inbound event** — rejected before any processing; fix the carrier public key or any proxy stripping the signature headers.

## 6. Example wiring: flow to email archive

A common pattern: received faxes open an inbox ticket for triage, and a [Flow](/guides/build-first-flow) reacts to the inbound event — match the sender to a contact, branch (for example, a known supplier versus an unknown fax number), and forward to the right team email. Enable inbox routing on the DID as above, then let the Flow handle classification that a static recipient list cannot.

For a pure archive (no human triage), skip the inbox flag and set `forward_emails` to a mail archive address plus an `archive_path` label like `legal/incoming` — that is the entire setup.

## Next steps

* [Fax channel](/channels/fax) — payloads, capability limits, and error codes
* [Webhook consumer](/guides/webhook-consumer) — reliable endpoint design
* [Webhook security](/webhooks/security) — signature verification recipes
* [Build your first Flow](/guides/build-first-flow) — orchestrate on inbound events
* [Inbox setup](/guides/inbox-setup) — queues and assignment for the ticket side
