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

# Omnichannel Inbox setup: channels, routing, macros, SLA, AI drafts

> Stand up the unified Inbox end to end — connect SMS, WhatsApp, and email channels, route inbound conversations with rules, give agents macros, enforce first-response SLA, and turn on AI-drafted replies with self-serve deflection.

# Omnichannel Inbox setup

The Inbox is the operator surface for every customer conversation in your workspace — SMS, WhatsApp, email, RCS, Viber, Instagram, Messenger, LINE, Telegram, web chat, and voice tickets land on one queue with one assignment model. Setting it up well takes six things in order: connect at least one inbound channel, add routing rules so conversations reach the right team, publish macros so replies start from vetted text, attach an SLA policy so first response is a measurable clock, turn on AI drafts, then give the team saved views and bulk actions to keep the queue clean.

Everything here is per-tenant configuration you control. Channel writes, routing rules, SLA policies, and deflection settings are org-level: creating or editing them requires an owner or admin role, while reading and working the queue is open to any signed-in operator.

<Steps>
  <Step title="Connect an inbound channel">
    Wire one messaging channel so inbound traffic has a place to land.
  </Step>

  <Step title="Add routing rules">
    Order priority queues and assign to a user, team, or round-robin pool.
  </Step>

  <Step title="Publish macros">
    Reusable replies with per-customer variable substitution.
  </Step>

  <Step title="Attach an SLA policy">
    First-response and resolution clocks, plus breach actions.
  </Step>

  <Step title="Enable AI drafts and deflection">
    Suggested replies in the composer, plus self-serve resolution.
  </Step>
</Steps>

## 1. Connect inbound channels

A conversation exists in the Inbox because an inbound message arrived on a connected channel, so channel wiring is the first step. In the dashboard, open **Channels**, pick a provider, and complete its setup — the per-channel guides under [Docs → Channels](/channels/sms) walk through credentials and numbers. Outbound traffic uses the same connection, so nothing to wire twice.

Each inbound SMS, WhatsApp message, or inbound email on a connected channel creates (or appends to) an Inbox conversation automatically. Voice calls create tickets with their transcript and recording attached, so agents work voice follow-ups in the same queue as messaging.

`POST /inbox/tickets/internal` creates a ticket directly for channels that don't have a native inbound path — a partner-system hand-off, a manual entry, or a migration import — so those rows carry the same subject, priority, and assignment model.

## 2. Routing rules

Routing rules decide who owns a conversation the moment it arrives. Rules are evaluated in ascending `priority` order, and the lowest number wins — 1 runs first, so front-load your catch-alls and push specific rules up top. `POST /inbox/routing-rules/test` dry-runs a candidate rule against a sample message and reports which existing rules it would have beaten.

Conditions (all optional; combine freely):

* `channel` — one or more of `sms`, `whatsapp`, `email`, `rcs`, `viber`, `instagram`, `messenger`, `line`, `telegram`, `agent`, `voice`, `video`, `apple_messages`, `web_chat`.
* `keyword` — plain substrings, or `/regex/` patterns; regex entries are ReDoS-checked at save time, so an explosive pattern is rejected with `VALIDATION_ERROR` and never reaches the matcher.
* `language` — ISO 639-1 codes detected from message text, `country`, `tag_in`, `has_agent_history`, `sentiment` (`positive`, `neutral`, `negative`), plus `contact_segment_id`, `time_of_day` business-hours windows, and an `effort` band on the contact's latest CES score (`min_score` / `max_score`, 0–10).

Actions:

* `assign_user` / `assign_team` — direct to one user or a team's queue.
* `assign_round_robin` — spread across a pool of `user_ids` (up to 50).
* `assign_skill_based` — pick the operator whose skills overlap the rule's `required_skills` list most; `strategy: "weighted"` ranks by per-skill proficiency instead, and `respect_capacity: true` skips operators who are out of messaging capacity.
* `set_tag`, `set_priority` (`urgent`|`high`|`normal`|`low`), `trigger_agent` — hand the conversation to an AI agent instead of a human.

