---
title: "Verification workflow"
url: https://docs.agentsverify.dev/guides/verification-workflow
---

# Verification workflow

## Customer workflow

[](https://docs.agentsverify.dev/guides/verification-workflow#customer-workflow)

Base URL: `https://api.agentsverify.dev`. These six operations use your existing workspace and credits. Manage your account, API key and purchases in the [dashboard](https://app.agentsverify.dev/dashboard). Use a server-side HTTP client for application integrations. The self-hosted interactive reference can make customer API requests with an API key from the documentation site. CSV upload is a separate PUT to the returned storage URL; it is not performed automatically by the API reference. Dashboard session origins remain separate. Requests use your workspace and normal credit rules.

1.  **Authenticate and check credits.** Send your key in `X-API-Key` to the API only. `GET /v1/credits` returns `{"credits": <available balance>}`. This is a current balance, not a reservation or guarantee of funding for a later submission. Keep the key out of URLs, replies, application browser bundles and logs. In the API reference, enter it only in the authentication field; it is not persisted across page reloads or sent through a third-party proxy.
2.  **Prepare one CSV.** Use one-column UTF-8 CSV, optionally with a BOM and an explicit first-record header such as `email`. Standard CSV quoting and LF/CRLF are supported. All address records must be syntactically valid; blank records, extra columns and malformed addresses reject the whole file before checks or credit holds. Duplicates are checked once. `GET /v1/verifications` reports the current file-byte and row limits alongside saved history.
3.  **Create or recover the verification.** Save a UUID request identity, then send bodyless `POST /v1/verifications` with `Idempotency-Key` and `X-Upload-Content-Length` computed from the CSV’s UTF-8 bytes. HTTP 201 creates a verification; HTTP 200 recovers the existing one. Save the returned `id`. Also send optional `X-Upload-Filename` with the percent-encoded local basename (for example `contacts%20October.csv`) so dashboard history retains that name. Do not send local directory paths. A one-row CSV remains an upload in history.
4.  **Upload the CSV.** When the receipt contains `upload`, PUT raw CSV bytes to `upload.url`, using `Content-Type: text/csv` and, for a whole-file transfer, `Content-Range: bytes 0-<last byte index>/<total bytes>`. This is a storage resumable-upload URL, not an API endpoint. Send no API key or Authorization header to storage. HTTP 200/201 confirms durable receipt; HTTP 308 means the transfer is incomplete. After HTTP 200/201, status may briefly remain `uploading` while the backend detects the completed transfer. Continue polling, respecting `Retry-After`; do not re-upload after a confirmed transfer. Preserve the same Idempotency-Key to recover an interrupted API creation; use the storage protocol or the Python client to resume interrupted bytes. [Transfer examples](https://docs.agentsverify.dev/quickstart.md) explain the two stages. Whole-file validation and processing start automatically.
5.  **Read progress and results.** Poll `GET /v1/verifications/{id}`, respecting `Retry-After`. Read `issue` for actionable guidance; `credits_required` means adding credits resumes an underfunded file without re-uploading it. Download `GET /v1/verifications/{id}/results` for the available finalized CSV rows, including partial results. The columns are `email,result,message,checked_at`. A header-only CSV means no outcomes are available yet. Saved results can be read again without starting another check. Detail and history include `created_at` and nullable `completed_at`. Completion is recorded once all input processing, address outcomes and credit settlement finish, including cancellation or failure. It excludes notification delivery and archival. Subtract `created_at` for total elapsed time, including upload, preparation and queueing. `completed_at` is null while unfinished or for historical jobs without a recorded completion timestamp; `checked_at` remains the separate per-address result timestamp.
6.  **Recover or cancel.** Retry uncertain creation responses with the same UUID Idempotency-Key. A new identity creates another verification and can charge again. Use bodyless `POST /v1/verifications/{id}/cancel` to cancel remaining work; settlement and refunds can continue while status is `cancelling`.

## Outcomes, credits and errors

[](https://docs.agentsverify.dev/guides/verification-workflow#outcomes-credits-and-errors)

*   **Valid:** The address passed our verification checks and is assessed as safe to email, with low expected bounce risk. Delivery is not guaranteed.
*   Outcomes are `valid`, `invalid`, `catch_all`, `unknown` and `error`. Unknown is inconclusive; catch-all is risky. Final unknown results refund their held credit. Other finalized outcomes cost one credit. Unchecked cancelled addresses are refunded and excluded from the results CSV.
*   Verification status is `uploading`, `preparing`, `waiting`, `verifying`, `cancelling`, `completed`, `completed_with_errors`, `cancelled` or `failed`. A failed file has an actionable issue; do not keep polling it as if it were active.
*   Errors use `issue.code`, `issue.message` and `request_id`. Fix authentication on 401; fix the specified request or CSV defect before retrying. For 429 or 503, respect `Retry-After` and reuse the original request identity.
*   Processing time varies with queue and receiver limits. Backend retries are automatic; resubmitting is not a polling or retry mechanism.
