Phone Validation API

Turn a phone field full of human typing into E.164

Phone Validation API returns live Phone Validation data as clean JSON for validate and format phone numbers worldwide.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a Phone Validation endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
P
/phone-validate/v1

2 active endpoints, on 1 and 2 credit tiers.

  • POST/phone-validate/v1/validate
  • POST/phone-validate/v1/batch

What Phone Validation endpoints does ReefAPI ship?

2 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

2 endpoints

validate

1 cr

validate ONE number → validity + format/region/line-type/carrier/timezone/location.

required
number
optional
region, default_region, lang

batch

2 cr

validate up to 100 numbers in one call (shared default region).

required
numbers
optional
region, default_region, lang

Every parameter, every allowed value →

Phone Validation API

2 of 2 endpoints, ready to run

View docs ↗

One number in, and out come E.164, the national and international spellings, the country and region code, the line type, the carrier where it is known, the location and the time zones.

1 credit1 required · 2 optional
POST/phone-validate/v1/validate
ok3 ms · 1 records · sample
{
  "ok": true,
  "meta": {
    "api": "phone-validate",
    "endpoint": "validate",
    "mode": "offline",
    "latency_ms": 2.674,
    "record_count": 1,
    "cache_hit": false,
    "completeness_pct": 100
  },
  "data": {
    "input": "+90 532 123 4567",
    "is_valid": true,
    "is_possible": true,
    "parse_error": null,
    "e164": "+905321234567",
    "national_format": "0532 123 45 67",
    "international_format": "+90 532 123 45 67",
    "rfc3966": "tel:+90-532-123-45-67",
    "country_code": 90,
    "region_code": "TR",
    "national_number": 5321234567,
    "line_type": "mobile",
    "carrier": "Turkcell",
    "location": "Turkey",
    "timezones": [
      "Europe/Istanbul"
    ],
    "possible_reason": "IS_POSSIBLE"
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Phone Validation API works

Phone Validation is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /phone-validate/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 or 2 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Normalising an imported contact list before it reaches your CRM

A contact export contains local formats, spaces, brackets and a few things that were never phone numbers. You want one column of E.164 and an honest reject pile.

01batch
POST/phone-validate/v1/batch
{"numbers": ["+90 532 123 4567", "+44 20 7946 0958", "12345"], "region": "TR"}

region is the default for entries with no + prefix, so a local-format column parses without pre-processing.

02Keep e164 where is_valid is true; route the rest by parse_error.
POSTKeep e164 where is_valid is true; route the rest by parse_error.

The failure is named rather than blank — a nonsense string came back with parse_error INVALID_COUNTRY_CODE and every format field null.

One credit for the list. Nothing leaves for the network, so the whole thing is arithmetic against the numbering plans and finishes in about as long as the HTTP round-trip.

request
curl -X POST https://api.reefapi.com/phone-validate/v1/validate \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"number":"+90 532 123 4567"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "phone-validate",
    "endpoint": "validate",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

What line_type, carrier and location actually resolve to, country by country

These three fields have wildly uneven coverage, and the reason is the numbering plan of each country rather than the quality of the lookup. The table is five measured calls. Read it before you build a rule that assumes any of them is always present.

Inputline_typecarrier / location
+14155552671 (US)fixed_line_or_mobilecarrier null · location "San Francisco, CA"
+442079460000 (GB)fixed_linecarrier null · location "London"
05321234567 with region TRmobilecarrier "Turkcell" · location "Turkey"
+90 555 123 45 67mobilecarrier "Turk Telekom" · location "Turkey"
"12345"unknowneverything null, timezones []

location granularity is set by the country, not by a setting: a US number resolved to a city and state, a UK number to a city, and both Turkish numbers only to "Turkey". Never build a UI that promises city-level detail. carrier comes from the allocated number range rather than a live network query, so where it is populated treat it as an indication of the original operator, not proof of the current one.

What is computed, what is looked up, and where the answer thins out

Measured on a Turkish mobile, a British landline, a US number and a piece of junk. Two of these go against us.

It is offline, and it shows in the timing

The parse itself came back in fractions of a millisecond — the numbers are checked against the published numbering plans, not against a carrier lookup service. That is why a batch costs one call and why a rejected number costs nothing extra.

Four spellings of the same number, plus the time zones

A Turkish mobile returned E.164, the national spelling with its leading zero, the spaced international form and the tel: URI, along with the region code and the time zones the number sits in. The formatting is the part that is tedious to get right per country and it is done per country.

Against us: the carrier is not universal

The Turkish mobile named its carrier. The British landline and the US number both returned carrier null. This is not a gap in one country's data so much as what the underlying numbering plans publish: where a range is assigned to an operator, you get the operator, and where numbers port freely or ranges are not published that way, you get nothing. A null here means unknown, never 'no carrier'.

Against us: North American numbers cannot say mobile or landline

The British number came back line_type fixed_line and the Turkish one mobile. The US number came back fixed_line_or_mobile, because the North American plan does not separate them — mobile and landline share the same ranges. If your flow depends on knowing whether you can send an SMS, this field will not tell you inside the US.

Invalid input fails loudly and specifically

A five-digit string returned is_valid false, is_possible false and parse_error INVALID_COUNTRY_CODE, with every formatted field null rather than echoed back. is_possible is the separate, looser question — whether the number could exist at that length — which is the one to use when you want to accept partially-typed input without accepting nonsense.

What people build with Phone Validation

The jobs this data is most often used for.

2

endpoints

1/2

credits per call

01

Ops teams use Phone Validation to validate ONE number → validity + format/region/line-type/carrier/timezone/location.

02

Developer tools use Phone Validation to validate up to 100 numbers in one call (shared default region).

03

Validation workflows use Phone Validation to validate, enrich, classify and normalize operational data, all from one ReefAPI key and credit pool.

What Phone Validation data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/phone-validate/v1/validate \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"number":"+90 532 123 4567"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/phone-validate/v1/validate",
    headers={"x-api-key": REEF_KEY},
    json={
  "number": "+90 532 123 4567"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Phone Validation.

Get a free key →
Why can't it tell me whether a US number is a mobile?

Because the North American numbering plan does not separate them. A measured US number returned line_type "fixed_line_or_mobile", and that is the final answer rather than a lookup failure — mobile and landline numbers are drawn from the same ranges, so no amount of parsing distinguishes them. Contrast the measured Turkish numbers, which returned "mobile" outright because Turkey allocates mobile ranges separately, and the UK number, which returned "fixed_line". If your product depends on knowing, you need a live HLR lookup, not number parsing, and this API is honest about not being one.

What is the difference between is_valid and is_possible?

is_possible asks whether the digits could form a number in that country — right length, plausible prefix. is_valid asks whether they actually match an allocated range. A number can be possible and not valid: correct shape, nonexistent range. That is exactly the case for a typo in the middle of an otherwise well-formed number, and it is why both booleans are returned rather than one. possible_reason names which check ran — measured "IS_POSSIBLE" on the valid numbers.

Why did national_number lose its leading zero?

Because it is an integer, not a string. A measured Turkish number returned national_format "0532 123 45 67" and national_number 5321234567 in the same response — the trunk prefix is a formatting convention, not part of the number, so the integer form drops it. Never display national_number and never store it as your key. Use national_format for local display and e164 for storage.

Which of the four formats should I store?

e164 — the unambiguous international form, measured as "+905321234567". national_format is what a local reader expects to see ("0532 123 45 67"), international_format is the spaced readable international form ("+90 532 123 45 67"), and rfc3966 is the tel: URI for click-to-call links ("tel:+90-532-123-45-67"). Store one, render the others. Storing a display format is how duplicate contact records happen.

How do I parse a number that has no country code?

Pass region. A measured call on the bare Turkish national string "05321234567" with region TR resolved cleanly to +905321234567; without a region there is nothing to anchor it to. If your input is a mix, keep the user's country alongside the number and pass it every time — default_region does the same job as a fallback for a whole batch. Numbers that already carry a + are unaffected by either.

What comes back for garbage input?

An honest verdict, not an exception. A measured call on "12345" returned is_valid false, is_possible false and parse_error "INVALID_COUNTRY_CODE", with e164, formats, country_code, region_code, national_number, carrier and location all null, line_type "unknown" and timezones as an empty array. The envelope is still a success — validation succeeded, and its answer is no. Branch on is_valid and read parse_error to tell a malformed entry apart from a well-formed but unallocated one.

What is the timezones array for?

The IANA zones a number's region covers, measured as ["America/Los_Angeles"] for the US number and ["Europe/Istanbul"] for the Turkish ones. It is an array because large countries span several, so a number in a multi-zone country legitimately returns more than one and you cannot pick between them from the number alone. It is genuinely useful for the thing people always want it for: not calling a customer at three in the morning.

Can I clean a whole contact list in one call?

Yes — batch takes a numbers array with a shared region or default_region and returns count, valid_count, possible_count plus results[], where each entry is the same record the single-number action returns. The two counters tell you how dirty the list is without walking it, which is the fast way to answer 'how much of our CRM is unreachable' before deciding whether to spend on a deeper check.

What is the Phone Validation API?

Phone Validation API is a ReefAPI endpoint group for validate and format phone numbers worldwide. It returns live JSON through POST requests under /phone-validate/v1.

Is the Phone Validation API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Phone Validation calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Phone Validation login or account?

No login to Phone Validation is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Phone Validation data?

The page example is captured from a live validate call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Phone Validation API use?

Phone Validation actions currently cost 1-2 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Phone Validation from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call phone-validate actions with the same key, credit pool and JSON envelope used by normal REST requests.

19 Utilities & AI APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Phone Validation, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-30.