TIN Validate API

Programmatically validate Tax Identification Numbers (TINs) across all 249 ISO 3166-1 countries and territories.
Format, structure, and check-digit checks — in a single request.

🔑
Need an API key? Create one from your Account → API Keys page. Each account supports up to 10 active keys.
i
API access requires payment. Buy validation credits or subscribe to Pro before creating API keys. Review pricing or check the supported countries.

Introduction

The TIN Validate API lets you validate 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 validation-check results.

Key capabilities:

Base URL

All API requests are made to:

Base URL
https://tin-validate.com/api/v1

The API uses major path versions. Backwards-compatible changes are released in-place within v1; breaking changes will use a new major path such as /api/v2.

Authentication

Every request must include a valid API key as a Bearer token in the Authorization header:

HTTP Header
Authorization: Bearer YOUR_API_KEY
⚠️
Keep your API key secret. Never expose it in client-side code, public repositories, or browser requests. Always call the API from your backend.

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.

Credit Usage

Validation credits are consumed only by POST /validate. A completed validation consumes 1 validation credit, including an invalid TIN result, because the validation rules were executed.

Request schema errors, invalid validation input, and validation execution errors do not consume validation credits. Reference endpoints such as GET /countries and GET /countries/{countryCode}/tin-types do not consume validation credits, though they remain authenticated and rate limited.

Rate Limiting

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.


Validate a TIN

POST /validate

Validates a Tax Identification Number against all known TIN types for the given country. Returns a detailed breakdown of each validation check for every applicable TIN type. Pass tinTypeId to validate against one specific TIN type.

Request Body

Send a JSON body with Content-Type: application/json. Unrecognised fields are rejected with 422.

FieldTypeDescription
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.
tinTypeId string optional Specific TIN type to validate against. Omit this field to validate against all TIN types for the country; do not send null.
Example Request Body
{
  "country": "FR",
  "tin": "42226020800026",
  "tinTypeId": "fr-siret"
}

Response Schema

A successful response returns 200 with the following JSON structure:

FieldTypeDescription
submittedValuestringThe original TIN value as submitted.
normalisedValuestringThe TIN with all whitespace and formatting stripped.
countryobjectCountry info: alpha2Code, alpha3Code, name.
isValidbooleantrue if the TIN matches at least one TIN type for the country.
matchedFormattedValuestring | nullThe matched TIN formatted for display, or null if invalid.
tinTypeResultsarrayValidation results per TIN type (see below).

TIN Type Result Object

Each item in the tinTypeResults array contains:

FieldTypeDescription
tinTypeIdstringStable machine-readable identifier for this TIN type.
namestringName of the TIN type (e.g. "French Tax Identification Number (NIF/SPI) - Individuals").
isValidbooleanWhether the TIN is valid for this specific TIN type.
issuedToIndividualsbooleanWhether this TIN type is issued to individuals.
issuedToEntitiesbooleanWhether this TIN type is issued to legal entities.
validationChecksarrayOrdered list of validation checks (see below).

Validation Check Object

FieldTypeDescription
descriptionstringHuman-readable description of the validation check.
passedbooleantrue if the TIN satisfies this check.

Full Example Response

200 OK
{
  "submittedValue": "01 23 456 789 417",
  "normalisedValue": "0123456789417",
  "country": {
    "alpha2Code": "FR",
    "alpha3Code": "FRA",
    "name": "France"
  },
  "isValid": true,
  "matchedFormattedValue": "01 23 456 789 417",
  "tinTypeResults": [
    {
      "tinTypeId": "fr-nif",
      "name": "French Tax Identification Number (NIF/SPI) - Individuals",
      "isValid": true,
      "issuedToIndividuals": true,
      "issuedToEntities": false,
      "validationChecks": [
        { "description": "Must consist of exactly 13 characters.", "passed": true },
        { "description": "All characters must be digits (0-9).", "passed": true },
        { "description": "Character in position 1 must be one of ['0','1','2','3'].", "passed": true },
        { "description": "Must pass the modulus-511 check-digit algorithm.", "passed": true }
      ]
    },
    {
      "tinTypeId": "fr-siren",
      "name": "French SIREN - Entities",
      "isValid": false,
      "issuedToIndividuals": false,
      "issuedToEntities": true,
      "validationChecks": [
        { "description": "Must consist of exactly 9 characters.", "passed": false },
        { "description": "All characters must be digits (0-9).", "passed": true },
        { "description": "Must pass the Luhn (mod 10) check-digit algorithm.", "passed": false }
      ]
    }
  ]
}

List Countries

GET /countries

Returns the full TIN Validate country catalogue covering all 249 ISO 3166-1 countries and territories. Use this endpoint to populate country pickers, validate country codes before calling POST /validate, or decide when to call the country-specific TIN types endpoint.

This endpoint is authenticated but does not consume validation credits.

Response Schema

FieldTypeDescription
countriesarrayAll 249 ISO 3166-1 countries and territories, sorted by country name.
countries[].alpha2CodestringISO 3166-1 alpha-2 country code used by validation requests.
countries[].alpha3Codestring | nullISO 3166-1 alpha-3 country code, when available.
countries[].namestringCountry name.

Example Response

