> ## 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 health: find and repair numbers that silently drop inbound SMS

> The Numbers → Inbound health tab lists SMS-capable numbers whose routing entry is missing — a gap that silently drops inbound texts — and the dashboard plus API repair that re-registers them.

# Inbound health: find and repair numbers that silently drop inbound SMS

Inbound SMS reaches you only when the platform can resolve the destination
number back to your workspace. For an SMS-capable number you own, that
resolution runs through a per-number reverse map. When such a number loses
its reverse-map entry — after a bulk import, a maintenance-window change,
or a purchase whose registration was interrupted — inbound texts to it
have no workspace to land in and can be dropped with no error on either
side.

The **Inbound health** tab on the Numbers hub shows every number in that
state and lets you re-register it in one action. This page walks through
what the tab reports, when a manual repair helps, and how to run both
steps over the API. It uses only your own workspace's data — you never
see or touch another account's numbers.

## How gap detection works

A control-plane probe scans owned SMS-capable numbers and flags any that
are reachable in your inventory but have no reverse-map entry. Two
scoping rules keep the list honest:

* **Only SMS-capable numbers you own** are checked. Voice-only numbers
  never appear, because inbound routing for texts is irrelevant to them.
* **Shared pool numbers are excluded.** A number that also appears in the
  platform inventory resolves inbound before the reverse map is even
  consulted, so flagging it would misreport a healthy route as a gap.

Because of those two exclusions, a row in the Inbound health list is a
true routing gap, not a cosmetic inventory quirk. Any number that
appeared in the list while the gap was open could have been silently
dropping inbound texts.

## Walk the Inbound health tab

In the dashboard, open **Numbers** and choose **Inbound health** from the
**More** overflow menu — it sits with the lower-frequency surfaces
(Attestation, Replenishment, Reputation, Toll-Free RespOrg, and the
others) so the primary tab strip stays uncluttered.

* **Healthy zero-state.** When `gapCount` is zero, the tab tells you
  every SMS-capable number resolves correctly — no action is needed and
  the tab can stay closed another cycle.
* **Error state.** If the health read itself failed, the tab shows an
  error instead of a stale table. Refresh; a persisted read failure is
  worth an escalation note rather than a repair attempt.
* **Gap table.** Each row shows one affected number, masked (first three
  digits plus the last two, e.g. `+15********71`) so the raw digits never
  leave the API, together with its current status (`active`,
  `pending_compliance`, or `suspended` — the statuses that count as
  owned). The table lists at most 250 rows; the `gapCount` total above it
  always reports the full count, so a saturated table is annotated rather
  than silently truncated.

## Repair from the tab

The repair button re-registers every missing reverse-map entry for your
workspace in one action. It is deliberately safe to run:

* **Role gate.** Reading the tab is allowed for every role that can see
  Numbers. Triggering the repair requires **owner, admin, or developer**
  in the dashboard, or an API key with **numbers write** for API calls —
  a viewer sees the same honest gap list but cannot mutate it.
* **Idempotent.** The repair inserts only rows still missing at insert
  time and ignores rows that already exist. Re-running it after the gap
  closes is a no-op, and a concurrent purchase completing at the same
  moment cannot create a duplicate entry.
* **Expected result.** After a successful repair, the affected numbers
  resolve inbound immediately — send a test text to confirm, or re-read
  the health endpoint and expect `gapCount: 0`.

## API equivalents

Read the gap list:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/numbers/inbound-resolution/health" \
  -H "X-API-Key: dv_live_sk_..."
```

```json 200 theme={null}
{
  "data": {
    "gaps": [
      { "phoneNumberMasked": "+15********71", "status": "active" }
    ],
    "gapCount": 1,
    "resolverOrgScanCap": 250
  }
}
```

Trigger the repair (sends an empty body; optionally attach an
`Idempotency-Key` header to dedupe network retries):

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/numbers/inbound-resolution/repair" \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'
```

```json 200 theme={null}
{
  "data": {
    "orgId": "org_01J9Z8ABCDEF",
    "tenantId": "a1b2c3d4-...",
    "rowsInserted": 1
  }
}
```

`rowsInserted: 0` means the call ran and the workspace was already clean
— a valid no-op, not an error.

The same pair from the Node.js SDK:

```typescript theme={null}
const health = await fetch(
  'https://api.orbit.devotel.io/api/v1/numbers/inbound-resolution/health',
  { headers: { 'X-API-Key': process.env.ORBIT_API_KEY! } },
).then((r) => r.json())

if (health.data.gapCount > 0) {
  const repair = await fetch(
    'https://api.orbit.devotel.io/api/v1/numbers/inbound-resolution/repair',
    {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.ORBIT_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: '{}',
    },
  ).then((r) => r.json())
  console.log(`re-registered ${repair.data.rowsInserted} numbers`)
}
```

In both responses, numbers appear masked — first three digits plus the
last two — so a log or a screenshot never exposes the full digits.

## When repair alone does not fix inbound delivery

A repaired reverse map gets the inbound text to your workspace. If texts
still do not arrive where you expect, the remaining questions live inside
your workspace configuration:

* The hourly background sweep runs the same repair the button triggers,
  so a gap the repair reports as fixed will not re-open — and re-running
  it is never harmful.
* Each number also carries an optional per-number SMS route override.
  If that override is set to `disabled`, the inbound text resolves and
  stores but dispatches nowhere — the repair cannot change that.
* Inbox assignment and webhook delivery are separate steps downstream of
  resolution.

Work these in order on the
[inbound SMS troubleshooting runbook](/troubleshooting/inbound-sms-no-route) —
it sequences this health check, the route override, and the webhook
subscription, and lists the escalation material Support needs if all
three come back clean.

## See also

* [Troubleshooting: inbound SMS to your number never arrives](/troubleshooting/inbound-sms-no-route)
  — the ordered runbook this page hands off to when repair is not enough.
* [Inbound message resolution](/concepts/inbound-message-resolution) —
  how a number resolves to your workspace, and the four per-number SMS
  route types.
* [Inbound number routing](/guides/inbound-number-routing) — set the
  per-number route override the health tab cannot fix.
* [Bulk number-order history](/guides/numbers-bulk-orders-history) —
  reconcile provisioning after a bulk buy.
