API reference
One call at checkout. One to prove it later.
Every request is authenticated with a bearer API key. Branch on decision, not on status— the decision already applies your organisation’s policy for the unavailable case.
Authentication
Create keys in the dashboard. A key is shown once and stored only as a SHA-256 digest, so a lost key is replaced rather than recovered.
Authorization: Bearer vp_live_XXXXXXXXXXXXXXXXXXXXXXXXEndpoints
- POST
/api/v1/verifyCheck a VAT number. The checkout call.
Synchronous. Returns a decision, not just a verdict. Counts against the quota only when a live consultation is made.
- GET
/api/v1/checksThe audit archive, newest first.
Cursor paginated with ?limit= (max 100) and ?cursor=. Filter with ?status= and ?vatNumber=.
- GET
/api/v1/checks/{id}One check, with its receipt re-verified on read.
Verification is recomputed from the stored facts, never read from a column — a stored 'valid' flag would defeat the point.
- GET
/api/v1/auditVerify the whole receipt chain.
Walks the chain oldest first and reports the index it broke at, if any. Free; it does not count against the quota.
- GET
/api/v1/statusPer-member-state VIES availability.
Useful for explaining an UNAVAILABLE answer, and for a status page.
curl -X POST https://viesproof.altixcode.com/api/v1/verify \
-H "Authorization: Bearer vp_live_..." \
-H "Content-Type: application/json" \
-d '{
"vatNumber": "DE143454214",
"clientReference": "order_9001",
"trader": { "name": "Example GmbH", "city": "Berlin" }
}'Decisions
Three answers, three decisions. The mapping for UNAVAILABLE depends on your organisation’s policy, which is why the decision is computed here rather than left to each caller to re-derive.
| decision | status | Meaning |
|---|---|---|
| ACCEPT_ZERO_RATED | VALID | VIES confirmed the registration and issued a consultation number. The reverse charge may be applied. |
| CHARGE_VAT | INVALID | The member state replied: not registered. Charge domestic VAT. Also returned for UNAVAILABLE when your policy is fail-closed. |
| REVIEW | UNAVAILABLE | Nobody answered. Your policy is to flag rather than block, so the sale may proceed but must not be recorded as verified. |
Receipts and verification
Every consultation is appended to a per-organisation hash chain. Each receipt commits to the previous receipt’s digest, so an entry cannot be edited, removed or reordered without breaking verification from that point on. The digest is HMAC-signed with a key held only by the server.
GET /api/v1/audit
{
"verified": false,
"checked": 412,
"brokenAt": 412,
"reason": "digest_mismatch",
"chainLength": 1204
}brokenAt is the index of the first entry that failed. An auditor needs to know which record was altered, not merely that something was.
Supported member states
Syntax is checked locally before any call to VIES, so a malformed number costs nothing and produces a message that says what the right shape is. Great Britain is absent: it left the EU VAT area. Northern Ireland remains, as XI.
- AT
- BE
- BG
- CY
- CZ
- DE
- DK
- EE
- EL
- ES
- FI
- FR
- HR
- HU
- IE
- IT
- LT
- LU
- LV
- MT
- NL
- PL
- PT
- RO
- SE
- SI
- SK
- XI
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | vat_bad_syntax | The number does not match its country's format. The message says what the format is. |
| 400 | vat_unknown_country | Not an EU VAT country code. GB is no longer one; XI is. |
| 400 | vat_empty | No VAT number was supplied. |
| 401 | missing_api_key / invalid_api_key | No bearer token, or one we do not recognise. |
| 402 | quota_exceeded | The monthly check limit is reached. Never returns VALID instead. |
| 404 | not_found | No check with that id in your organisation. |