EU VAT Validation API Documentation
Developer documentation for the VIESAC REST API: validate EU VAT numbers, create VAT audit trails, and retrieve PDF/XML certificates from VIES and supported official national registries such as HMRC, Brreg, and Swiss UID. All requests require Bearer authentication. Register for an API key.
OpenAPI 3 — https://viesac.eu/openapi.yaml
Authentication
Use your API key in the Authorization header with the Bearer scheme:
Authorization: Bearer viesac_your_api_key
Base URL
All endpoints are relative to:
https://viesac.eu/api/v1
OpenAPI specification
Machine-readable OpenAPI 3 description of this API (paths, schemas, Bearer security). Use it in Postman, code generators, or AI assistants.
https://viesac.eu/openapi.yamlQuick start
A reliable integration usually follows this sequence. It also gives API agents a clear decision path.
-
1
Authenticate
Send your API key with every request in the
Authorizationheader. -
2
Choose the outcome
Use
GET /validatefor a fast status check, orPOST /auditswhen you need evidence and a certificate. -
3
Store the reference
Keep the audit
reference_number; use it to retrieve the audit and its PDF or XML certificate.
VAT validation API endpoints
Start with this index, then use the field reference below when you need request or response detail.
| Method | Endpoint | Use when you need to… |
|---|---|---|
| GET | /account | Read the active plan and available capacity. |
| GET | /validate | Check a VAT number without creating an audit. |
| POST | /audits | Create auditable verification evidence and certificates. |
| GET | /audits | Search the audit history. |
| GET | /audits/{reference_number} | Read one audit and its links. |
| PUT | /audits/{reference_number} | Update order, invoice, comment, or monitoring data. |
| GET | /partners/check | Find saved partners by VAT or company name. |
| GET | /audits/{reference_number}/certificate | Download the PDF evidence for a valid audit. |
| GET | /audits/{reference_number}/certificate/xml | Download the technical XML evidence. |
/validate
Quick VAT status check — does not create an audit. Powered by VIESAC multi-source intelligence: VIES (European Commission), supported official national registries, VIESAC SmartRouter™, VIESAC SmartCache™, and VIESAC AI Engine work together to return the most accurate result.
⚠ For quick lookups only. This endpoint does not produce an official audit record. For legally reliable VAT verification, compliance documentation, and a timestamped certificate with full audit trail, use POST /audits instead.
Query params:
| Field | Requirement and description |
|---|---|
vat | (obligatorisk) — Full VAT including country prefix (e.g. DE123456789 or CHE-123.456.789 MWST). |
Response fields:
| Field | Description |
|---|---|
vat | Full VAT (country + number). |
country_code | Country code, for example DE. |
vat_number | VAT number without the country prefix. |
status | Validation result: valid, invalid, or audit_required. |
checked_at | ISO 8601 timestamp. |
Rate limits
Live VAT validations per account, per hour
GET /validate
| Plan | Validations |
|---|---|
| Free | 10 / hour |
| Starter | 100 / hour |
| Pro | 500 / hour |
| Business | 1,000 / hour |
| Enterprise | Unlimited — by agreement |
Enterprise capacity, support level, and commercial terms are tailored to your volume and agreed individually. If a limit is exceeded, the API returns HTTP 429 with retry_after (seconds) and upgrade_url.
/account
Get account stats: plan, total audits, audits this month, remaining this month.
Response:
| Field | Description |
|---|---|
plan, plan_label | Current plan. |
monthly_limit | Monthly audit limit; null means unlimited. |
requests_total | Total audits across all time. |
requests_this_month | Audits created this month. |
requests_remaining | Audits still available this month. |
validation_hourly_limit, validation_remaining_this_hour | Live-validation capacity for the current hour. |
upgrade_url | Link to change plan. |
/audits
Create a new VAT validation audit. Validates via VIES or a supported official national registry (for example Swiss UID for CH). If the official source is unavailable, the audit is queued for retry.
Body (JSON):
| Field | Requirement and description |
|---|---|
vat_number | (obligatorisk) — VAT number with or without country prefix. Swiss MWST, TVA, and IVA suffixes are normalized. |
country_code | (valgfritt) — 2-letter ISO code when vat_number has no prefix. |
requester_vat | (valgfritt) — Requester VAT. If omitted, the primary profile VAT is used. |
company_name | (valgfritt) — Company name; VIESAC AI can fill it when empty. |
company_address | (valgfritt) — Company address; VIESAC AI can fill it when empty. |
order_number | (valgfritt) — Your order reference. |
invoice_number | (valgfritt) — Your invoice reference. |
comment | (valgfritt) — Free-form note. |
monitoring | (valgfritt) — false, day, week, month, quarter, or year. |
audit_details | (valgfritt) — Structured metadata such as XML, JSON, or CSV. |
method | (valgfritt) — api, woocommerce, magento, or make. |
/audits/{reference_number}
Update an audit by reference number. You can update order_number, invoice_number, comment, and monitoring. Changes are recorded in the audit log. If the reference is not found for your account, returns 404 with an error message.
Body (JSON):
| Field | Description |
|---|---|
order_number | (valgfritt) — Order reference. |
invoice_number | (valgfritt) — Invoice reference. |
comment | (valgfritt) — Free-form note. |
monitoring | (valgfritt) — false to disable, or day, week, month, quarter, year to set frequency. |
404 if reference not found: {"error":"No audit found for this reference number."}
/partners/check
Check partner(s) by VAT number or company name. Returns one row per company (latest audit per country+VAT) with name, VAT, address, last status, last check date, and if monitoring is enabled: frequency and next check date.
Query params:
| Field | Requirement and description |
|---|---|
q | (obligatorisk) — VAT (e.g. DE123456789) or a partial company name. |
Response:
| Field | Description |
|---|---|
data | Partner objects with company, VAT, address, latest status, last check, and optional monitoring details. |
count | Number of partners found. |
/audits
List audits with filters. Default limit 100, max 500.
Query params:
| Field | Description |
|---|---|
limit | Number of results, default 100, maximum 500. |
date_from | Start date in YYYY-MM-DD format. |
date_to | End date in YYYY-MM-DD format. |
vat_number | Partial search. |
order_number | Partial search. |
invoice_number | Partial search. |
country_code | Exact match, for example DE. |
/audits/{reference_number}
Get full details of a single audit, including certificate_url and details_url.
/audits/{reference_number}/certificate
Download PDF certificate. Returns binary PDF with Bearer auth.
?locale= (valgfritt) — Certificate language: en (default), de, fr. Example: /audits/VAC-20260216-ABC123/certificate?locale=de
/audits/{reference_number}/certificate/xml
Download technical certificate (XML). Original VIES checkVatResponse or supported national registry evidence XML. Available for VALID status only.
Audit response includes certificate_url, certificate_xml_url, and certificate_urls (public links, no auth): pdf_en, pdf_locale (from Accept-Language), xml — when status is VALID.
Interpret audit results
| Field | Meaning |
|---|---|
status | valid (VIES confirmed), limited_valid (fallback), pending, invalid, or error. |
vies | 1 = valid certificate; 0 = negative/error; 2 = VIES unavailable and the audit will update later. |
API request and response examples
Each example pairs a complete request with the response shape your code or agent should expect.
Dark blocks are requests. Select the language you use, then copy the full example.
Light blocks are JSON responses. Treat values shown as examples, not fixed production data.
1. Quick VAT Validate — GET /validate
Instantly check if a VAT number is valid without creating an audit. Powered by VIESAC multi-source intelligence combining VIES, supported national registries, VIESAC SmartRouter™, VIESAC SmartCache™, and VIESAC AI Engine.
For quick lookups only — no audit record is stored. For a full, legally reliable verification with a timestamped certificate, use POST /audits.
curl -X GET "https://viesac.eu/api/v1/validate?vat=DE123456789" \
-H "Authorization: Bearer YOUR_API_KEY"Response (200) — VAT is valid:
{
"vat": "DE123456789",
"country_code": "DE",
"vat_number": "123456789",
"status": "valid",
"checked_at": "2026-03-16T12:00:00+00:00"
}
Response (200) — VAT is not valid:
{
"vat": "DE000000000",
"country_code": "DE",
"vat_number": "000000000",
"status": "invalid",
"checked_at": "2026-03-16T12:00:00+00:00"
}
Response (200) — Audit required (VIES unavailable and no fallback result):
{
"vat": "DE123456789",
"country_code": "DE",
"vat_number": "123456789",
"status": "audit_required",
"checked_at": "2026-03-16T12:00:00+00:00",
"code": "audit_required",
"next_step": "create_audit",
"create_audit_url": "https://viesac.eu/app/vat-validation",
"docs_url": "https://viesac.eu/api-docs"
}
Rate limit response (429):
{
"error": "VAT validation limit exceeded. Your current plan allows 10 live VAT validations per hour.",
"code": "rate_limit_exceeded",
"limit": 10,
"window": "1 hour",
"retry_after": 1800,
"upgrade_url": "https://viesac.eu/app/payment"
}
2. Get account — GET /account
Get plan and audit statistics.
curl -X GET "https://viesac.eu/api/v1/account" \
-H "Authorization: Bearer YOUR_API_KEY"Response (200):
{
"plan": "FREE",
"plan_label": "Free",
"monthly_limit": 15,
"requests_total": 120,
"requests_this_month": 12,
"requests_remaining": 3,
"validation_hourly_limit": 10,
"validation_requests_this_hour": 4,
"validation_remaining_this_hour": 6,
"upgrade_url": "https://viesac.eu/app/payment"
}
3. Create audit — POST /audits
Create a new VAT validation. Returns the audit object (201).
curl -X POST "https://viesac.eu/api/v1/audits" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"country_code":"DE","vat_number":"123456789","order_number":"ORD-001"}'Response (201):
{
"reference_number": "VAC-20260216-ABC123",
"country_code": "DE",
"vat_number": "123456789",
"status": "valid",
"vies": 1,
"company_name": "Example GmbH",
"company_address": "Example Str. 1\n10115 Berlin",
"consultation_number": "12345678901234",
"order_number": "ORD-001",
"certificate_url": "https://viesac.eu/cert/...?locale=en",
"certificate_xml_url": "https://viesac.eu/cert/.../xml",
"requested_at": "2026-02-13T12:00:00.000000Z",
...
}
4. List audits — GET /audits
List audits with filters. Query params: limit, date_from, date_to, country_code, vat_number, order_number, invoice_number.
curl -X GET "https://viesac.eu/api/v1/audits?limit=50&country_code=DE&date_from=2026-02-01" \
-H "Authorization: Bearer YOUR_API_KEY"Response (200):
{
"data": [
{
"reference_number": "VAC-20260216-ABC123",
"country_code": "DE",
"vat_number": "123456789",
"status": "valid",
"company_name": "Example GmbH",
"requested_at": "2026-02-13T12:00:00.000000Z",
...
}
],
"count": 1
}
5. Get audit — GET /audits/{reference_number}
Get full details of a single audit by its reference number.
curl -X GET "https://viesac.eu/api/v1/audits/VAC-20260216-ABC123" \
-H "Authorization: Bearer YOUR_API_KEY"Response (200):
{
"reference_number": "VAC-20260216-ABC123",
"country_code": "DE",
"vat_number": "123456789",
"status": "valid",
"vies": 1,
"company_name": "Example GmbH",
"company_address": "Example Str. 1\n10115 Berlin",
"consultation_number": "12345678901234",
"certificate_url": "https://viesac.eu/cert/...?locale=en",
"certificate_xml_url": "https://viesac.eu/cert/.../xml",
"certificate_urls": {"pdf_en":"...","pdf_locale":"...","xml":"..."},
"requested_at": "2026-02-13T12:00:00.000000Z",
...
}
404 if reference not found: {"error":"No audit found for this reference number."}
6. Update audit — PUT /audits/{reference_number}
Update order number, invoice number, comment, or monitoring for an existing audit. Changes are logged.
curl -X PUT "https://viesac.eu/api/v1/audits/VAC-20260216-ABC123" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"order_number":"ORD-002","comment":"Updated via API"}'Response (200): same shape as GET /audits/{reference_number}. 404 if reference not found.
7. Check partner — GET /partners/check?q=
Search by VAT (e.g. DE123456789) or company name. Returns full list per company with last status, last check date, and monitoring info if set.
curl -X GET "https://viesac.eu/api/v1/partners/check?q=DE123456789" \
-H "Authorization: Bearer YOUR_API_KEY"Response (200):
{
"data": [
{
"company_name": "Example GmbH",
"vat": "DE123456789",
"country_code": "DE",
"vat_number": "123456789",
"address": "Example Str. 1\n10115 Berlin",
"last_status": "valid",
"last_check_date": "2026-02-13T12:00:00.000000Z",
"monitoring": { "frequency": "month", "next_check_at": "2026-03-13T12:00:00.000000Z" }
}
],
"count": 1
}
If no partners match: data is [], count is 0, and message is included.
8. Download PDF certificate — GET /audits/{reference_number}/certificate
Download PDF certificate. Query: ?locale=en|de|fr. Available only when status is VALID.
curl -X GET "https://viesac.eu/api/v1/audits/VAC-20260216-ABC123/certificate?locale=en" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o certificate.pdfResponse (200):
Binary PDF file (Content-Type: application/pdf).
404 if reference not found or status not VALID: {"error":"Certificate is not available for this audit. Only audits with VALID status have certificates."}
9. Download XML certificate — GET /audits/{reference_number}/certificate/xml
Download technical certificate (VIES checkVatResponse). Available only when status is VALID.
curl -X GET "https://viesac.eu/api/v1/audits/VAC-20260216-ABC123/certificate/xml" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o certificate.xmlResponse (200):
XML content (Content-Type: application/xml).
404 if reference not found or status not VALID: same error as PDF endpoint.
VIESAC API webhooks
Webhooks are optional. When enabled for an API key, VIESAC will send HTTP POST callbacks to your URL when an audit is created and when its status changes.
Events
audit.created— sent right afterPOST /auditscreates an audit.audit.pending— status becamependingorlimited_valid.audit.completed— status becamevalid,invalid, orerror.audit.failed— status becameerror.
Payload
Each delivery includes an event envelope plus data shaped like GET /audits/{reference_number}.
{
"id": 123,
"event": "audit.completed",
"attempt": 1,
"created_at": "2026-03-31T12:00:00+00:00",
"data": {
"reference_number": "VAC-20260216-ABC123",
"country_code": "DE",
"vat_number": "123456789",
"status": "valid",
"vies": 1,
"company_name": "Example GmbH",
"company_address": "Example Str. 1\n10115 Berlin",
"consultation_number": "12345678901234",
"certificate_url": "https://viesac.eu/cert/...?locale=en",
"certificate_xml_url": "https://viesac.eu/cert/.../xml",
"certificate_urls": {"pdf_en":"...","pdf_locale":"...","xml":"..."},
"requested_at": "2026-02-13T12:00:00+00:00"
},
"meta": { "from_status": "pending", "to_status": "valid" }
}
Security (HMAC signature)
Each request is signed. Verify the signature before processing.
| Header | Description |
|---|---|
X-Viesac-Event | Event name. |
X-Viesac-Delivery | Unique delivery id. |
X-Viesac-Timestamp | Unix timestamp used in the signature. |
X-Viesac-Signature | sha256=<hex> from HMAC-SHA256(secret, timestamp + '.' + raw_body). |
// Pseudocode
expected = HMAC_SHA256(secret, timestamp + "." + rawBody)
constantTimeEquals("sha256=" + expected, signatureHeader)
Retries
If delivery fails due to timeouts or 5xx/429, VIESAC retries with backoff:
- 15 minutes
- 230 minutes
- 33 hours
- 46 hours
- 524 hours
Hard failures (most 4xx) disable webhooks temporarily to prevent queue buildup.