vatverify home

Changelog.

Reverse-chronological release log. Every ship, every fix.

bzst_id evidence field, SDK v0.2.0, reliability improvements

A third immutable evidence reference on §18e qualified confirmations, plus reliability improvements across the registry chain.

  • Retries on transient upstream blips. VIES, HMRC, BFS, Brønnøysund, and BZSt calls now retry brief upstream failures automatically before falling back to cache. Customers see source_status: live more often; /status numbers reflect genuine downtime instead of every momentary hiccup.
  • Audit log durability. Audit-trail writes (the §18e evidence record) now retry transient failures instead of silently dropping the record. No added latency.
  • bzst_id field on POST /v1/confirm (meta.bzst_id) and GET /v1/confirmations/{id}. BZSt returns its own request identifier in every qualified-confirmation response — now surfaced as a third immutable evidence reference alongside request_id and confirmation_id. Customers can prove "BZSt acknowledged this specific request" with a stable, queryable identifier independent of our own internal IDs. Strengthens the §18e evidence chain.
  • @vatverify/node v0.2.0 ships with client.confirm(), client.confirmations.get(id), bzst_id on ConfirmResponse.meta and ConfirmationRecord, and three new typed error classes (BzstError, BzstInvalidRequesterError, BzstQualifiedFieldsMissingError).

BZSt §18e qualified VAT confirmation

German sellers now have a first-class REST endpoint for the legal evidence §18e UStG requires, previously locked inside enterprise tax suites or scraped out of BZSt's raw eVatR form.

  • POST /v1/confirm issues a qualified Bestätigungsmitteilung from the German Bundeszentralamt für Steuern (BZSt), with per-field match codes (A/B/C/D) for company name, street, postcode, and town. Business plan only.
  • GET /v1/confirmations/{id} fetches a stored confirmation. Records are retained 10 years and remain readable through plan downgrades.
  • Idempotency-Key header (UUID): safe retries on network flakes return the originally stored row instead of issuing a new BZSt call.
  • Audit log entries with endpoint: 'confirm' render the match grid directly in the dashboard's lookup view.
  • Node SDK: vat.confirm(), vat.confirmations.get(id), typed MatchCode + BzstSessionLimitError / BzstUnavailableError / BzstRejectedError classes. Published alongside the API deploy.

Guide: §18e qualified confirmation.

Dashboards for audits, usage, and webhooks

Three new dashboard surfaces closing the gap between what the API does and what paying customers can actually see.

  • Audits dashboard (/dashboard/audits, Starter+): list recent validations, filter by endpoint and date, paste a request_id to replay the exact stored response. New "Copy as curl" reconstructs the original call. Detail endpoint now returns request_body, latency_ms, status_code, and valid for each record.
  • Usage dashboard (/dashboard/usage, Starter+): charts for request volume (success vs failure over time), endpoint mix, top countries, and cache source mix. 7d / 30d / 90d toggle is instant (client-side slicing). Backed by a new GET /v1/usage/rollup endpoint.
  • Webhooks dashboard (/dashboard/webhooks, Pro+): add / list / pause / rotate / delete endpoints with inline label edit. Test button verifies reachability. Recent-failures panel shows deliveries QStash gave up on, with a drawer for full response body and delivery metadata. Filter chips scope the list per endpoint.
  • API keys polish: inline label edit and rotate-with-24-hour-grace now available on every key card. During the grace window both old and new secrets work, so you can swap servers without downtime.
  • New API endpoints: GET /v1/audits (list + cursor pagination), GET /v1/usage/rollup (per-day rollup), PATCH /v1/webhooks/{id} (label + enabled), POST /v1/webhooks/{id}/rotate, GET /v1/webhooks/failures, GET /v1/webhooks/{id}/failures. All documented in the API reference.

Audit log + Webhooks

  • Audit log: retrieve any past validate/batch/decide response by its request_id via GET /v1/audits/{request_id}. Records retained 30 days (Pro) or 90 days (Business).
  • Webhooks: register up to 5 HTTPS endpoints per key to receive signed validation.completed and batch.completed events. Delivered via a durable queue with 3 retries. HMAC-SHA256 signed with a per-endpoint secret and 5-minute replay protection. Pro and Business plans.
  • Node.js SDK (@vatverify/node): vat.audits.get(requestId), vat.webhooks.create(url), vat.webhooks.list(), vat.webhooks.delete(id), vat.webhooks.test(id), new WebhookLimitError class.

Initial launch

  • 32 countries live (EU-27 + XI + GB + CH + LI + NO)
  • /v1/validate endpoint with real checksum validation and 30-day caching
  • /v1/decide tax-rules engine (Business plan)
  • Official Node.js SDK (@vatverify/node)
  • Offline validation library (@vatverify/vat-rates): format + checksum + rates
  • Test mode with magic VAT numbers (vtv_test_* keys)
  • Full documentation at vatverify.dev/docs
  • 15 guides at vatverify.dev/guides