Skip to main content

Response Format

Every Vatly response follows the same envelope pattern: either data or error, always accompanied by meta. This means if (response.error) always works as a check.

Success response

{
  "data": {
    "valid": true,
    "vat_number": "NL123456789B01",
    "country_code": "NL",
    "company": {
      "name": "Acme B.V.",
      "address": "Keizersgracht 123, Amsterdam"
    },
    "consultation_number": "WAPIAAAAA1BBB2",
    "requested_at": "2026-03-06T12:00:00Z"
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "cached": false
  }
}

data fields

FieldTypeDescription
validbooleanWhether the VAT number is active and registered
vat_numberstringThe normalized VAT number
country_codestringTwo-letter country code
companyobject | nullCompany name and address (when valid and available)
company.namestringRegistered company name
company.addressstring | nullRegistered address
consultation_numberstring | nullVIES/HMRC consultation number (Business and Scale tiers only)
requested_atstringISO 8601 timestamp of the validation

Error response

{
  "error": {
    "code": "invalid_vat_format",
    "message": "The VAT number format is invalid. Expected format: CC123456789",
    "docs_url": "https://docs.vatly.dev/errors/invalid_vat_format"
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

error fields

FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable explanation
docs_urlstringLink to the error documentation page

meta fields

Present on every response — success or error.
FieldTypeDescription
request_idstringUnique request identifier (UUID)
cachedboolean | nullWhether the result came from cache (success only)
cached_atstring | nullISO 8601 timestamp of the cached result (when cached)
staleboolean | nulltrue when serving an expired cached result due to upstream failure
modestring | null"test" when using a test key, omitted for live keys

Response headers

HeaderWhen presentDescription
X-Request-IdAlwaysUnique request identifier matching meta.request_id
X-RateLimit-LimitAuthenticated requestsTotal requests allowed this period
X-RateLimit-RemainingAuthenticated requestsRequests remaining this period
X-RateLimit-ResetAuthenticated requestsWhen the quota resets (ISO 8601)
Retry-After429 and 503 responsesSeconds to wait before retrying

Request ID header

Every response includes an X-Request-Id header matching meta.request_id. You can pass your own X-Request-Id header and it will be echoed back — useful for correlating requests in your own logging.
curl -H "Authorization: Bearer vtly_live_your_api_key" \
  -H "X-Request-Id: my-trace-id-123" \
  "https://api.vatly.dev/v1/validate?vat_number=NL123456789B01"