API Documentation

REST API for VAT validation audits. All requests require Bearer authentication. Register for API key.

Authentication

Use your API key in the Authorization header with the Bearer scheme:

Authorization: Bearer viesac_your_api_key

Never expose your API key in client-side code or public repositories.

Base URL

All endpoints are relative to:

https://viesac.eu/api/v1

Endpoints

GET
/validate
New

Quick VAT status check — does not create an audit. Powered by VIESAC multi-source intelligence: VIES (European Commission), 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:

  • vat (pakollinen) — Full VAT including country prefix (e.g. DE123456789)

Response fields:

  • vat — Full VAT (country + number)
  • country_code — Country code (e.g. DE)
  • vat_number — VAT number without country prefix
  • status — Validation result: valid, invalid, or audit_required
  • checked_at — ISO 8601 timestamp

Rate limits

Free plan: 10 requests / hour

Paid plans: rate limits depend on your plan tier.

Exceeded: HTTP 429 with retry_after (seconds) and upgrade_url.

GET
/account

Get account stats: plan, total audits, audits this month, remaining this month.

Response:

  • plan, plan_label — Current plan
  • monthly_limit — Monthly limit (null = unlimited)
  • requests_total — Total audits (all time)
  • requests_this_month — Audits this month
  • requests_remaining — Available this month
  • upgrade_url — Link to upgrade plan
POST
/audits

Create a new VAT validation audit. Validates via VIES. If VIES is down, VIESAC AI validates with proprietary data; the audit waits for VIES to return and retrieves full data plus the official certificate.

Body (JSON):

  • vat_number (pakollinen) — VAT number (with or without country prefix; system normalizes automatically)
  • country_code (valinnainen) — 2-letter ISO (e.g. DE, FR). Enter if vat_number is without prefix.
  • requester_vat (valinnainen) — Requester VAT (e.g. DE123456789). If omitted, your primary VAT is used. If provided and already in your profile, that one is used; if new, it is created in your profile and used.
  • company_name (valinnainen) — Company name. If empty, VIESAC AI fills it in.
  • company_address (valinnainen) — Company address. If empty, VIESAC AI fills it in.
  • order_number (valinnainen) — Your order reference if this validation is linked to an order.
  • invoice_number (valinnainen) — Your invoice reference if this validation is linked to an invoice.
  • comment (valinnainen)
  • monitoring (valinnainen) — Enable re-check monitoring for this partner: false (no monitoring), day, week, month, quarter, year. When set, the partner is added or updated in monitoring with the next check date.
  • audit_details (valinnainen) — Your data in a convenient format (e.g. XML, JSON, CSV). We detect the format and display it in the audit details.
  • method (valinnainen) — Source: api (default), woocommerce, magento, make. Used for analytics. If omitted and the request User-Agent contains "Make" or "Integromat", make is set automatically.
PUT
/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):

  • order_number (valinnainen) — Order reference
  • invoice_number (valinnainen) — Invoice reference
  • comment (valinnainen)
  • monitoring (valinnainen) — false to disable monitoring for this partner, or day, week, month, quarter, year to set frequency.

404 if reference not found: {"error":"No audit found for this reference number."}

GET
/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:

  • q (pakollinen) — VAT (e.g. DE123456789) or company name (partial match)

Response:

  • data — Array of objects: company_name, vat, country_code, vat_number, address, last_status, last_check_date, monitoring (null or { "frequency": "month", "next_check_at": "..." })
  • count — Number of partners found
GET
/audits

List audits with filters. Default limit 100, max 500.

Query params:

  • limit — Number of results (default 100)
  • date_from — YYYY-MM-DD
  • date_to — YYYY-MM-DD
  • vat_number — Partial search
  • order_number — Partial search
  • invoice_number — Partial search
  • country_code — Exact match (e.g. DE)
GET
/audits/{reference_number}

Get full details of a single audit, including certificate_url and details_url.

GET
/audits/{reference_number}/certificate

Download PDF certificate. Returns binary PDF with Bearer auth.

?locale= (valinnainen) — Certificate language: en (default), de, fr. Example: /audits/VAC-20260216-ABC123/certificate?locale=de

GET
/audits/{reference_number}/certificate/xml

Download technical certificate (XML). Original VIES checkVatResponse. 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.

Status & vies

status: valid (VIES confirmed), limited_valid (VIESAC VALID — fallback when VIES unavailable), pending (no data yet), invalid (negative), error.

vies: 1 = VIES VALID (certificate), 0 = negative/error, 2 = VIES unavailable — audit awaits VIES response; when received, status updates automatically.

Examples

Each endpoint shows request and response together.

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, 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": "Rate limit exceeded. Free plan allows 10 VAT validations per hour. Upgrade your plan for higher limits.",
  "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": 38,
  "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.pdf

Response (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.xml

Response (200):

XML content (Content-Type: application/xml).

404 if reference not found or status not VALID: same error as PDF endpoint.

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 after POST /audits creates an audit.
  • audit.pending — status became pending or limited_valid.
  • audit.completed — status became valid, invalid, or error.
  • audit.failed — status became error.

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.

X-Viesac-Event: event name

X-Viesac-Delivery: delivery id

X-Viesac-Timestamp: unix timestamp

X-Viesac-Signature: sha256=<hex> of 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:

  • 5 minutes
  • 30 minutes
  • 3 hours
  • 6 hours
  • 24 hours

Hard failures (most 4xx) disable webhooks temporarily to prevent queue buildup.