Home / VAT API / Integrations / Python

Python

Python EU VAT Validation API

Validate EU VAT numbers from any Python backend — Django, Flask, FastAPI, or scripts — with a single HTTP call using requests or httpx. Returns live VIES registration status, company name, and address in under 100ms.

VIES-backedSub-100ms cachedFree plan available27 EU countries

Quick start

CURL

curl -H "Authorization: Bearer YOUR_API_KEY" \
  http://localhost:3000/api/v1/validate/DE/DE123456789

Code example

Full integration example including error handling for service_unavailable responses from VIES.

Python (requests)

import requests
import os

TAXID_API_KEY = os.getenv("TAXID_API_KEY")

def validate_vat(country: str, vat_number: str) -> dict:
    """Validate an EU VAT number. Returns valid, status, company_name."""
    resp = requests.get(
        f"http://localhost:3000/api/v1/validate/{country}/{vat_number}",
        headers={"Authorization": f"Bearer {TAXID_API_KEY}"},
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()

result = validate_vat("DE", "DE123456789")
if result["valid"]:
    print(f"Active EU business: {result['company_name']}")
elif result["status"] == "service_unavailable":
    raise RuntimeError("VIES unavailable — retry later")
else:
    print("Invalid VAT number")

Python (httpx async)

import httpx
import os

TAXID_API_KEY = os.getenv("TAXID_API_KEY")

async def validate_vat(country: str, vat_number: str) -> dict:
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(
            f"http://localhost:3000/api/v1/validate/{country}/{vat_number}",
            headers={"Authorization": f"Bearer {TAXID_API_KEY}"},
        )
        resp.raise_for_status()
        return resp.json()

# Django async view or FastAPI endpoint:
# result = await validate_vat("DE", "DE123456789")
# if result["valid"]: ...

API response

The TaxID API returns a consistent JSON response for every validation:

200 OK — valid numbervalid
{
  "valid": true,
  "status": "active",
  "country_code": "DE",
  "vat_number": "DE123456789",
  "company_name": "Example GmbH",
  "company_address": "Musterstraße 1, 10115 Berlin",
  "request_date": "2026-05-10T00:00:00.000Z",
  "cached": false,
  "request_id": "req_01j..."
}
active

VAT number is valid and the business is registered

invalid

VAT number format is wrong or not registered in VIES

service_unavailable

VIES or the national authority is temporarily down — retry later, do not silently zero-rate

Implementation steps

  1. 1

    Get a free TaxID API key

    Sign up at taxid.dev/signup. No credit card required. Store your API key as an environment variable (TAXID_API_KEY) using python-dotenv or your framework's secrets management — never hardcode it.

  2. 2

    Call the API with requests or httpx

    Use the requests library for synchronous code (Django, Flask) or httpx for async code (FastAPI, Starlette). Both libraries let you pass the Authorization header and parse the JSON response in two lines.

  3. 3

    Parse the JSON response

    The API returns a dict with valid (bool), status (str), company_name, and company_address. Check data['valid'] is True for an active EU business. The status field can be 'active', 'invalid', 'not_found', or 'service_unavailable'.

  4. 4

    Handle service_unavailable separately from invalid

    VIES has occasional downtime. Raise a distinct exception for status 'service_unavailable' so your code handles it differently from a genuinely invalid VAT number. A good pattern: log the event, charge standard VAT, and queue the customer for re-validation once VIES recovers.

Frequently asked questions

Which Python library should I use to call the TaxID API?

Use requests for synchronous Django or Flask apps. Use httpx for async FastAPI or Starlette apps. Both are straightforward — import the library, pass the Authorization header, and call resp.json(). No special SDK needed.

Can I use the TaxID API in a Celery background task?

Yes. Celery tasks run synchronously (unless you use gevent/eventlet), so use the requests library. This is a good pattern for subscription re-validation: queue a Celery task for each customer with tax_exempt status and re-validate their VAT number monthly.

How do I validate multiple EU VAT numbers in one Python request?

Use the batch endpoint: POST /api/v1/validate with a JSON body containing a 'numbers' list of up to 25 dicts, each with 'country' and 'vat' keys. Results are returned in the same order, processed in parallel on the TaxID side.

How do I set a request timeout for the TaxID API in Python?

Pass timeout=10 to requests.get() or httpx.get(). This gives the API up to 10 seconds to respond, which covers VIES latency even during slow periods. Always set a timeout — without one, a VIES timeout will hang your worker indefinitely.

Country-specific API docs:

Start validating EU VAT numbers in Python

Free plan — 100 validations/month. No credit card required.

Other integrations

Stripe

Validate EU VAT numbers before applying Stripe reverse-charge

Shopify

EU VAT validation for Shopify B2B storefronts

Node.js

EU VAT validation in Node.js with a single HTTP call

PHP

PHP EU VAT number validation via REST API — cURL or Guzzle