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

# Pick the right inbound routing for a DID

> Choose between IVR, queue, voicemail, SIP forward, PSTN transfer, ring groups, conference, and the other route types on a number — set it from the dashboard or the API, verify it with the IVR simulator, and avoid the common attach mistakes.

Every phone number you own has an inbound routing config: the per-DID instruction that decides where an arriving call goes. It is one of the first decisions you make on a new number — before the IVR question, before staffing a queue — and it is a common support point because the route type is a single choice with very different consequences. This guide lays the full set of route types side by side, gives a decision table, and covers the ways to set and verify the choice.

Intents, keywords, DNIS patterns, and messaging-side routing are companions to this decision, not replacements for it — see [section 5](#5-companion-routing) for how they stack with the per-DID route.

Routing here is inbound-only. Changing a number's routing config never changes how your outbound calls are placed; outbound termination is unaffected by anything on this page.

## 1. What the routing config is

One row per DID. The core of it is a `(type, config)` pair:

* **`type`** — the routing decision: run an IVR flow, drop into a queue, ring a softphone, take a voicemail, drop the call, and so on. The full enum is in [section 2](#2-the-full-route-type-enum).
* **`config`** — a type-specific object. Each type accepts exactly one shape and validates it at write time, so a wrong-shaped config answers `422` instead of breaking mid-call. `ivr` takes `{ flowId }`; `queue` takes `{ queueId }`; a department mailbox takes `{ boxId }`; `decline` takes no config at all.

Optional siblings ride alongside:

* **`fallback_type` + `fallback_config`** — a depth-1 fallback destination, used when the primary route fails (queue has nobody available, webhook URL times out). The fallback accepts the same type set, but only `agent`, `softphone_user`, `softphone_register`, `voicemail`, `ivr`, `queue`, and `sip_forward` have fallback editors in the dashboard.
* **`business_hours`** — a schedule gate in front of the route. Outside the window, the route behaves as if no schedule matched, and the caller follows your primary path (or the fallback when hours complement it).
* **`caller_id_filter`** — allow/block/VIP lists matched on the inbound caller number. A blocked caller short-circuits before the route fires; a VIP always passes.
* **`recording_mode`** — per-route override of the org recording default: `off`, `all`, `inbound`, or `outbound`.
* **`sms_route_type` + `sms_route_config`** — an independent per-DID SMS termination (`webhook`, `agent`, `auto_reply`, or `disabled`). Voice and SMS on the same DID are separate settings on the same row; the voice route never blocks the SMS route.
* **`active`** — flip off to deactivate the route without deleting it. An inactive DID falls through to your org default inbound handling.

The voice gateway resolves the routing on every inbound call. Writes apply immediately — the next caller to the DID gets the new destination.

## 2. The full route type enum

Thirteen values. Each is reachable from the dashboard picker, the API, and (where it makes sense) the IVR Builder's attach surface.

| `type`                      | Label                       | Config shape                                                                                                                                                                                                                                      | Use it for                                                                                                                                                                                                                                                                                                            |
| --------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ivr`                       | IVR menu                    | `{ flowId }` referencing a published IVR flow                                                                                                                                                                                                     | Menus, speech-driven triage, business-hours branches — anything where the caller's digits or intent decides the destination.                                                                                                                                                                                          |
| `queue`                     | Call queue                  | `{ queueId, maxWaitSec?, textBackEnabled?, textBackMessage? }`                                                                                                                                                                                    | Hold the caller in FIFO and dispatch to an eligible agent. The standard support/sales answerer.                                                                                                                                                                                                                       |
| `voicemail`                 | Voicemail                   | `{ greetingUrl?, maxDurationSec?, notifyEmails?, notifyUserIds?, notifySmsRecipients?, retentionDays?, emailEnabled?, aiCallbackAgentId?, textBackEnabled?, textBackMessage? }`                                                                   | Capture a message from a caller you won't answer right now, with optional notification to up to five recipients.                                                                                                                                                                                                      |
| `dispatch_to_voicemail_box` | Department voicemail box    | `{ boxId, greetingUrl?, maxDurationSec?, aiCallbackAgentId?, textBackEnabled?, textBackMessage? }`                                                                                                                                                | Drop the caller into a shared department mailbox (sales@, support@) — the whole team sees the recording, not one user's inbox.                                                                                                                                                                                        |
| `agent`                     | AI agent                    | `{ agentId }`                                                                                                                                                                                                                                     | A Devotel AI agent answers and handles the call end to end.                                                                                                                                                                                                                                                           |
| `softphone_user`            | Browser softphone           | `{ userId, emailEnabled? }`                                                                                                                                                                                                                       | Ring one specific teammate's in-browser softphone.                                                                                                                                                                                                                                                                    |
| `softphone_register`        | Registered devices          | `{ usernames: string[] (1–50), strategy?: 'simultaneous' \| 'sequential', ringTimeoutSec?: 1–120, alsoRingPstn?: string[] (≤5 E.164) }`                                                                                                           | Fork-ring registered SIP devices — desk phones, mobile softphones, Linphone/Zoiper/Bria apps.                                                                                                                                                                                                                         |
| `ring_group`                | Ring group                  | `{}` — the group identity lives in the sibling `ring_group_id` field, not in `config`                                                                                                                                                             | Ring a saved group of devices, extensions, and phone numbers that you manage once and point many DIDs at.                                                                                                                                                                                                             |
| `shared_line`               | Shared line appearance      | `{ sharedLineId, ringTimeoutSec?: 5–120 }`                                                                                                                                                                                                        | Fork-ring every member device of a shared line; any member can answer. The receptionist / exec-assistant pattern.                                                                                                                                                                                                     |
| `sip_forward`               | Forward to your PBX         | `{ mode: 'trunk', trunkId }` or `{ sipUri, sipUsername?, sipPassword? }`                                                                                                                                                                          | SIP-forward the call to your existing PBX or carrier trunk. The password is written with `***` on readback — see [section 7](#7-common-mistakes).                                                                                                                                                                     |
| `transfer`                  | Transfer to PSTN            | `{ destination: E.164, callerIdOverride?: E.164, ringTimeoutSec?: 1–60 }`                                                                                                                                                                         | Bridge the caller to a fixed external phone number. Toll applies on the forwarded leg.                                                                                                                                                                                                                                |
| `conference`                | Conference room             | `{ conferenceName, startMuted?, waitingMusicUrl?, pin? (4–8 digits) }`                                                                                                                                                                            | Drop the caller into a named conference room; multiple DIDs can pour into the same room.                                                                                                                                                                                                                              |
| `decline`                   | Decline (SIP 603)           | `{ reason?: string (≤120 chars) }`                                                                                                                                                                                                                | Reject the call immediately — no media path, no answer, no PDD billing. For deprecated or honeypot DIDs.                                                                                                                                                                                                              |
| `webhook`                   | Media Streams / your server | exactly one of `{ url }` or `{ staticVerbs: [{ verb, ...}] (1–50) }`, plus `{ method?, timeoutSec?: 1–10, fallbackBehavior?: 'safe-default' \| 'voicemail' \| 'decline', signingSecret?, fallbackUrl?, fallbackMethod?, fallbackSigningSecret? }` | Point the DID at an HTTPS URL on your own server; the platform fetches Jambonz verbs from it per call. The only route type whose response may include a `listen` verb (real-time audio fork to your `wss://` endpoint). URLs are SSRF-guarded at write time, so a private-IP CNAME or metadata address answers `422`. |

The same enum is what [DNIS pattern routing](/guides/dnis-pattern-routing) accepts per `target_type` — the config shape you would send in `target_config` there is the same body you'd put on `config` here.

## 3. The three writing paths

All of them write the same row to the same endpoint; pick the surface you happen to be in.

**Dashboard — Numbers → *number* → Routing.** The picker grid renders one card per route type with its label and description. Select a type and the config section below it swaps to the matching editor — IVR flows get a flow dropdown, queues get a queue dropdown, SIP forward gets trunk-or-URI fields, and types with no config (like `decline`) hide the section. The fallback panel uses the same picker with the fallback-supported subset. Save writes the PUT below.

**API — `PUT /api/v1/numbers/:e164/routing`.** Programmatic and CI-friendly. The `:e164` path parameter accepts the number with or without the leading `+` and stores it with one.

```bash cURL theme={null}
curl -X PUT "https://api.orbit.devotel.io/api/v1/numbers/+14155550123/routing" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "queue",
    "config": { "queueId": "queue_01h..." },
    "fallback_type": "voicemail",
    "fallback_config": { "maxDurationSec": 120 },
    "business_hours": {
      "days": ["mon", "tue", "wed", "thu", "fri"],
      "start": "09:00",
      "end": "17:00",
      "timezone": "America/New_York"
    }
  }'
```

Other accepted body fields: `active`, `caller_id_filter`, `recording_mode` (`off | all | inbound | outbound`), `ring_group_id` (required when `type` is `ring_group`), `holiday_calendar_id`, `sms_route_type`, and `sms_route_config`. (For the SMS sibling, `webhook` takes `{ url, method?, secret?, fallback_url?, fallback_method?, fallback_secret? }`, `agent` takes `{ agentId }`, `auto_reply` takes `{ body: string (≤1600 chars) }`, and `disabled` takes `{}`.)

The shape of `(type, config)` is strict — a mismatched pair returns `422` with a message naming the expected shape (`queue route requires { queueId, ... }`), not a saved-and-broken-at-runtime. `GET /api/v1/numbers/:e164/routing` returns the current value; a sip-forward password comes back as `***` and re-sending the redacted sentinel preserves the stored password.

**From the IVR Builder.** In Voice → IVR Builder the toolbar has an attach action that writes the same row with `type: "ivr"` and the current flow id — so the authoring screen owns the attach for the IVR case specifically, while the others write through the Numbers page or the API.

Bulk apply exists too: `POST /api/v1/numbers/routing/bulk` runs the same per-DID validation across a list of numbers and returns per-item outcomes.

## 4. Decision: which type for which scenario

Answer the question in the table; the overflow / backup column tells you what to set as the fallback while you configure the primary.

| Scenario                                          | Primary `type`                          | Common fallback                            | Notes                                                                                                          |
| ------------------------------------------------- | --------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| Caller self-serves (balance, hours, order status) | `ivr`                                   | `voicemail` or `queue`                     | Build and publish the flow first — see [Build and ship your first IVR flow](/guides/build-ivr-flow).           |
| Speech-driven triage over a team                  | `ivr`                                   | `queue`                                    | Use a `speechInput` node with `speechIntents`; route each intent to a queue.                                   |
| Support / sales team answers                      | `queue`                                 | `voicemail` or `dispatch_to_voicemail_box` | Create the queue first ([voice queues guide](/guides/voice-queues)), then attach with `config.queueId`.        |
| Nobody answers; take a message                    | `voicemail`                             | —                                          | Set `notifyEmails` / `notifyUserIds` so someone actually hears it.                                             |
| Whole team owns a mailbox                         | `dispatch_to_voicemail_box`             | —                                          | Create the box under Voice first; the route references its `boxId`.                                            |
| An AI agent answers                               | `agent`                                 | `voicemail`                                | Reference an agent id owned by your org.                                                                       |
| One specific person answers                       | `softphone_user`                        | `voicemail`                                | The route rings their browser softphone; nobody else.                                                          |
| Ring desk phones / SIP apps                       | `softphone_register`                    | `voicemail`                                | Register the devices against your SIP edge first.                                                              |
| A group of destinations                           | `ring_group`                            | `voicemail`                                | Create the group under Voice → Ring groups; pass `ring_group_id` as a sibling field.                           |
| Receptionist pattern — every member rings         | `shared_line`                           | `voicemail`                                | Line roster is in Voice → Shared lines.                                                                        |
| Your own PBX answers                              | `sip_forward`                           | `voicemail` or `decline`                   | Point at a trunk by id, or a `sip:` / `sips:` URI.                                                             |
| Forward to a fixed external number                | `transfer`                              | `voicemail` or `decline`                   | Toll applies on the PSTN leg — check the destination before you attach.                                        |
| A named meeting room                              | `conference`                            | —                                          | The room stays open; other DIDs can pour in.                                                                   |
| DEPRECATED / honeypot DID                         | `decline`                               | —                                          | Cheapest possible answer: SIP 603, no media, no billing.                                                       |
| Your server decides per call                      | `webhook`                               | `voicemail` or `decline`                   | Twilio `voiceUrl`-style: fetch verbs from your HTTPS endpoint. The only route that can return a `listen` verb. |
| SMS on a messaging-only DID                       | set `sms_route_type`, leave voice alone | —                                          | See [section 5](#5-companion-routing).                                                                         |

When in doubt, `queue` with a `voicemail` fallback beats a bare direct line: it absorbs bursts, gives you queue health metrics, and stays under one DID while the IVR question stays open.

## 5. Companion routing — patterns, keywords, and messaging

The per-DID route is the top of the inbound chain. Three sibling features route the same traffic at a different layer; pick them alongside the route type, not instead of it.

* **[DNIS pattern routing](/guides/dnis-pattern-routing)** — one `target_type` + `target_config` rule per a block of DIDs, matching by E.164 prefix or regex. Per-DID routing (this page) always wins: a specific DID with its own entry beats the pattern, so use patterns as the fallback layer under your explicit numbers.
* **[Keyword auto-reply rules](/guides/keyword-auto-reply-rules)** — on the SMS/WhatsApp/RCS/Viber side, a rule fires before a human sees the inbox: reply, opt-in/out, hand to an agent, or trigger a flow. Voice routing is untouched by it; message routing picks up where `[sms_route_type](#1-what-the-routing-config-is)` terminates.
* **[Hosted messaging](/guides/hosted-messaging)** — when a DID is provisioned for messaging at hosting, the inbound SMS destination is decided at order time. The `sms_route_type` sibling on this row re-points it after activation, per DID.

Layer them: a DNIS pattern sends your forty-country support pool to one queue; keyword rules pre-answer the easy inbound texts on the same number; the IVR attaches to the specific DID you want to behave differently.

## 6. Verify with the simulator before you attach

For the `ivr` type, the simulator (`POST /api/v1/voice/ivr-flows/:id/simulate`) drives a scripted caller through the graph without burning a live minute. Run it on the **published** snapshot before the attach step — that is what the routing row actually answers with:

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/voice/ivr-flows/ivr_01h.../simulate" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "turns": [{ "digits": "1" }], "source": "published", "max_steps": 50 }'
```

The response returns `reached_nodes`, `emitted_verbs`, and `termination_reason` per turn. `source: "published"` walks the live snapshot; `source: "draft"` (the default) walks the unsaved draft — publish first, then simulate `published`, then attach the routing row. Sending a `definition` inline simulates a candidate graph without saving.

For the non-IVR types, verification is a real inbound call to the DID, watched in the call log — or a dashboard re-read of the routing tab to confirm the saved `(type, config)`. Attach-time `422`s are the guard that catches a shape error before either of those.

## 7. Common mistakes

* **Attaching a draft IVR.** The route stores the flow's id; the gateway resolves the published head at call time. If you wrote the row before you published, the caller hears whatever was last published — sometimes the empty stub, sometimes an older version. Publish, simulate `source: "published"`, then attach.
* **Missing `flowId` on `ivr`**, **missing `queueId` on `queue`**, **missing `boxId` on `dispatch_to_voicemail_box`.** Strict-shape validation rejects the write with `422` and a message naming the required field — but the Numbers tab that echoes a saved row with an empty config section wrote it before this validation existed. If an existing DID answers the wrong destination, re-save the route with the config filled in.
* **Sending the redacted `sip_forward` password.** Readback returns `sipPassword: "***"`. If you POST that literal `***` back without retyping the password, the API preserves the stored one — but pasting `***` into a brand-new route stores a literal `***` as the password. Retype it on change.
* **Setting the fallback to a type the dashboard can't configure.** The fallback panel only edits `agent`, `softphone_user`, `softphone_register`, `voicemail`, `ivr`, `queue`, and `sip_forward`. Richer primary-only types (`transfer`, `conference`, `decline`, `ring_group`, `dispatch_to_voicemail_box`, `shared_line`, `webhook`) save an empty config when picked as a fallback from an older dashboard — a `422` on the types that need a target. Pick the fallback from the supported subset.
* **Putting the ring-group identity in `config`.** `ring_group` accepts `{}` — the group id lives in the sibling `ring_group_id` field on the body, not inside `config`. A `config.ringGroupId` key is a strict-mode `422`.
* **Two routes for one DID.** There is one row per DID — a second `PUT` replaces the first. If you need two destinations, use `fallback_type`; if you need a menu in front, put both behind an `ivr` flow and route inside it.
* **`business_hours` written with the wrong key spelling.** The strict schema accepts only `{ days, start, end, timezone }` (numeric or `"mon"`..-style day names) or the per-day `{ mon: { open, close }, ... }` shape. A mis-typed key (`startTime`, `tz`) now answers `422` at write — before this, it silently meant "no schedule". If a schedule looks inactive, re-check which shape you saved.
* **Keyword rules vs `auto_reply`.** A bulk `sms_route_type: "auto_reply"` replies one fixed body to every inbound text on the DID; a keyword rule replies only when its keyword matches. Don't set `auto_reply` on a number that also runs keyword rules — the per-DID reply fires before rules evaluate.

***

**See also:** [DNIS pattern routing](/guides/dnis-pattern-routing) · [Build an IVR flow](/guides/build-ivr-flow) · [Voice queues](/guides/voice-queues) · [Voicemail boxes](/guides/voice-voicemail-boxes) · [Keyword auto-reply rules](/guides/keyword-auto-reply-rules) · [Hosted messaging](/guides/hosted-messaging)
