Verify Error Handling
When an error occurs, the Verify API returns a structured error with the following fields:
How failures surface: sync vs. async
Where an error shows up depends on which endpoint you use.
- Synchronous (
/verify) waits for processing to finish, so every failure — both request validation and document processing — comes back as an HTTP error response with the fields above. The HTTP status codes below apply to this endpoint. The wait is capped at 5 minutes on both engines. If the run outlives it, the response is usually a504 Gateway Timeoutfrom the load balancer, which has no Extend error body and norunId. Less often it is a500 INTERNAL_ERRORwithretryable: falsewhose body carriesrunId. In both cases the run keeps processing, and resubmitting starts a second run.verify_agenticruns often exceed 5 minutes, so use the asynchronous endpoint for them. - Asynchronous (
/verify_runs) returns200with a verify run as soon as the job is accepted. Request-level problems (invalid request, auth, a file URL that cannot be downloaded) still return an HTTP error at creation time, but document processing failures are not HTTP errors — the run instead reachesstatus: "FAILED"with afailureReasonandfailureMessage(one of the failure reasons below), which you read when you poll.
Production integrations should use the asynchronous /verify_runs endpoint and check status on the returned run. Webhook events for verify runs are not available yet, so poll GET /verify_runs/{id} until the status is PROCESSED, FAILED, or CANCELLED.
Failure reasons
These codes describe why a verify run failed. On the sync endpoint they appear in the error body’s code field; on the async endpoint they appear as the run’s failureReason. The structured error’s retryable flag is authoritative at runtime.
Additional failure reasons may be added in the future. Handle unknown values gracefully.
Transient failures on the async endpoint are retried automatically before the run is marked FAILED, so a FAILED run with a retryable reason has already been attempted more than once. Retrying by creating a new run is still reasonable after a short delay.
HTTP status codes
These HTTP status codes are returned by the synchronous /verify endpoint. On the asynchronous /verify_runs endpoint, only request-level errors are returned at creation time — processing failures surface on the run as status: "FAILED".
400 Bad Request
Returned when required fields are missing (for example file), the file locator is invalid or points at a private network, the file at url could not be downloaded, config.engineVersion is unsupported, config contains a key that is not recognised (including the removed signalAllowlist and policy), advancedOptions.requireParsing is false on verify_agentic, metadata exceeds 10 KB, or a list filter or pagination token is invalid. The code is INVALID_REQUEST or the name of the failed validation.
401 Unauthorized
Returned when the API token is missing or invalid.
402 Payment Required
Returned when the organization is blocked from creating runs because of an overdue balance or exhausted credits (USAGE_BLOCKED).
403 Forbidden
Returned when the API key does not have permission to create or read document-processing runs.
404 Not Found
Returned when the run ID does not exist in this workspace or has been deleted, when a referenced file has been purged (FILE_PURGED), and when Verify is not enabled for your organization. During the beta, every verify endpoint returns 404 NOT_FOUND for organizations that have not been granted access; contact support@extend.ai to request it.
422 Unprocessable Entity
Returned when the file cannot be verified: it is not a supported type (FILE_TYPE_NOT_SUPPORTED), or no check applies to it (NO_APPLICABLE_SIGNALS).
429 Too Many Requests
Returned when you exceed the rate limit. Retry with exponential backoff. See Rate Limits.
500 Internal Server Error
Returned as INTERNAL_ERROR when an internal error stops the run (for example, a detection model, content analysis, or the assessment is unavailable) or the synchronous request exceeds its 5-minute timeout, and as PARSE_FAILED when the document could not be parsed. Retry with exponential backoff when retryable is true. A timeout returns retryable: false: the run continues in the background and the error body includes its runId, so fetch that run instead of resubmitting the file.
504 Gateway Timeout
Returned by the load balancer when a synchronous /verify request runs past 5 minutes. The response has no Extend error body and no runId. The run continues in the background, so don’t resubmit the file. Use the asynchronous /verify_runs endpoint for verify_agentic and for long documents.
Handling errors
The async pattern below creates a run, polls it to a terminal state, and branches on the outcome.
Python
TypeScript
Java
Go
Cancelling a run
POST /verify_runs/{id}/cancel moves a PROCESSING run to CANCELLED and stops in-flight work. Cancelling a run that has already finished, failed, or been cancelled is a no-op that returns the run unchanged, so it is safe to call from a timeout handler without checking status first. A cancelled run never has output.
Deleting a run
DELETE /verify_runs/{id} removes a run and everything derived from its document: the result, the evidence artifacts, and the embedded parse. A run that is still processing is cancelled first. The input file is never deleted, even a zero-retention file another run is using. After deletion the run returns 404 from every read and no longer appears in GET /verify_runs. The response is { "id": "vr_..." }.
For the general error format and codes shared by every endpoint, see Error Handling.

