# VAT Validation REST API Example

## Validate EU VAT Numbers with a REST API

To validate an EU VAT number via REST API, send a GET request to `https://api.eurovalidate.com/v1/vat/{vat_number}` with your API key in the `X-API-Key` header. The response includes the validation status, company name, address, and a confidence score indicating data freshness. No SOAP, no XML parsing, no WSDL downloads. One HTTP call, JSON response, under 300ms.

## curl Example

The fastest way to test. Replace `YOUR_API_KEY` with a free key from [eurovalidate.com](https://eurovalidate.com).

### Valid VAT number

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://api.eurovalidate.com/v1/vat/NL820646660B01
```

Response:

```json
{
  "vat_number": "NL820646660B01",
  "country_code": "NL",
  "status": "valid",
  "company_name": "ABN AMRO BANK N.V.",
  "company_address": "GUSTAV MAHLERLAAN 00010\n1082PP AMSTERDAM",
  "request_id": "req_abc123",
  "meta": {
    "confidence": "high",
    "source": "vies_live",
    "cached": false,
    "response_time_ms": 247,
    "last_verified": "2026-04-08T09:00:00Z",
    "upstream_status": "ok"
  }
}
```

### Invalid VAT number

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://api.eurovalidate.com/v1/vat/DE000000000
```

Response:

```json
{
  "vat_number": "DE000000000",
  "country_code": "DE",
  "status": "invalid",
  "company_name": null,
  "company_address": null,
  "request_id": "req_def456",
  "meta": {
    "confidence": "high",
    "source": "vies_live",
    "cached": false,
    "response_time_ms": 189,
    "upstream_status": "ok"
  }
}
```

## Node.js Example

Install the SDK:

```bash
npm install @eurovalidate/sdk
```

```javascript
import { EuroValidate } from '@eurovalidate/sdk';

const ev = new EuroValidate('YOUR_API_KEY');

const result = await ev.validateVat('FR40303265045');

if (result.status === 'valid') {
  console.log(`Company: ${result.company_name}`);
  console.log(`Cached: ${result.meta.cached}`);
  console.log(`Confidence: ${result.meta.confidence}`);
} else {
  console.log(`VAT ${result.vat_number} is ${result.status}`);
}
```

## Python Example

Install the SDK:

```bash
pip install eurovalidate
```

```python
from eurovalidate import Client

client = Client(api_key="YOUR_API_KEY")
result = client.validate_vat("IT00159560366")

if result.status == "valid":
    print(f"Company: {result.company_name}")  # FERRARI S.P.A.
    print(f"Response time: {result.meta.response_time_ms}ms")
else:
    print(f"VAT {result.vat_number} is {result.status}")
```

## Unified Validation (VAT + IBAN + EORI in one call)

For checkout flows where you need multiple checks at once:

```bash
curl -X POST https://api.eurovalidate.com/v1/validate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vat_number": "NL820646660B01",
    "iban": "DE89370400440532013000",
    "eori_number": "NL810002383"
  }'
```

This returns all three results in a single response, saving you three round trips.

## Response Fields Explained

| Field | Type | Description |
|-------|------|-------------|
| `vat_number` | string | The VAT number as submitted (normalized) |
| `country_code` | string | ISO 3166-1 alpha-2 (or EL for Greece) |
| `status` | string | `valid`, `invalid`, `error`, or `unavailable` |
| `company_name` | string or null | Registered company name from VIES |
| `company_address` | string or null | Registered address |
| `meta.confidence` | string | `high`, `medium`, `low`, or `unknown` |
| `meta.source` | string | `vies_live` or `vies_cached` |
| `meta.cached` | boolean | Whether the response came from cache |
| `meta.response_time_ms` | integer | Time to produce the response |

## Latency

| Scenario | Typical Time |
|----------|-------------|
| Cached response (Redis hit) | 1-5 ms |
| Live VIES call | 150-300 ms |
| VIES slow country (DE) | 500-1000 ms |
| IBAN (offline MOD-97) | 65 ms |

Cached responses are served for 24 hours after the first live check. Second and subsequent requests for the same VAT number hit the cache.

## Common Pitfalls

**Germany and Spain never return company names.** These countries redact trader data under national data protection law. Your code should handle `company_name: null` for DE and ES VAT numbers.

**Greece uses EL, not GR.** VIES uses `EL` as the country prefix for Greece, but ISO 3166 uses `GR`. The API accepts both: `EL094019245` and `GR094019245` resolve to the same company.

**Format validation happens locally.** If you send `DE12345` (too short for Germany, which requires 9 digits), the API returns HTTP 400 immediately without calling VIES. This saves your quota.

**Rate limits are per API key.** Free tier: 100 requests/hour. Headers `X-RateLimit-Remaining` and `X-RateLimit-Reset` tell you where you stand.

## Error Handling

The API uses RFC 7807 Problem Details for errors:

```json
{
  "type": "https://eurovalidate.dev/errors/http",
  "title": "VAT number for DE must be 9 characters (got 5)",
  "status": 400,
  "detail": "VAT number for DE must be 9 characters (got 5)..."
}
```

Handle these status codes:

| Code | Meaning | Action |
|------|---------|--------|
| 200 | Success (check `status` field) | Process result |
| 400 | Bad format | Fix input |
| 401 | Invalid API key | Check key |
| 429 | Rate limit | Wait, retry after `Retry-After` |
| 502 | VIES upstream down | Use cached result or retry |

## Authentication

Pass your API key in the `X-API-Key` header:

```
X-API-Key: ev_live_your_key_here
```

Get a free key (no credit card): [eurovalidate.com](https://eurovalidate.com)

## Pricing

| Tier | Price | Requests |
|------|-------|----------|
| Free | $0 | 100/hour |
| Starter | $19/mo | 5,000/hour |
| Growth | $49/mo | 25,000/hour |
| Scale | $149/mo | 100,000/hour |

## Next Steps

- [Full API documentation](https://api.eurovalidate.com/docs)
- [Validate VAT in Node.js](https://blog.eurovalidate.com/validate-eu-vat-nodejs)
- [Validate VAT in Python](https://blog.eurovalidate.com/validate-eu-vat-python)
- [Add VAT validation to Stripe checkout](https://blog.eurovalidate.com/stripe-vat-validation-tutorial)
- [Get a free API key](https://eurovalidate.com)
