Programmatically validate Tax Identification Numbers (TINs) across all 249 ISO 3166-1 countries and territories.
Format checks, structure validation, and check-digit verification — in a single request.
The TIN Validate API allows you to verify whether a given Tax Identification Number is structurally valid for a specific country. The API checks the TIN against all known TIN types for the country (e.g. personal TINs, corporate SIRENs, VAT numbers) and returns detailed, per-rule validation results.
Key capabilities:
All API requests are made to:
https://tin-validate.com/api
Every request must include a valid API key as a Bearer token in the Authorization header:
Authorization: Bearer YOUR_API_KEY
You can manage your API keys (create, rename, revoke) from the API Keys dashboard. Your full key is shown only once at creation — store it securely.
API requests are subject to rate limiting to ensure fair usage. If you exceed the limit, the API responds with 429 Too Many Requests.
Wait for the indicated period before retrying. If you need higher limits, contact us.
Validates a Tax Identification Number against all known TIN types for the given country. Returns a detailed breakdown of each validation rule for every applicable TIN type.
Send a JSON body with Content-Type: application/json.
| Field | Type | Description | |
|---|---|---|---|
| country | string | required | ISO 3166-1 alpha-2 country code (e.g. FR, US, DE). |
| tin | string | required | The Tax Identification Number to validate. Whitespace and formatting characters are automatically stripped. |
{
"country": "FR",
"tin": "01 23 456 789 417"
}A successful response returns 200 with the following JSON structure:
| Field | Type | Description |
|---|---|---|
| submittedValue | string | The original TIN value as submitted. |
| submittedValueNormalised | string | The TIN with all whitespace and formatting stripped. |
| country | object | Country info: alpha2Code, alpha3Code, name. |
| isValid | boolean | true if the TIN matches at least one TIN type for the country. |
| officialFormatTin | string | null | The TIN formatted per its official display format, or null if invalid. |
| tinTypes | array | Validation results per TIN type (see below). |
| message | string | null | Reserved. Currently always null. |
Each item in the tinTypes array contains:
| Field | Type | Description |
|---|---|---|
| tinType | string | Name of the TIN type (e.g. "French Tax Identification Number (NIF/SPI) - Individuals"). |
| isValid | boolean | Whether the TIN is valid for this specific TIN type. |
| issuedToPersons | boolean | Whether this TIN type is issued to natural persons. |
| issuedToEntities | boolean | Whether this TIN type is issued to legal entities. |
| validationSteps | array | Ordered list of rule checks (see below). |
| Field | Type | Description |
|---|---|---|
| ruleDescription | string | Human-readable description of the validation rule. |
| rulePassed | boolean | true if the TIN satisfies this rule. |
{
"submittedValue": "01 23 456 789 417",
"submittedValueNormalised": "0123456789417",
"country": {
"alpha2Code": "FR",
"alpha3Code": "FRA",
"name": "France"
},
"isValid": true,
"officialFormatTin": "01 23 456 789 417",
"tinTypes": [
{
"tinType": "French Tax Identification Number (NIF/SPI) - Individuals",
"isValid": true,
"issuedToPersons": true,
"issuedToEntities": false,
"validationSteps": [
{ "ruleDescription": "Must consist of exactly 13 characters.", "rulePassed": true },
{ "ruleDescription": "All characters must be digits (0-9).", "rulePassed": true },
{ "ruleDescription": "Character in position 1 must be one of ['0','1','2','3'].", "rulePassed": true },
{ "ruleDescription": "Must pass the modulus-511 check-digit algorithm.", "rulePassed": true }
]
},
{
"tinType": "French SIREN - Entities",
"isValid": false,
"issuedToPersons": false,
"issuedToEntities": true,
"validationSteps": [
{ "ruleDescription": "Must consist of exactly 9 characters.", "rulePassed": false },
{ "ruleDescription": "All characters must be digits (0-9).", "rulePassed": true },
{ "ruleDescription": "Must pass the Luhn (mod 10) check-digit algorithm.", "rulePassed": false }
]
}
],
"message": null
}Errors are returned as JSON with a detail field describing the issue:
{
"detail": "A human-readable error message."
}| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Validation completed successfully. |
| 400 | Bad Request | Invalid input — e.g. missing country or tin, or unsupported country code. |
| 401 | Unauthorized | Missing or invalid API key. |
| 403 | Forbidden | Account is suspended, deleted, or email is not verified. |
| 404 | Not Found | User associated with the API key was not found. |
| 422 | Validation Error | Request body does not match the expected JSON schema. |
| 429 | Too Many Requests | Rate limit exceeded. Retry after the indicated period. |
| 500 | Server Error | An unexpected error occurred. Contact support if persistent. |
curl -X POST https://tin-validate.com/api/validate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"country": "FR", "tin": "0123456789417"}'import requests
response = requests.post(
"https://tin-validate.com/api/validate",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"country": "FR",
"tin": "0123456789417",
},
)
data = response.json()
print(f"Valid: {data['isValid']}")
for tin_type in data["tinTypes"]:
print(f"\n {tin_type['tinType']}: {'✓' if tin_type['isValid'] else '✗'}")
for step in tin_type["validationSteps"]:
icon = "✓" if step["rulePassed"] else "✗"
print(f" {icon} {step['ruleDescription']}")const response = await fetch("https://tin-validate.com/api/validate", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
country: "DE",
tin: "12345678901",
}),
});
const data = await response.json();
console.log("Valid:", data.isValid);
data.tinTypes.forEach((type) => {
console.log(`${type.tinType}: ${type.isValid ? "✓" : "✗"}`);
type.validationSteps.forEach((step) => {
console.log(` ${step.rulePassed ? "✓" : "✗"} ${step.ruleDescription}`);
});
});TIN Validate supports all 249 ISO 3166-1 countries and territories. Pass the ISO 3166-1 alpha-2 country code in the country field.
If a country code is not supported, the API returns 400 with a descriptive error message.
| Date | Change |
|---|---|
| 2026-02-15 | API documentation published. |
| 2026-01-31 | API v1 released — POST /api/validate endpoint. |