Skip to content
Markets open

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

Look up a phone number

GET/api/v1/lookup/{number}

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

NameInTypeDescription
numberrequiredpathstring-

Response 200

FieldTypeDescription
datarequiredobject-
inputrequireddata.inputstringWhat you sent
validrequireddata.validbooleanWhether the input is a well-formed E.164 number
reasonrequireddata.reasonstring | nullWhy it is not valid, when it is not
e164requireddata.e164string | null+ followed by digits, e.g. +447700900123
internationalFormatrequireddata.internationalFormatstring | null+<country code> <rest>, e.g. +44 7700900123
countryrequireddata.countryobject | null-
isorequireddata.country.isostring | nullISO 3166 alpha-2. null for a shared dial code the decks do not resolve (+1, +7)
namerequireddata.country.namestring-
dialCoderequireddata.country.dialCodestring-
basisrequireddata.country.basisstringrate_decks when the matching destinations name the country; dial_code otherwiseOne of rate_decks, dial_code
numberTyperequireddata.numberTypestringInferred 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.numberTypeConfidencenumber0 to 1: the share of matching decks that agree on numberType
operatorrequireddata.operatorstring | nullThe 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.networkobject | nullThe 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.mccMncstring | nullMobile network code (MCC-MNC), when known, e.g. "234-58"
operatorrequireddata.network.operatorstring | nullThe network the number range was allocated to, e.g. "Manx Telecom"
sourcerequireddata.network.sourcestringrange = public number-range dataOne of range, hlr
matchedPrefixrequireddata.matchedPrefixstring | nullThe longest dial prefix any live deck matched
riskrequireddata.riskobject-
blockedrequireddata.risk.blockedbooleanA destination we do not carry (embargoed or platform-blocked)
sanctionedrequireddata.risk.sanctionedboolean-
highRiskrequireddata.risk.highRiskbooleanPremium-rate, or a prefix on our high-risk list (satellite, remote and high-cost destinations often abused for revenue-share fraud)
reasonsrequireddata.risk.reasonsstring[]-
pricingrequireddata.pricingobject-
voicerequireddata.pricing.voiceobject | nullThe cheapest live public route for the number, or null when none serves it
raterequireddata.pricing.voice.ratestringUSD, 6 decimals: per minute for voice, per message for SMS
currencyrequireddata.pricing.voice.currencystring-One of USD
unitrequireddata.pricing.voice.unitstring-One of min, msg
billingIncrementrequireddata.pricing.voice.billingIncrementstring | nulle.g. "60/60"; null when the listing does not state one
destinationrequireddata.pricing.voice.destinationstringThe destination the number matched on that route, e.g. "United Kingdom-Mobile"
routeIdrequireddata.pricing.voice.routeIdstring (uuid)The cheapest public route that serves the number (see GET /routes/{id})
routesServingrequireddata.pricing.voice.routesServingintegerHow many public routes serve the number
networkdata.pricing.voice.networkobject | nullSMS only: the network rate is for, when the route prices per network; null otherwise
mccMncrequireddata.pricing.voice.network.mccMncstring | nullMobile network code (MCC-MNC) the price is for, e.g. "234-10"; null when unknown
operatorrequireddata.pricing.voice.network.operatorstring | nullNetwork name from public number-range data, e.g. "O2"
sourcerequireddata.pricing.voice.network.sourcestringrange = number-range data; none = not determinedOne of range, hlr, none
rateBasisrequireddata.pricing.voice.network.rateBasisstringnetwork = 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.countryRatestring | nullSMS only: the route's price for other or unknown networks (USD, 6 decimals), when it prices per network
smsrequireddata.pricing.smsobject | nullThe cheapest live public route for the number, or null when none serves it
raterequireddata.pricing.sms.ratestringUSD, 6 decimals: per minute for voice, per message for SMS
currencyrequireddata.pricing.sms.currencystring-One of USD
unitrequireddata.pricing.sms.unitstring-One of min, msg
billingIncrementrequireddata.pricing.sms.billingIncrementstring | nulle.g. "60/60"; null when the listing does not state one
destinationrequireddata.pricing.sms.destinationstringThe destination the number matched on that route, e.g. "United Kingdom-Mobile"
routeIdrequireddata.pricing.sms.routeIdstring (uuid)The cheapest public route that serves the number (see GET /routes/{id})
routesServingrequireddata.pricing.sms.routesServingintegerHow many public routes serve the number
networkdata.pricing.sms.networkobject | nullSMS only: the network rate is for, when the route prices per network; null otherwise
mccMncrequireddata.pricing.sms.network.mccMncstring | nullMobile network code (MCC-MNC) the price is for, e.g. "234-10"; null when unknown
operatorrequireddata.pricing.sms.network.operatorstring | nullNetwork name from public number-range data, e.g. "O2"
sourcerequireddata.pricing.sms.network.sourcestringrange = number-range data; none = not determinedOne of range, hlr, none
rateBasisrequireddata.pricing.sms.network.rateBasisstringnetwork = 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.countryRatestring | nullSMS only: the route's price for other or unknown networks (USD, 6 decimals), when it prices per network
methodrequireddata.methodstringAlways prefix: no carrier network query is madeOne of prefix
cachedAtrequireddata.cachedAtstringWhen this answer was computed. Answers are cached for up to 10 minutes

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.