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.
{
"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_limitedclears within a minute;quota_exceededclears at 00:00 UTC. Both sendRetry-After. Retrying sooner cannot succeed and only consumes rate-limit budget. - Retry with backoff, knowing what it costs.
capacity_unavailableis 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_timeoutandinternal_errorare 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, onrate_limitedandquota_exceeded. Use it rather than guessing.capacity_unavailabledoes 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 onquota_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.