API reference
Number lookup
Validate a number and see its country, line type, network, risk and cheapest live price. Prefix-based, free.
1 operationBase URL https://packetexchange.io/api/v1Postman collection
BrowseNumber lookup
Look up a phone number
GET/
- Access
- Key optional. A key or token personalises the answer.
- Rate limit
- 60 requests per minute
Validates and formats an E.164 number and tells you what its prefix is on the exchange: country, line type (mobile, fixed, toll free, premium), the network where the rate decks agree, whether it is a blocked or high-risk destination, and the cheapest live public price to reach it by voice and by SMS (the same logic as GET /routes/price-number).
SMS prices are by destination network where the route prices per network: pricing.sms.network says which network the price is for and pricing.sms.countryRate is the price for other or unknown networks. The network is determined from the number's range (ported numbers may be priced at the network the range belongs to).
Prefix-based. No carrier HLR query is made, so the answer cannot tell you whether the number is in service or has been ported. It is free, needs no key (a scoped key needs routes:read), and is limited to 60 lookups a minute per caller. Send the number in international format (+447700900123 or 00447700900123; spaces and dashes are ignored). A malformed number answers 200 with valid: false and a reason.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
numberrequired | path | string | - |
Response 200
| Field | Type | Description |
|---|---|---|
datarequired | object | - |
inputrequireddata.input | string | What you sent |
validrequireddata.valid | boolean | Whether the input is a well-formed E.164 number |
reasonrequireddata.reason | string | null | Why it is not valid, when it is not |
e164requireddata.e164 | string | null | + followed by digits, e.g. +447700900123 |
internationalFormatrequireddata.internationalFormat | string | null | +<country code> <rest>, e.g. +44 7700900123 |
countryrequireddata.country | object | null | - |
isorequireddata.country.iso | string | null | ISO 3166 alpha-2. null for a shared dial code the decks do not resolve (+1, +7) |
namerequireddata.country.name | string | - |
dialCoderequireddata.country.dialCode | string | - |
basisrequireddata.country.basis | string | rate_decks when the matching destinations name the country; dial_code otherwiseOne of rate_decks, dial_code |
numberTyperequireddata.numberType | string | Inferred from the destination names on the rate decks that match the number (prefix-based, not an HLR query)One of mobile, fixed, toll_free, premium, unknown |
numberTypeConfidencerequireddata.numberTypeConfidence | number | 0 to 1: the share of matching decks that agree on numberType |
operatorrequireddata.operator | string | null | The network, only when at least three different sellers' decks name the same one for this prefix. Prefix-based: a ported number keeps its original network here |
networkrequireddata.network | object | null | The mobile network the number's RANGE belongs to, from public number-range data. A ported number keeps its range's network here. null when the range is not known |
mccMncrequireddata.network.mccMnc | string | null | Mobile network code (MCC-MNC), when known, e.g. "234-58" |
operatorrequireddata.network.operator | string | null | The network the number range was allocated to, e.g. "Manx Telecom" |
sourcerequireddata.network.source | string | range = public number-range dataOne of range, hlr |
matchedPrefixrequireddata.matchedPrefix | string | null | The longest dial prefix any live deck matched |
riskrequireddata.risk | object | - |
blockedrequireddata.risk.blocked | boolean | A destination we do not carry (embargoed or platform-blocked) |
sanctionedrequireddata.risk.sanctioned | boolean | - |
highRiskrequireddata.risk.highRisk | boolean | Premium-rate, or a prefix on our high-risk list (satellite, remote and high-cost destinations often abused for revenue-share fraud) |
reasonsrequireddata.risk.reasons | string[] | - |
pricingrequireddata.pricing | object | - |
voicerequireddata.pricing.voice | object | null | The cheapest live public route for the number, or null when none serves it |
raterequireddata.pricing.voice.rate | string | USD, 6 decimals: per minute for voice, per message for SMS |
currencyrequireddata.pricing.voice.currency | string | -One of USD |
unitrequireddata.pricing.voice.unit | string | -One of min, msg |
billingIncrementrequireddata.pricing.voice.billingIncrement | string | null | e.g. "60/60"; null when the listing does not state one |
destinationrequireddata.pricing.voice.destination | string | The destination the number matched on that route, e.g. "United Kingdom-Mobile" |
routeIdrequireddata.pricing.voice.routeId | string (uuid) | The cheapest public route that serves the number (see GET /routes/{id}) |
routesServingrequireddata.pricing.voice.routesServing | integer | How many public routes serve the number |
networkdata.pricing.voice.network | object | null | SMS only: the network rate is for, when the route prices per network; null otherwise |
mccMncrequireddata.pricing.voice.network.mccMnc | string | null | Mobile network code (MCC-MNC) the price is for, e.g. "234-10"; null when unknown |
operatorrequireddata.pricing.voice.network.operator | string | null | Network name from public number-range data, e.g. "O2" |
sourcerequireddata.pricing.voice.network.source | string | range = number-range data; none = not determinedOne of range, hlr, none |
rateBasisrequireddata.pricing.voice.network.rateBasis | string | network = that network's own rate; all_operators = the route's rate for networks it does not list separately; country = the route's price for other or unknown networksOne of network, all_operators, country |
countryRatedata.pricing.voice.countryRate | string | null | SMS only: the route's price for other or unknown networks (USD, 6 decimals), when it prices per network |
smsrequireddata.pricing.sms | object | null | The cheapest live public route for the number, or null when none serves it |
raterequireddata.pricing.sms.rate | string | USD, 6 decimals: per minute for voice, per message for SMS |
currencyrequireddata.pricing.sms.currency | string | -One of USD |
unitrequireddata.pricing.sms.unit | string | -One of min, msg |
billingIncrementrequireddata.pricing.sms.billingIncrement | string | null | e.g. "60/60"; null when the listing does not state one |
destinationrequireddata.pricing.sms.destination | string | The destination the number matched on that route, e.g. "United Kingdom-Mobile" |
routeIdrequireddata.pricing.sms.routeId | string (uuid) | The cheapest public route that serves the number (see GET /routes/{id}) |
routesServingrequireddata.pricing.sms.routesServing | integer | How many public routes serve the number |
networkdata.pricing.sms.network | object | null | SMS only: the network rate is for, when the route prices per network; null otherwise |
mccMncrequireddata.pricing.sms.network.mccMnc | string | null | Mobile network code (MCC-MNC) the price is for, e.g. "234-10"; null when unknown |
operatorrequireddata.pricing.sms.network.operator | string | null | Network name from public number-range data, e.g. "O2" |
sourcerequireddata.pricing.sms.network.source | string | range = number-range data; none = not determinedOne of range, hlr, none |
rateBasisrequireddata.pricing.sms.network.rateBasis | string | network = that network's own rate; all_operators = the route's rate for networks it does not list separately; country = the route's price for other or unknown networksOne of network, all_operators, country |
countryRatedata.pricing.sms.countryRate | string | null | SMS only: the route's price for other or unknown networks (USD, 6 decimals), when it prices per network |
methodrequireddata.method | string | Always prefix: no carrier network query is madeOne of prefix |
cachedAtrequireddata.cachedAt | string | When this answer was computed. Answers are cached for up to 10 minutes |
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.