REST API v1

API Reference

APIVAT exposes a simple JSON REST API for EU VAT number validation. All endpoints are served over HTTPS from https://apivat.eu.

Authentication

All requests require an API key passed as a Bearer token in the Authorization header.

HTTP header
Authorization: Bearer vat_your_api_key_here

Generate an API key from your dashboard. Keys are shown once at creation and stored hashed — treat them as passwords.

GET /v1/vat/:vatId

Validate a single EU VAT number. Returns the registration status, registered company name, and address. Results are cached for 30 days — cached responses return in milliseconds.

Request

ParameterTypeDescription
vatIdpathEU VAT number including the 2-letter country prefix (e.g. LU12345678).

Example

curl
curl -X GET https://apivat.eu/v1/vat/LU12345678 \
  -H "Authorization: Bearer vat_your_api_key_here"
Response
{
  "vat_id": "LU12345678",
  "valid": true,
  "name": "Example S.A.",
  "address": "1 Rue de la Loi, L-1234 Luxembourg",
  "source": "cache",
  "checked_at": "2026-05-10T09:00:00Z"
}

Response fields

FieldTypeDescription
vat_idstringNormalised VAT number as queried.
validbooleantrue if the VAT number is registered and active.
namestring | nullRegistered company name, or null if invalid or not disclosed.
addressstring | nullRegistered address, or null if invalid or not disclosed.
source"cache" | "vies"cache means the result came from the 30-day ES cache; vies means it was fetched live.
checked_atISO 8601Timestamp of when this result was last fetched from VIES.

POST /v1/vat/batch

Validate multiple EU VAT numbers in a single request. Available on paid plans. Results are returned in the same order as the input array. Each VAT number in the batch counts against your monthly quota.

Request body

FieldTypeDescription
vat_idsstring[]Array of EU VAT numbers to validate. Maximum length is tier-dependent (Basic: 10, Pro: 100, Max: 1,000).

Example

curl
curl -X POST https://apivat.eu/v1/vat/batch \
  -H "Authorization: Bearer vat_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"vat_ids": ["LU12345678", "DE811082782", "FR40303265045"]}'
Response
{
  "results": [
    {
      "vat_id": "LU12345678",
      "valid": true,
      "name": "Example S.A.",
      "address": "1 Rue de la Loi, L-1234 Luxembourg",
      "source": "cache",
      "checked_at": "2026-05-10T09:00:00Z"
    },
    {
      "vat_id": "DE811082782",
      "valid": true,
      "name": "Another GmbH",
      "address": "Musterstraße 1, 80333 München",
      "source": "vies",
      "checked_at": "2026-05-10T09:00:01Z"
    },
    {
      "vat_id": "FR40303265045",
      "valid": false,
      "name": null,
      "address": null,
      "source": "vies",
      "checked_at": "2026-05-10T09:00:02Z"
    }
  ]
}

Error codes

Error responses include a JSON body with a message field describing the error.

StatusNameDescription
400Bad RequestThe VAT ID is malformed (missing country prefix, invalid characters, or too short).
401UnauthorizedMissing or invalid API key. Include your key as a Bearer token.
402Quota ExceededYour monthly lookup quota is exhausted. Upgrade your plan or wait for the next billing cycle.
429Rate LimitedRequests exceed your tier's per-second rate limit. Back off and retry with exponential delay.
502VIES Upstream ErrorVIES returned a transient error (MS_MAX_CONCURRENT_REQ, MS_UNAVAILABLE, etc.). Retry after a short delay.
504Upstream TimeoutVIES did not respond within the timeout window (some member states can be slow). Retry is safe.

Rate limits & quotas

Each plan has a per-second rate limit and a monthly lookup quota. Exceeding the rate limit returns 429; exceeding the monthly quota returns 402. Quotas reset at the start of each calendar month.

PlanMonthly quotaRate limitMax batch size
Free100 / mo1 req/s
Basic1,000 / mo5 req/s10
Pro10,000 / mo20 req/s100
Max100,000 / mo100 req/s1,000

Rate limit headers are included on every response: X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp).

Code examples

JavaScript / TypeScript

Single lookup — JavaScript
const res = await fetch(
  "https://apivat.eu/v1/vat/LU12345678",
  { headers: { Authorization: "Bearer vat_your_api_key_here" } }
)
const data = await res.json()
console.log(data.valid, data.name)
Batch lookup — JavaScript
const res = await fetch("https://apivat.eu/v1/vat/batch", {
  method: "POST",
  headers: {
    Authorization: "Bearer vat_your_api_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    vat_ids: ["LU12345678", "DE811082782"],
  }),
})
const { results } = await res.json()

Python

Single lookup — Python (httpx)
import httpx

resp = httpx.get(
    "https://apivat.eu/v1/vat/LU12345678",
    headers={"Authorization": "Bearer vat_your_api_key_here"},
    timeout=30,
)
data = resp.json()
print(data["valid"], data["name"])
Batch lookup — Python (httpx)
import httpx

resp = httpx.post(
    "https://apivat.eu/v1/vat/batch",
    headers={
        "Authorization": "Bearer vat_your_api_key_here",
        "Content-Type": "application/json",
    },
    json={"vat_ids": ["LU12345678", "DE811082782"]},
    timeout=60,
)
results = resp.json()["results"]

Ready to integrate?

Create a free account to get your API key. 100 lookups per month, no credit card required.

Get started free