ATverify

Reliability

How to handle registry outages. What live, cached, and degraded mean in API responses.

National VAT registries have bad days. VIES has historically gone offline most Tuesdays for maintenance. HMRC rate-limits aggressively. BFS speaks SOAP and occasionally times out. The vatverify API is designed so a registry outage never returns a 502 to your checkout; instead, the response carries a freshness signal you can act on.

Three freshness states

Every response includes meta.source_status. There are exactly three values:

source_statusMeaningQuotaLatency
liveFresh response straight from the registry1 unit200ms–2s
cachedServed from the 30-day cache (within freshness window)0 units~2ms
degradedRegistry failed live; served from the fallback cache (last known good)0 units~2ms

live and cached are the happy paths. degraded is the one to handle.

What degraded means

When a registry is unreachable, vatverify returns the most recent successful lookup for that VAT number rather than a 502 registry_unavailable. The VAT number is still validated against real registry data, just last known good rather than real time.

{
  "data": {
    "valid": true,
    "vat_number": "IE6388047V",
    "verified_at": "2026-04-22T08:14:29Z",
    "company": { "name": "Apple Distribution International Ltd" }
  },
  "meta": {
    "cached": true,
    "source": "vies",
    "source_status": "degraded",
    "latency_ms": 3,
    "request_id": "a1b2c3d4-..."
  }
}

data.verified_at always reflects when the data was originally fetched from the registry. On a degraded response that's the last time the registry answered for this VAT number, which could be hours or days old.

How to handle it

For most use cases (onboarding flows, Stripe customer creation, checkout), degraded should be treated the same as live. The whole point is your funnel doesn't stall because VIES is having a Tuesday.

const result = await vat.validate({ vat_number: 'IE6388047V' });

if (result.data.valid) {
  // ship it (works for live, cached, and degraded)
  await createCustomer(result.data);
}

For compliance-sensitive workflows (tax audit evidence, invoice issuance with reverse-charge), you may want to flag or queue degraded responses for re-verification once the registry is back.

if (result.meta.source_status === 'degraded') {
  await queueForReVerification(result.data.vat_number);
  // still proceed, but mark the record for follow-up
}

Why not just retry?

The SDK already retries 502, 503, 504 with exponential backoff (see Retries). When the registry is genuinely down for hours, retrying won't help. You'd just stack latency before failing. The degraded fallback gives you a useful answer in 2ms instead of a timeout in 30 seconds.

If you want hard-fail behavior instead, use cache=false to force a live registry call. That bypasses both the cache and the degraded fallback, and will return 502 registry_unavailable when the registry is down.

await vat.validate({ vat_number: 'IE6388047V', cache: false });

Live status

Real registry uptime and latency for the past 30 days, broken out per registry: vatverify.dev/status. All numbers come from the public GET /v1/status.json endpoint, no marketing SLAs.