Call-Detail Enrichment
Most routing decisions match on the dialed digits. Call-detail enrichment lets you match on what the numbers are: the operating company (OCN) that owns them, their LATA, state, and rate center, the ported-number routing number (LRN), and the call’s overall jurisdiction. This makes carrier-aware and jurisdiction-aware routing a first-class part of the configuration — no external rating engine required.
Typical uses:
- Send calls destined for a specific carrier’s numbers down a direct interconnect trunk instead of your default route.
- Apply interstate vs. intrastate rate decks by matching the call’s jurisdiction.
- Route by the LRN rather than the dialed number, so ported numbers rate and route according to where they actually live.
- Screen or scrub caller ID based on the calling number’s state or rate center.
The three numbers on a call
Section titled “The three numbers on a call”Enrichment data is available for three numbers, selected by the first letter of the field name:
| Prefix | Number | Description |
|---|---|---|
s… |
Source (calling party) | The presented caller ID |
d… |
Destination (called party) | The dialed number |
l… |
Routing number (LRN) | Where the called number actually routes after porting lookups |
The LRN (Location Routing Number) is the key to correct handling of ported numbers: a number that looks like it belongs to one carrier and region may have been ported elsewhere. When port data is unavailable for a call, the routing-number fields fall back to the called number’s own data.
Field reference
Section titled “Field reference”These field names are accepted everywhere a call-detail field can be used:
| Field | Meaning | Example value |
|---|---|---|
lrn |
Routing number in E.164 form | +12015550100 |
socn / docn / locn |
OCN (Operating Company Number) of the calling / called / routing number | 9206, 624H |
slata / dlata / llata |
LATA of the calling / called / routing number | 224 |
sstate / dstate / lstate |
US state of the calling / called / routing number | NJ |
sratecenter / dratecenter / lratecenter |
Rate center of the calling / called / routing number | JERSEYCITY |
call-type |
The call’s jurisdiction classification | interstateInterlata |
call-type values
Section titled “call-type values”The call as a whole is classified into exactly one of:
| Value | Meaning |
|---|---|
local |
Local calling area |
intrastateIntralata |
Same state, same LATA (not local) |
intrastateInterlata |
Same state, LATA boundary crossed |
interstateInterlata |
State boundary crossed |
international |
Outside the NANP, or NANP country boundary crossed |
Match these strings exactly — they are case-sensitive.
The match-on-call-details block
Section titled “The match-on-call-details block”match-on-call-details is a match operation, usable in any match list —
translation contexts, caller-ID contexts, and screening contexts. It names a
field with match-on, and carries a nested match list that is evaluated
against the field’s value instead of the dialed number:
match: - match-on-call-details: match-on: docn match: - exact: "9206" - exact: "624H"The nested list supports the same operations as any match block (exact,
regex, ast-pattern, and, …), OR’d together. Combine a call-detail
condition with a digit pattern using and:
match: - and: - ast-pattern: "_+1NXXNXXXXXX" - match-on-call-details: match-on: call-type match: - exact: "interstateInterlata"How lookups behave
Section titled “How lookups behave”- Lazy. The telephony-data queries run only when a call actually reaches a
rule that references a call-detail field (or an explicit
collect-numberinfo, below). - Cached per call. The first lookup’s result is reused for every subsequent call-detail match on the same call — many rules can reference these fields without repeated queries.
- Fail-closed. If data cannot be resolved for a call — an unparseable or anonymous caller ID, a number outside the coverage data engine (currently only NANP), or a lookup failure — the match evaluates false. The call is never matched by guesswork; it simply falls through to your later rules.
Controlling when enrichment is captured: collect-numberinfo
Section titled “Controlling when enrichment is captured: collect-numberinfo”Enrichment results are also stamped onto the call’s detail records (CDRs) for
rating and reporting. By default that happens only if a matching rule needed
the data. A modify block can force the lookup at a specific point in the walk
with collect-numberinfo: true:
"100": match: - always: true modify: operations: - strip-prefix: "9" - must-normalize: e164 collect-numberinfo: trueThe lookup runs after the block’s rewrite operations, so you can place it where the number is canonical — access codes stripped, normalized to E.164 — and the CDR enrichment reflects the real destination rather than the raw dialed string. The captured data is recorded on the inbound leg and every outbound leg the routing decision produces.
Call-detail fields in LCR blocks
Section titled “Call-detail fields in LCR blocks”Least-cost-routing lookups can also be driven by call-detail fields, in two
places on a route’s lcr block:
prefix-match-source— which value keys the rate-table prefix lookup: the literaldialednum, or any field above. Usinglrnhere makes your rate lookups port-corrected.selector— which rows are eligible within a matched prefix: a literal value,!all, or!match-on:<field>to resolve a field at call time and match rows whose selector column equals it.
routes: domestic-lcr: strategy: sequential lcr: tablename: us-rates prefix-match-source: lrn # rate the routing number, not the dialed number prefix-match-logic: prefix # longest-prefix match selector: "!match-on:call-type" # pick the row matching this call's jurisdiction route-count: 3 destinations: # fallback if no LCR row hits - trunk: default-carrierWith rate rows uploaded per jurisdiction (selector values local,
intrastateIntralata, interstateInterlata, …), the same table applies the
correct rate deck automatically per call.
Worked examples
Section titled “Worked examples”Direct interconnect by carrier (LEC)
Section titled “Direct interconnect by carrier (LEC)”You have a direct trunk to a neighboring carrier and want their numbers to bypass your default LCR route. Match the routing number’s OCN so ported numbers go the right way:
translations: wholesale-out: # Traffic homed on the neighbor's switches → direct interconnect. "100": match: - match-on-call-details: match-on: locn match: - exact: "9206" target: resource-type: trunk resource-id: neighbor-direct failure-treatment: all-circuits-busy
# Everything else → normal LCR. "200": match: - always: true target: resource-type: route resource-id: domestic-lcrIf the OCN lookup fails for a call, rule 100 simply doesn’t match and the call takes the LCR route — degraded, but never stuck.
Jurisdictional routing (ITSP)
Section titled “Jurisdictional routing (ITSP)”Different carriers for interstate and intrastate traffic:
translations: rated-out: "100": match: - match-on-call-details: match-on: call-type match: - exact: "interstateInterlata" target: resource-type: route resource-id: interstate-carriers
"200": match: - match-on-call-details: match-on: call-type match: - exact: "intrastateIntralata" - exact: "intrastateInterlata" - exact: "local" target: resource-type: route resource-id: intrastate-carriers
# Data unavailable or international → safe default. "900": match: - always: true target: resource-type: route resource-id: default-carriersIn-state toll restriction (PBX / campus)
Section titled “In-state toll restriction (PBX / campus)”A screening context that permits local and in-state calls but blocks out-of-state toll calling from restricted lines. Screening rules are evaluated lowest priority first; the first match decides, and no match means deny:
screening-contexts: in-state-only: "100": match: - ast-pattern: "_[2-9]XX" # extensions / short codes permit: true "200": match: - match-on-call-details: match-on: call-type match: - exact: "local" - exact: "intrastateIntralata" - exact: "intrastateInterlata" permit: true # Anything else (interstate, international, unresolvable) is denied # by the fail-closed default -- no explicit deny rule needed.A line profile references this with screening-context: in-state-only;
blocked calls receive the toll-denied treatment (SIP 403). Note that the
fail-closed lookup works for you here: a call whose jurisdiction can’t be
determined is denied, not permitted.
Caller-ID scrubbing by geography
Section titled “Caller-ID scrubbing by geography”Caller-ID contexts share the same match engine, so a trunk’s
outbound-caller-id-context can brand the presented number differently by
the caller’s state:
caller-id-contexts: brand-by-state: "100": match: - match-on-call-details: match-on: sstate match: - exact: "NJ" - exact: "NY" modify: operations: - replace: "+12015550100" # regional main number "200": match: - always: true modify: operations: - replace: "+18005550100" # national number for everyone elsePorted-number-correct rating (wholesale)
Section titled “Ported-number-correct rating (wholesale)”Rate and route on where numbers actually live:
routes: ported-aware: strategy: sequential lcr: tablename: onnet-rates prefix-match-source: lrn prefix-match-logic: prefix selector: "!all" route-count: 2 destinations: - trunk: overflow-carrierA dialed number in the 212 NPA that has been ported to a carrier you interconnect with directly will match your on-net rate rows by its LRN — even though its dialed prefix suggests otherwise.
Verifying call-detail routing
Section titled “Verifying call-detail routing”Every routing decision is captured in the route-forensics log, including each call-detail rule evaluated and whether it matched. When validating a new jurisdiction- or carrier-based rule, place a few test calls and pull their forensic records: the trace shows the exact rule-by-rule walk, so you can confirm the call-detail match fired (or see that data was unavailable and the call fell through) without guessing from the final destination alone.