Skip to main content

The E.164 phone number format

E.164 is the ITU-T standard for international phone numbering, and it is the only string form Orbit accepts wherever a phone number moves through the platform — the to on a send, the query on a number search or lookup, the routing key on an inbound number, and the identity every webhook and delivery-receipt payload carries back. This page is the model behind those gates: what the format is, where Orbit normalizes and where it refuses, what the refusal looks like, and how to normalize user-supplied input before it reaches an endpoint.

What the format is

An E.164 number is one flat string with no spaces, dashes, or parentheses:
  • A leading + — the international prefix, mandatory.
  • The country calling code — 1 to 3 digits (1 for US/CA, 44 for the UK, 49 for Germany). This is the routing prefix: the first digits after + decide which country’s numbering plan owns the rest of the string, which is why no national trunk prefix or international access code (00, 011) may appear before or after the +.
  • The national destination number — the subscriber number as that country’s plan defines it.
Digit count after the + is at most 15, and the first digit after the + is never 0 (a country calling code cannot start with zero). In regex form, the structural gate is /^\+[1-9]\d{1,14}$/. Examples: The structural gate is only the first pass. +1234567890123456 (16 digits) fails it; +123 passes the shape but fails the second pass — the country numbering plan behind calling code 1 says that is not a complete, dialable number. Treat “shaped like E.164” and “valid E.164” as two different verdicts, exactly as the free E.164 formatter tool reports them.

Where Orbit normalizes, and where it refuses

Orbit normalizes every number to canonical E.164 on the way in and on storage: whatever shape an inbound SMS arrives in, the contact, the conversation, and every emitted event carry the normalized form, so any two spellings of the same number — (415) 555-0130, +1 415 555-0130, +14155550130 — resolve to one identity and dedupe against each other. Your outbound input is the other direction: send surfaces refuse rather than repair. A to that is not valid E.164 is rejected deterministically before anything bills, queues, or dispatches — see Validation gates for the full reject catalog. The refusal is deliberate: a platform that guesses the country you meant can deliver to the wrong subscriber, so the gate returns a 422 and leaves the fix on your side.

Where the rejection surfaces

Three gate families run the same E.164 check and answer with the same INVALID_PHONE_NUMBER code:
  • Send endpoints — SMS, WhatsApp, RCS, and voice dial validate the to (and an explicit from) before any wallet hold or provider call. A wrong-length destination for its country’s numbering plan is refused the same way, with a remediation sentence in the message.
  • Number search and purchase — every phone_number field on search, purchase, and bulk flows, plus the E.164 routing key of PUT /numbers/:phone/routing, must already be canonical.
  • Number lookup — both GET /numbers/lookup/{phone} and the bulk POST /numbers/lookup require +-prefixed E.164; a non-E.164 input never reaches a billed upstream dip.
The refusal arrives in the standard error envelope:
error.details.field and error.details.value echo the exact value your integration sent, and details.failureCode (when present) names the numbering-plan reason. Common inputs and their verdicts:

Line type follows the format

Format is the precondition for classification: the line-type surfaces in Line type and reachability — the free public checker, the billed lookup endpoint — only resolve once the input parses as E.164. Then the two answers pair in sequence: E.164 says the number is structurally dialable; line type says what the number can do. A fixed line can pass the format gate and still be a no for SMS, and a depends verdict on a VoIP or fixed-or-mobile range is a reachability question the format cannot answer. Scrub a list in that order — structural first (free), classified second.

What the format interacts with downstream

  • Number purchase — every inventory row on Numbers overview keys on the canonical phone_number, and purchase, bulk purchase, and bulk reserve all consume E.164 strings. The same string becomes the routing key for inbound configuration.
  • Sender-ID country matrix — an E.164 from is only the start of a sender decision. The sender-ID country matrix documents the per-country rules (registration, alphanumeric replacement, pre-registered sender classes) that apply after the format check passes, and Sender resolution picks the actual sender from your verified set.
  • US/CA routing — the porting pre-flight on Numbers overview resolves the carrier from the number itself: a +1… string is read through the NANP (country code 1), routed to the US/CA provider lane, and every other country code routes to the international lane. Valid E.164 is what makes provider selection a pure function of the prefix rather than a per-request decision.

Normalizing user-supplied input

Normalize at collection time — in the form that captures a phone number or the importer that reads a CSV — so every stored and submitted value is canonical before it meets an Orbit gate. The accepted pattern is libphonenumber (the same numbering-plan analysis Orbit’s own validators use): parse the raw input with an explicit default country for national-format input, then emit the canonical form via the format’s international (E.164) projection. Never regex-patch a missing +: without a country context, 4155550130 and 2079460958 are unresolvable guesses. Worked example — normalize +1 (415) 555-0130 (or the national spelling (415) 555-0130 with default country US):
Pre-flight the result with the free E.164 formatter tool — browser-side, no account, same numbering-plan verdicts the API returns — before you bulk-load recipients into a list, a flow, or a batch send.

See also