Create a rule:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/inbox/routing-rules \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "WhatsApp Spanish → LATAM team round robin",
    "priority": 10,
    "conditions": {
      "channel": ["whatsapp"],
      "language": ["es"]
    },
    "action": {
      "type": "assign_round_robin",
      "target_id": "rr-latam",
      "user_ids": ["user_maria", "user_diego"]
    }
  }'
```

`PATCH /inbox/routing-rules/{ruleId}` edits name, priority, the enabled flag, conditions, or action; `DELETE` removes the rule. Disabling a rule (instead of deleting it) keeps its position for re-enabling later. In the dashboard this maps to **Inbox → Routing rules** — *screenshot placeholder: rule list with priority ordering and actions.*

## 3. Macros

A macro is a named sequence of steps an agent applies to the current conversation with one click: send a reply, tag it, assign it, set its status or priority, snooze it, schedule a follow-up, create a task, set a disposition, or hand off to an AI agent. Personal macros are visible to their creator; shared macros (`is_shared: true`) are visible to the whole team and editable only by owners and admins.

Body text supports per-customer variables — `{{contact.first_name}}`, `{{organization.name}}`, and the conversation context — substituted at run time, and a localized variant per locale (`en` is required as the fallback):

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/inbox/macros \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Shipping delay apology",
    "category": "logistics",
    "is_shared": true,
    "steps": [
      {
        "type": "send_message",
        "config": {
          "body": {
            "en": "Hi {{contact.first_name}} — sorry about the delay. Your order is now scheduled to arrive {{order.eta}}.",
            "es": "Hola {{contact.first_name}} — disculpa la demora. Tu pedido llegará {{order.eta}}."
          }
        }
      },
      { "type": "add_tag", "config": { "tags": ["shipping-delay"] } }
    ]
  }'
```

`POST /inbox/conversations/{conversationId}/run-macro` fires a macro against the open conversation from the composer. Popular macros per agent surface via `GET /inbox/macros/popular`, and usage analytics via `GET /inbox/macro-analytics` so you can tell which shared macros are actually adopted. *Screenshot placeholder: macro picker above the conversation composer.*

## 4. SLA policies and the first-response clock

A policy sets two clocks per conversation: `first_response_target_minutes` (how long a customer waits for a first reply) and `resolution_target_minutes` (how long until the conversation closes). A third clock, `next_response_target_minutes`, governs follow-ups once the customer has replied again. Without any policy, the workspace reports against synthetic defaults — 4h first response, 24h resolution, business hours only — so the dashboard pill works from day one, and a policy you create replaces them.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/inbox/sla/policies \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "WhatsApp: 15-minute first response",
    "scope": "per_channel",
    "channel_filter": "whatsapp",
    "first_response_target_minutes": 15,
    "resolution_target_minutes": 480,
    "business_hours_only": false,
    "breach_action_type": "slack_webhook",
    "breach_action_config": {
      "webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX"
    }
  }'