200 OK
{
  "countries": [
    {
      "alpha2Code": "DE",
      "alpha3Code": "DEU",
      "name": "Germany"
    },
    {
      "alpha2Code": "FR",
      "alpha3Code": "FRA",
      "name": "France"
    }
  ]
}

List TIN Types for a Country

GET /countries/{countryCode}/tin-types

Returns the TIN types supported for a country. Use this endpoint to discover available identifiers before validation, display country-specific options, or resolve tinTypeId values returned by POST /validate. Countries in the catalogue with no native modelled TIN type return an empty tinTypes array.

This endpoint is authenticated but does not consume validation credits.

Path Parameters

FieldTypeDescription
countryCode string required ISO 3166-1 alpha-2 country code (e.g. FR, US, DE).

Response Schema

FieldTypeDescription
countryobjectCountry info: alpha2Code, alpha3Code, name.
tinTypesarraySupported TIN types for the country, or an empty array when no native TIN type is modelled.

TIN Type Reference Object

FieldTypeDescription
tinTypeIdstringStable machine-readable identifier for this TIN type.
namestringName of the TIN type.
issuingBodystring | nullIssuing authority when available.
issuedToIndividualsbooleanWhether this TIN type is issued to individuals.
issuedToEntitiesbooleanWhether this TIN type is issued to legal entities.
summarystring | nullShort description when available.
aliasesarrayCommon local names or abbreviations.
statusstring | nullStatus label such as current or transitional, when available.
examplesarrayExample values in display format.
validationChecksarrayValidation check descriptions for this TIN type.

Example Response

200 OK
{
  "country": {
    "alpha2Code": "FR",
    "alpha3Code": "FRA",
    "name": "France"
  },
  "tinTypes": [
    {
      "tinTypeId": "fr-siret",
      "name": "French SIRET - Professional Persons and Entities (Establishments)",
      "issuingBody": "Institut national de la statistique et des etudes economiques (National Institute of Statistics and Economic Studies)",
      "issuedToIndividuals": true,
      "issuedToEntities": true,
      "summary": "Fourteen-digit establishment identifier made from a SIREN plus a NIC.",
      "aliases": ["SIRET", "Numero Siret"],
      "status": "current",
      "examples": ["422 260 208 00026"],
      "validationChecks": [
        { "description": "Must consist of exactly 14 characters." },
        { "description": "All characters must be digits (0-9)." },
        { "description": "Must pass the Luhn (mod 10) check-digit algorithm." }
      ]
    }
  ]
}

Error Responses

Most API errors are returned as JSON with a string detail field. Schema validation errors use FastAPI's standard detail array.

Error Response
{
  "detail": "A human-readable error message."
}
Schema Validation Error
{
  "detail": [
    {
      "loc": ["body", "tinTypeId"],
      "msg": "String should match the expected pattern.",
      "type": "string_pattern_mismatch"
    }
  ]
}

HTTP Status Codes

CodeMeaningDescription
200OKValidation completed successfully.
400Bad RequestWell-formed JSON, but invalid validation input such as an unsupported country, unknown tinTypeId, empty normalised TIN, or over-length normalised TIN.
401UnauthorizedMissing or invalid API key.
402Payment RequiredValidation credits are exhausted.
403ForbiddenAccount is suspended, deleted, or email is not verified.
404Not FoundUser associated with the API key was not found, or the requested country was not found.
422Validation ErrorRequest body or path parameter does not match the expected schema, such as a missing required field, invalid country code shape, invalid tinTypeId format, or unrecognised JSON field.
429Too Many RequestsRate limit exceeded. Retry after the indicated period.
500Server ErrorAn unexpected error occurred. Contact support if persistent.

Code Examples

cURL

Shell
curl -X POST https://tin-validate.com/api/v1/validate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"country": "FR", "tin": "0123456789417"}'

Python

Python (requests)
import requests

response = requests.post(
    "https://tin-validate.com/api/v1/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["tinTypeResults"]:
    print(f"\n  {tin_type['name']}: {'✓' if tin_type['isValid'] else '✗'}")
    for check in tin_type["validationChecks"]:
        icon = "✓" if check["passed"] else "✗"
        print(f"    {icon} {check['description']}")

JavaScript

JavaScript (fetch)
const response = await fetch("https://tin-validate.com/api/v1/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.tinTypeResults.forEach((type) => {
  console.log(`${type.name}: ${type.isValid ? "✓" : "✗"}`);
  type.validationChecks.forEach((check) => {
    console.log(`  ${check.passed ? "✓" : "✗"} ${check.description}`);
  });
});

Supported Countries

TIN Validate supports all 249 ISO 3166-1 countries and territories. Pass the ISO 3166-1 alpha-2 country code in the country field. You can also call GET /countries to retrieve the current API country catalogue.

Some countries have no native modelled TIN type, or are documented through another country's tax identifier system. Use GET /countries/{countryCode}/tin-types to discover whether native TIN type rules are available before validating.

ℹ️
You can try out any country by using the web validator — select a country from the dropdown to see which TIN types are available.

Changelog

DateChange
2026-06-28Added the API v1 supported countries reference endpoint.
2026-02-15API documentation published.
2026-01-31API v1 released — POST /api/v1/validate endpoint.

💬
Questions or feedback? Reach out via our contact page or email [email protected].