Validation API & Scraper
The Validation API checks business and contact identifiers as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary vat endpoint validates a VAT number and returns format validity plus company name and address where available, and you can validate an IBAN, an email and batch. It is built for billing, KYC and onboarding forms that need to verify identifiers before accepting them. One ReefAPI key, one shared credit pool, the standard envelope.
What `valid` actually asserts in each of the three checks
The three checks answer three different questions, and a single boolean hides that. Read this before you branch on valid. Each check also keeps reporting the parts it did establish when the overall verdict is false, so a failure is diagnosable rather than opaque.
| Check | `valid: true` means | What you still get when it is false |
|---|---|---|
| iban | the ISO 13616 mod-97 checksum passes — computed locally, no bank is contacted | country_code, country_name, check_digits, length, sepa and the full checksum object; bban, bank_code, branch_code and account_number all go null and reason names the failure |
| vat | VIES answered that the number is registered at the moment you asked | format_valid reports the syntax verdict separately, so you can tell a malformed number from a well-formed but unregistered one; company_name and company_address are the VIES record when there is one |
| syntax parses, the domain has MX, and the address is not disposable | syntax_valid, has_mx, mx_records, is_disposable, is_role_account, is_free_provider, did_you_mean and a 0–100 score are each returned independently | |
| batch | n/a — the wrapper | count and valid_count plus every item's own record; a bad item comes back valid:false and never fails the batch |
A measured bad-checksum IBAN (DE89370400440532013001) returned valid:false, reason 'checksum_failed' and checksum {remainder: 28, expected: 1}. The remainder is exposed on purpose — if you are reconciling against another validator, that number tells you whether you disagree about the math or about the input.
Real request and response JSON
Captured from the indexed primary action, vat, on .
{
"method": "POST",
"url": "https://api.reefapi.com/validate/v1/vat",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"vat_number": "IE6388047V"
}
}{
"ok": true,
"meta": {
"api": "validate",
"endpoint": "vat",
"mode": "live",
"latency_ms": 824,
"record_count": 1,
"bytes": 551,
"cache_hit": false,
"method": "eu_vies_rest"
},
"data": {
"valid": true,
"format_valid": true,
"query": "IE6388047V",
"vat_number": "6388047V",
"full_vat_number": "IE6388047V",
"country_code": "IE",
"vies_country_code": "IE",
"company_name": "GOOGLE IRELAND LIMITED",
"company_address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4",
"request_date": "[redacted-phone]T17:20:42.583Z",
"request_identifier": null,
"consultation_number": null,
"user_error": "VALID",
"source": "vies"
}
}What the Validation API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| vat | Validate an EU VAT number via VIES → validity + registered company name & address. | Ops teams call vat to validate an EU VAT number via VIES → validity + registered company name & address.. | vat_number, country |
| iban | Validate + parse an IBAN offline (ISO 13616 mod-97) → country, BBAN, bank/branch/account. Optional enrich=true adds BIC + bank name/city (openiban.com, proxied). | Developer tools call iban to validate + parse an IBAN offline (ISO 13616 mod-97) → country, BBAN, bank/branch/account. | iban, enrich |
| Validate an email: syntax + live MX + disposable-domain + role-account flags. | Validation workflows call email to validate an email. | email, check_mx | |
| batch | Validate up to 100 mixed items ({type:vat|iban|email,value}) in one call. | Data-quality teams call batch to validate up to 100 mixed items ({type:vat|iban|email,value}) in one call.. | items, check_mx |
Call vat from your stack
curl -X POST https://api.reefapi.com/validate/v1/vat \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"vat_number":"IE6388047V"}'import requests
r = requests.post(
"https://api.reefapi.com/validate/v1/vat",
headers={"x-api-key": REEF_KEY},
json={
"vat_number": "IE6388047V"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/validate/v1/vat", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"vat_number": "IE6388047V"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.validate.vat with {"vat_number":"IE6388047V"}.Who uses this API and why
- Billing systems call vat and iban to validate a customer's tax and bank details.
- Onboarding forms use email validation to catch typos and undeliverable addresses.
- Compliance pipelines use batch to validate a list of records.
Questions developers ask before integrating
Why is an address at a disposable domain valid:false when has_mx is true?
Because MX presence and usefulness are different questions. A measured check on [email protected] returned syntax_valid true, has_mx true with two real MX hosts, is_disposable true, and then valid false, deliverable false and score 10. Mail sent there really would be accepted — it just lands in a throwaway inbox. If you want the raw DNS answer rather than our verdict, read has_mx and mx_records and ignore valid.
Why did a perfectly real corporate address score 85 instead of 100?
A measured check on [email protected] came back valid true, deliverable true, is_disposable false, has_mx true across five Google MX hosts — and score 85, because is_role_account was true. Role addresses (info@, support@, sales@) are shared mailboxes: deliverable, but a poor signal for a signup form or a lead record. The score is there so you can set your own threshold instead of accepting our binary.
Does the IBAN check contact the bank or go over the network?
No. IBAN validation is pure local arithmetic — ISO 7064 MOD-97-10 over the rearranged string — so it works for every IBAN-adopting country and cannot be rate-limited or return a stale answer. The one optional network step is enrich, which looks up BIC and bank name/city and is off by default. Enrichment never changes the validity verdict; the mod-97 result is computed before it runs. Bank-directory coverage there is proven live for DE, NL, LU and LI, and thinner elsewhere.
Why is bank_code numeric for a German IBAN and letters for a British one?
Because the BBAN layout is defined per country, not globally, and the parser reports whatever that country's format specifies. Measured: DE89 3704 0044 0532 0130 00 yields bank_code '37040044' (8 digits), branch_code null, account_number '0532013000'. GB29 NWBK 6016 1331 9268 19 yields bank_code 'NWBK' (the 4-letter bank identifier), branch_code '601613' (the sort code) and account_number '31926819'. Both are 22 characters long, which is coincidence, not a rule — IBAN length varies by country. Store bank_code as a string.
What does the VAT response tell me beyond a yes/no?
A measured VIES lookup on IE6388047V returned valid true, format_valid true, the normalized split (country_code 'IE', vat_number '6388047V', full_vat_number 'IE6388047V'), company_name 'GOOGLE IRELAND LIMITED' and company_address, plus request_date as an ISO-8601 UTC timestamp. request_identifier and consultation_number came back null in that lookup, so do not build an audit trail on them — log request_date and the response instead. VIES uses EL for Greece and XI for Northern Ireland; GR and GB are accepted and mapped for you.
Can I validate a mixed list in one request?
Yes — batch takes up to 100 items shaped {type: vat|iban|email, value: ...}, mixing all three types freely, and VAT items may carry their own country. Each item is validated independently and tagged with its type in results[], and count plus valid_count give you the tally without walking the array. It is the right call for cleaning an imported customer table.
How do I make the email check offline and fast?
Set check_mx to false. You then get syntax parsing, the disposable-domain verdict, the role-account and free-provider flags and did_you_mean, with no DNS-over-HTTPS lookup at all. has_mx will be unresolved rather than false, so branch on mx_checked, not on has_mx, when you run in that mode.
What is the Validation API?
Validation API is a ReefAPI endpoint group for validation It returns live JSON through POST requests under /validate/v1.
Is the Validation API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Validation calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Validation login or account?
No login to 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 Validation data?
The page example is captured from a live vat call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Validation API use?
Validation actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Validation from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call validate actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Validation API a Validation scraper?
It is the managed alternative to a DIY Validation scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same validation back as clean JSON.