Skip to content

Errors

Every machine-readable code the Validation API can return, its HTTP status, what it means, what to do about it, and whether repeating the request can help.

The shape of an error

Errors are RFC 9457 problem documents, sent as application/problem+json. The code field is the contract: branch on it. title is English prose and may be reworded without notice.

json
{
  "type": "https://edocumenttools.com/en/developers/errors#unknown_target",
  "title": "No such validation target.",
  "status": 422,
  "code": "unknown_target",
  "requestId": "req_8f3c1d6a4b2e"
}

type is a URL that resolves to the section of this page describing that code. requestId is the same value the X-Request-Id header carries; quote it when you report a problem.

Some errors also carry detail, a sentence about this particular request. Nothing derived from your document ever appears in one — no filename, no element content, no party name, no amount.

An invalid document is not an error

Worth repeating on the page about errors: a document that runs and fails validation is answered with 200 OK and a report. Everything on this page describes the API being unable to execute your request, never a conclusion about an invoice.

The codes

api_disabledHTTP 404

The Validation API is not switched on for this deployment.

What to do: Nothing you send will change this. Check you are calling the right host.

Safe to retry? No — the same request will fail again

unauthorizedHTTP 401

No key, a malformed key, an unknown key, a revoked key, or a key whose project is suspended. The five are answered identically on purpose, so that probing tells an attacker nothing.

What to do: Check the Authorization header is present and reads `Bearer <key>`, and check the key is still active in the dashboard.

Safe to retry? No — the same request will fail again

forbidden_targetHTTP 403

The key is valid, the target exists, and this key is not permitted to use it.

What to do: Use a target from the set the catalogue endpoint returns for this key, or create a key without the restriction.

Safe to retry? No — the same request will fail again

not_foundHTTP 404

No such API route.

What to do: Check the path and the method. The only validation route is POST /api/v1/validate.

Safe to retry? No — the same request will fail again

invalid_requestHTTP 400

The request could not be understood: a missing field, an unexpected field, or a body that is not multipart.

What to do: Send exactly `target` and `file` as multipart/form-data. The problem document names what was wrong.

Safe to retry? No — the same request will fail again

duplicate_fieldHTTP 400

A form field was sent more than once.

What to do: Send one target and one file. A repeated field is refused rather than resolved, because picking one silently would validate something you did not choose.

Safe to retry? No — the same request will fail again

unknown_targetHTTP 422

No target has that id.

What to do: Ids are case-sensitive and frozen. Check the catalogue.

Safe to retry? No — the same request will fail again

target_input_mismatchHTTP 422

The document's root element is not one this target accepts.

What to do: Check the document roots listed for the target. Sending a CII document to a UBL target is the usual cause.

Safe to retry? No — the same request will fail again

unsupported_media_typeHTTP 415

The uploaded bytes are neither XML nor PDF, as determined from the bytes themselves.

What to do: Check you are sending the document and not, for example, a JSON envelope containing it.

Safe to retry? No — the same request will fail again

document_unreadableHTTP 422

The bytes are the right kind but could not be parsed, or were refused by the security screen — a declared DOCTYPE or XML entities, for instance.

What to do: Parse the document locally first. No external resource is ever fetched on behalf of a document, so an external entity is a refusal rather than a fetch.

Safe to retry? No — the same request will fail again

payload_too_largeHTTP 413

The upload is larger than the global cap or than this target accepts.

What to do: See the size each target accepts on the limits page.

Safe to retry? No — the same request will fail again

rate_limitedHTTP 429

Too many requests for this key in a short window.

What to do: Slow down. This clears within a minute and is not related to your daily allowance. Serialise or space out concurrent workers.

Safe to retry? After the window named below

quota_exceededHTTP 429

The account's daily validation allowance is used up.

What to do: Wait for the reset at 00:00 UTC, or ask for a larger allowance. Retrying before the reset cannot succeed.

Safe to retry? After the window named below

capacity_unavailableHTTP 503

The service could not take the work: the validation queue is full, the engine is still starting, or it is shutting down.

What to do: Back off and try again. This is the one 5xx that consumes no allowance — either the work never started, or the allowance unit was refunded when the queue refused it.

Safe to retry? With backoff, and see the note on repeated validations

validation_timeoutHTTP 504

Validation started but did not finish within the time limit.

What to do: The document was executed, so a retry is a second validation. Check the document size and complexity before repeating it.

Safe to retry? With backoff, and see the note on repeated validations

internal_errorHTTP 500

Something failed that should not have.

What to do: Keep the requestId and report it. A retry may or may not have already consumed a validation.

Safe to retry? With backoff, and see the note on repeated validations

Retrying

There is no idempotency key. A repeated POST /api/v1/validate is a second validation: it is admitted against your daily allowance, it runs, and it counts. A client that retries a timeout three times has used four validations.

That divides the failures into three kinds, and each code above says which kind it is.

  • Do not retry. Every 4xx about the request itself — a bad key, an unknown target, a malformed upload. The same bytes will fail the same way. Fix the request.
  • Retry after the window.rate_limited clears within a minute; quota_exceeded clears at 00:00 UTC. Both send Retry-After. Retrying sooner cannot succeed and only consumes rate-limit budget.
  • Retry with backoff, knowing what it costs.capacity_unavailable is the safe one: either the work was refused before it started, or it was refused by a queue that had already admitted it and the allowance unit was given back. Nothing was consumed either way. validation_timeout and internal_error are not safe in that sense — the document reached the executor and the unit is spent — so retry them deliberately rather than automatically, with exponential backoff and a low ceiling on attempts.

Practically: retry capacity_unavailable automatically, retry the other two at most once, and never retry a 4xx.

Headers

  • X-Request-Id — on every response, success or failure.
  • Retry-After — seconds, on rate_limited and quota_exceeded. Use it rather than guessing. capacity_unavailable does not carry one, because how long the queue will stay full is not something this deployment can honestly predict.
  • X-Quota-Limit, X-Quota-Remaining, X-Quota-Reset — on a validate response that reached the daily allowance gate: that is, on every success and on quota_exceeded. A request refused earlier — a bad key, a rate limit — never reached the gate and carries no quota headers. See Rate limits and quota.