Skip to content

Quickstart

1. Try it without a key

The endpoints are open to anonymous callers at 20 requests per minute per IP, so you can evaluate them before signing up:

curl https://verify.orvel.dev/v1/vat/FR03552081317
curl https://verify.orvel.dev/v1/iban/DE89370400440532013000
curl "https://verify.orvel.dev/v1/phone/0612345678?region=FR"

2. Get a key

Take the Free plan on the Pricing page: 500 calls a month, no card. Checkout lands you on Your API key, which shows a key that looks like ev.sub_1abc…. Use it as a bearer token:

export EV_KEY=ev.sub_1abc.deadbeef

curl -H "Authorization: Bearer $EV_KEY" \
  https://verify.orvel.dev/v1/siren/552081317

Every answer carries the quota in its headers:

X-Plan: free
X-Usage-Used: 1
X-Usage-Quota: 500
X-Usage-Remaining: 499

3. Read the status, not the HTTP code

A well-formed request is 200 even when the identifier turns out to be fake. The verdict is in status:

curl -s -H "Authorization: Bearer $EV_KEY" \
  https://verify.orvel.dev/v1/vat/DE999999999 | jq '{status, reason}'
{ "status": "invalid", "reason": "the number is not registered for intra-EU trade" }

When a register is down you get upstream_unavailable, a Retry-After header, and no charge against your quota:

{ "status": "upstream_unavailable", "reason": "the member state register is unavailable", "retry_after_s": 60 }

Treat that as "unknown", never as "invalid".

4. Same tools from an agent

Point any MCP client at https://verify.orvel.dev/mcp with the same key:

{
  "mcpServers": {
    "eu-verify": {
      "url": "https://verify.orvel.dev/mcp",
      "headers": { "Authorization": "Bearer ev.sub_1abc.deadbeef" }
    }
  }
}

Details and per-client snippets: MCP server.

5. Check what you have used

curl -H "Authorization: Bearer $EV_KEY" https://verify.orvel.dev/v1/usage
{ "plan": "free", "used": 12, "quota": 500, "remaining": 488, "period": "2026-09" }

Quotas reset on the first of the month (UTC). Upgrade, downgrade and invoices are in the customer portal.