# Errors

Source: https://veriport.io/docs/errors (published 2026-10-24)

Every non-2xx answer is an `application/problem+json` document (RFC 9457). Branch on `code`, show `detail` to a human, keep `instance` for support. The `type` of each problem is this page’s address plus `#` and the code: it links to the row of that code below.

- A 4xx or 5xx is never counted against the quota.
- Validation errors carry `errors[]` with the parameter name and the rule it broke.
- 503s from VIES carry `retryAfter` (seconds) and the `Retry-After` header; a cached answer, when one exists, is a 200 with `source.stale: true` instead.
- Bulk requests answer 200 with one result per item; an item that failed is a problem document in its slot.

## The catalogue

Generated from the same list the code uses: a code cannot exist in the API without appearing here.

| Code | HTTP | Title | What to do |
|---|---|---|---|
| `invalid_parameter` | 400 | A parameter is missing or malformed | Read `detail` and `errors[]`: each entry names the parameter and the rule it broke. Nothing was counted against your quota. |
| `unauthorized` | 401 | The API key is missing, unknown or revoked | Send `Authorization: Bearer vp_live_…`. Keys are shown once at sign-up; a revoked key cannot be restored, create a new one. |
| `forbidden_for_tier` | 403 | This option is not included in your tier | The `requester` option (consultation number) and the `record` option (a stored validation record) need prepaid credits or the monthly plan; the bulk endpoints need the monthly plan. See /pricing. |
| `not_found` | 404 | No such resource | Check the path against /openapi.json. Country codes are ISO 3166-1 alpha-2 (Greece is `EL` for VAT, `GR` for IBAN). |
| `quota_exceeded` | 402 | Monthly allowance and credits are used up | The free allowance resets on the first of the month (UTC). Buy a credit pack or the monthly plan at /pricing; the key stays the same. |
| `rate_limited` | 429 | Too many requests per second | Honour `Retry-After` and the `RateLimit-*` headers. Free keys may send 2 requests a second; the monthly plan 10. Use the bulk endpoint for lists. |
| `vies_unavailable` | 503 | VIES or the member state is unavailable and no cached answer exists | The Commission’s service or that country’s tax administration did not answer and we hold no previous answer for this number. Retry after `Retry-After` seconds; the call was not counted. |
| `vies_blocked` | 503 | VIES refused the request (concurrency or blocking) | VIES answered MS_MAX_CONCURRENT_REQ, GLOBAL_MAX_CONCURRENT_REQ or a blocking code. Retry after `Retry-After` seconds; the call was not counted. |
| `checkout_closed` | 503 | Paid checkout is not open yet | Join the waitlist on /pricing; you will be e-mailed when the merchant of record approves the site. The free tier works now. |
| `store_unavailable` | 503 | The database is not configured | Sign-ups and keys need a database; this deployment runs without one. Try again later. |
| `upstream_unavailable` | 503 | The public registry did not answer and no cached answer exists | The French company-registry APIs (recherche-entreprises.api.gouv.fr, INSEE Sirene) did not answer in time or refused the request. Retry after `Retry-After` seconds; the call was not counted. |
| `unprocessable_file` | 422 | The uploaded rows cannot be turned into a return | Read `errors[]`: each entry names the row (1-based, header excluded) and the rule it broke (unknown country, rate not in the table for the period, VAT does not equal net × rate, date outside the period). Fix the export and resend; nothing was counted. |
| `payload_too_large` | 413 | Too many rows or too many bytes | A request body is limited to 4.5 MB (4,500,000 bytes, the hosting platform’s limit); one OSS return to 50,000 rows. Aggregate per country and rate before sending, or split the quarter by month; for an e-invoice, send the XML rather than a PDF carrying large attachments. |
| `einvoice_unsupported` | 422 | The invoice uses a feature the e-invoice writers do not produce | Nothing is ever dropped silently: a field the writers cannot put in the file is refused. Read `feature` and `path` (the first one) and `unsupported[]` (all of them), remove or change those fields, and resend. The list of what v1 does not write is on /einvoice-api. Nothing was counted. |
| `einvoice_invalid` | 422 | The invoice breaks the rules of its format | Read `violations[]`: each names the published rule (BR-*, BR-DE-*, PEPPOL-*, or VP-* for Veriport’s own checks of national practice), its path in your JSON (or the XPath in the produced file) and what it requires. No file was produced and nothing was counted. |
| `einvoice_unreadable` | 422 | The file is not an e-invoice the API can read | Send a UBL 2.1 Invoice or CreditNote, a UN/CEFACT CII D16B CrossIndustryInvoice, or a ZUGFeRD / Factur-X PDF with its XML embedded; as the raw body (Content-Type application/xml or application/pdf) or as the `file` part of multipart/form-data. Nothing was counted. |
| `idempotency_conflict` | 409 | The Idempotency-Key is in use | The same `Idempotency-Key` was sent with a different body or query (a key is bound to one request), or a request with that key is still being processed. Send a new key for a new request; retry the same request after `Retry-After` seconds when it was still in progress. Nothing was counted. |
| `internal` | 500 | Unexpected error | Nothing was counted. If it repeats, write to hello@veriport.io with the `instance` id. |

## Example

A free key asking for a consultation number:

```json
{
  "type": "https://veriport.io/docs/errors#forbidden_for_tier",
  "title": "This option is not included in your tier",
  "status": 403,
  "detail": "The `requester` option asks VIES for a consultation number, the evidence a tax audit accepts; it is included with prepaid credits and the monthly plan. See https://veriport.io/pricing.",
  "instance": "req_7Qx2mZk9Lp",
  "code": "forbidden_for_tier"
}
```

## What is not an error

An invalid VAT number or IBAN is a normal answer: 200 with `valid: false`. A VAT number that cannot be one (wrong structure or check digit) answers 200 with `valid: false`, `source.kind: "structure_only"` and `upstream.status: "not_called"`, and is not counted. A member state that is down with a cached answer available answers 200 with `source.kind: "cache"`, `source.stale: true` and `upstream.status: "member_state_unavailable"`. A `GB` prefix is not aliased to `XI`: it answers `country_unknown`; check UK numbers with HMRC’s free service (gov.uk/check-uk-vat-number); Northern Ireland goods traders send `XI`.

## Questions

### Why is a 503 not counted?

Because you received no answer. Only a 200 with a live, cached or table answer costs a call.

## Read next

- [Reference: EU VAT number validation](https://veriport.io/docs/vat-validation)
- [Rate limits and quotas](https://veriport.io/docs/rate-limits)