```

`scope` takes `org_wide`, `per_channel`, or `per_segment`; one policy can be flagged `is_default` as the fallback. When a target breaches, the policy's `breach_action_type` fires — `none`, `reassign`, `notify`, `slack_alert`, `webhook`, or `slack_webhook` / `teams_webhook` with a `webhook_url`, so breached conversations surface in the chat tool your team already watches.

Read the live clock per conversation with `GET /inbox/sla/conversations/{conversationId}` — due-at, target minutes, and breach flags — the same state the dashboard SLA badge renders. The first-response clock starts on the first inbound customer message, so an agent-initiated thread doesn't breach before the customer ever wrote in.

## 5. AI drafts and deflection

Two AI assists layer onto the queue:

**AI drafts** propose the next reply to the operator. `POST /inbox/conversations/{conversationId}/ai-draft` returns one suggestion — draft text, a suggested action (`send`, `escalate`, `end`), a confidence score, and the knowledge-base sources it drew from — rendered inline above the composer with Accept / Edit / Discard. Every envelope also carries the co-pilot routing decision: `require_human_review` (always true) and `auto_approve_eligible`, which is only true when your workspace's co-pilot is enabled, the draft's confidence clears the threshold you set under the `inbox_copilot` settings key (0–1, default 0.9), **and** the suggested action is `send` — an `escalate` or `end` suggestion is never auto-approve-eligible, so a one-click approval automation can never quietly end or hand off a conversation. The flag is advisory: the human still Accepts, Edits, or Discards and nothing dispatches on its own. The dashboard pulls this on navigation, so each agent opens a conversation with a drafted first reply. Accepted and edited drafts feed back through `POST /inbox/ai-draft-feedback`, which tunes future suggestions.

**Deflection** resolves a conversation without an operator when the AI is confident enough. Two config endpoints govern it:

```bash theme={null}
curl -X PATCH https://api.orbit.devotel.io/api/v1/inbox/ticket-deflection/config \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "interactive_threshold": 0.7,
    "auto_threshold": 0.9,
    "fallback_message": "Let me bring in a teammate to help with that.",
    "fallback_trigger": "below_threshold"
  }'
```

`interactive_threshold` gates the agent-facing deflection card (`POST /inbox/tickets/{id}/deflect` suggests a self-serve answer; `/deflect/accept` closes the ticket as resolved-by-AI; `/deflect/escalate` flags it for the human queue). `auto_threshold` gates the fully automatic inbound path and must sit at or above the interactive threshold — auto-reply without a human review never runs at a looser bar. The `enabled: false` kill switch short-circuits both paths before any model call.

Cap the spend with `POST /inbox/ai-deflection-budget`, and watch resolved-without-agent volume plus savings through `GET /inbox/deflection-savings`.

## 6. Saved views and bulk actions

Saved views pin a filter to the sidebar so the team splits the queue the same way every day — conversations still breaching first-response SLA, everything tagged `billing`, anything unassigned and urgent. The same filter object a view stores is accepted by `GET /inbox/conversations`, so you can re-apply a saved view's filter from the API without translating fields.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/inbox/views \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SLA at risk",
    "scope": "team",
    "filters": {
      "sla_breach": "first_response",
      "statuses": ["open"]
    }
  }'
```

Team views are visible to the whole tenant; creating or re-scoping one requires owner or admin. Deleting a view is a soft delete, so an accidental click is reversible. `GET /inbox/views/counts` returns unread counts for pinned views so the sidebar badges update without loading the queues.

Bulk actions keep a big queue clean: `POST /inbox/conversations/bulk` applies one of `assign`, `snooze`, `close`, `reopen`, `tag`, `archive`, `mark_read`, or `mark_unread` across up to 200 conversation ids and returns per-id success/failure. The response carries an undo token valid for 60 seconds — post it to `POST /inbox/conversations/bulk/undo` to reverse exactly the ids that succeeded.

## 7. Webhook consumers for inbound

If your inbound traffic arrives on your own infrastructure first — a CPaaS bring-your-own route, a legacy migration — the [Webhook consumer guide](/guides/webhook-consumer) shows how to accept signed deliveries and re-emit them as Orbit events. Pair it with this setup: webhook-delivered inbound messages land in the same unified queue, get the same routing rules, and count against the same SLA clocks.

## See also

* [Inbox API reference](/api-reference/inbox) — full request/response schemas for every endpoint above
* [Team chat](/guides/team-chat) — the internal operator surface that sits alongside the customer queue
* [Webhook consumer](/guides/webhook-consumer) — accept signed inbound events on your own endpoint
* [On-call alerting](/guides/oncall-alerting) — page a rotation when SLA breach actions fire
