The Phone Numbers screen shows two different things side by side. The Trunk and Agent columns show what is stored in the database for each DID. The Routes to (live) column shows what the engine would actually do with an inbound call to that number right now, read back out of the live dialplan. Most of the time they agree. This page covers the precedence the engine uses, how to read the live decision, and what to do when the two columns disagree.

Rule precedence: per-number, trunk, park

The TeleQuick engine resolves an inbound call against the live dialplan blob in a fixed order. The first match wins: A per-number rule always beats a trunk rule. That is what makes a stale per-number rule dangerous: it keeps winning, even after you have changed the trunk’s routing or cleared the number’s agent binding in the database. If neither a number rule nor a trunk rule matches, the call falls through to park — the engine answers nothing useful and the caller gets silence.

Reading the live route decision and its reason

The console asks the control plane for the effective route of every DID that is bound to a trunk:
admin.dialplanRoutes reads the live dialplan blob and applies the engine’s own precedence, so the answer is the engine’s answer, not a re-derivation from the phone_number rows. Each entry in the response carries four fields: The reason is the important half. Two numbers can both show the same agent and still be configured very differently — one via a per-number rule, one via its trunk. The bracketed label after the route in the table ([number rule], [trunk rule], [no rule]) tells you which one you are looking at, and therefore which object you need to edit to change it. The route lookup is advisory. If it fails, the column falls back to a placeholder and the rest of the table still renders — a failed lookup never blocks the number inventory.

What each action means

A park result is always highlighted, because an inbound DID that parks is almost never intentional.

Why some numbers show no live decision

The route lookup is only issued for DIDs that have a trunk binding whose trunk still exists in the org. A number is skipped when:
  • trunk_id is null — the row shows — no trunk.
  • trunk_id points at a trunk that is not in the org’s trunk list.
Inbound calls arrive over a trunk, so a DID with no trunk binding has no inbound path to evaluate. Bind it to a trunk before you expect a live route. While the lookup is in flight, bound numbers show ….

When stored bindings and live rules drift

The console flags a mismatch on a row in two cases:
  • The number has an agent_id in the database, but the live rule’s agentId is something else (including null).
  • The number has no agent_id in the database, but a per-number rule (did_rule) is still matching it — the database says “let the trunk decide”, the engine says otherwise.
Mismatched rows are highlighted and carry the note “differs from this page; use Re-sync routing”. Drift is possible because the database rows and the engine’s live rules are two separate stores. Saving a number writes the database row and then triggers a dialplan rebuild fire-and-forget on the server side. The rebuild is not part of the save’s response. So the live rules can lag, or — if a rebuild did not land — stay behind indefinitely while the number screen happily shows the new binding. Because the rebuild is asynchronous, the console deliberately waits before reading routes back: roughly 1.2 s after adding a number, and 300 ms after a re-sync. If you read the live column immediately after your own edit through another client, expect the same lag.

What Re-sync routing rewrites

Re-sync routing calls admin.reconcileNumbers for the active org. It is the repair path for “the number screen says X but calls go to Y”, and it removes any need to touch the engine’s Redis state by hand.
It does two things:
  1. Rewrites the engine’s number mirrors in Redis from the database phone_number rows — the database is the source of truth.
  2. Rebuilds the dialplan so the live rules match those mirrors.
The result banner reports what happened: If the call fails, the banner shows the error instead. Nothing is written to the database by a re-sync — it only rewrites the engine-side state from what the database already says.

Verifying a number after a change

  1. Make the change — add or edit the number, or change the trunk’s routing.
  2. Give the asynchronous dialplan rebuild a moment, then re-read the table. The Routes to (live) column is what the engine will do.
  3. Check the reason label. If you intended the trunk to decide, you want [trunk rule]. If you bound an agent directly to the number, you want [number rule] with that agent.
  4. If the row is highlighted, or shows PARK (no rule — silence) on a number you expect to answer, click Re-sync routing.
  5. Confirm the banner counts look sane, and that the row’s live route now matches its Trunk and Agent columns.
If a row still mismatches after a re-sync, the disagreement is in the database rows themselves rather than in the engine mirrors — re-check the number’s trunk and agent bindings, and the trunk’s own routing.
  • Authentication — the API key your console session uses for control-plane calls
  • Telemetry — CDR agent_id records which agent a call actually routed through