--- title: "For AI agents" url: https://docs.agentsverify.dev/agents --- # For AI agents Give your agent the [complete workflow and generated API reference](https://docs.agentsverify.dev/api-reference.md). It describes all six customer operations, authentication, CSV uploads, credits, retries and results. ## Documentation formats [](https://docs.agentsverify.dev/agents#documentation-formats) * [llms.txt](https://docs.agentsverify.dev/llms.txt): a short documentation index. * [llms-full.txt](https://docs.agentsverify.dev/llms-full.txt): the guides and generated customer contract in one file. * [OpenAPI JSON](https://docs.agentsverify.dev/openapi.json): the six customer operations and schemas. * Each guide is available by appending `.md` to its path; the homepage is `/index.md`. Sending `Accept: text/markdown` to a guide URL also returns Markdown. ## Suggested starting prompt [](https://docs.agentsverify.dev/agents#suggested-starting-prompt) ``` Help me verify email addresses using AgentsVerify. First read https://docs.agentsverify.dev/api-reference.md.Ask me for an API key and the addresses or CSV to verify if I have not provided them.Use my API key only with the API described in that guide.Never repeat it in replies or logs, and never send it to the storage upload URL.Save the request identity and verification ID so you can recover interrupted work.Explain the saved results and the uncertainty of unknown or catch-all outcomes. ``` Create an account and obtain a key from the [dashboard](https://app.agentsverify.dev/dashboard/api-keys). An agent does not need your password or sign-in code. ## MCP [](https://docs.agentsverify.dev/agents#mcp) AgentsVerify also has an operational MCP integration for verification tools. That is separate from reading this documentation. See the [agent integration overview](https://agentsverify.dev/agents) for connection options; ordinary HTTP integrations can use this documentation without MCP. --- --- title: "AgentsVerify customer API reference" description: "Authenticated asynchronous email verification API contract." url: https://docs.agentsverify.dev/api-reference markdown_url: https://docs.agentsverify.dev/api-reference.md --- # AgentsVerify API Authenticated asynchronous email verification. Submit a CSV, then poll its saved result. Unknown results cost zero credits. Read the [verification workflow](https://docs.agentsverify.dev/guides/verification-workflow) for upload, progress, results, credits and recovery guidance. - Interactive reference: https://docs.agentsverify.dev/api-reference - Documentation index: https://docs.agentsverify.dev/llms.txt - Reference contact: Simon at simon@agentsverify.net ## Authentication All six operations in this customer reference accept an API key in `X-API-Key`. ## 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": }`. 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-/`. 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 - **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. ## Endpoint reference ### GET /v1/credits **Read available credits** Authentication scheme(s): `ApiKey`. #### Responses - **200** — Current available workspace balance; not a reservation - `application/json` ```json { "properties": { "credits": { "type": "integer", "minimum": 0.0 } }, "additionalProperties": false, "type": "object", "required": [ "credits" ] } ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` ### GET /v1/verifications **List saved verifications** Authentication scheme(s): `ApiKey`. #### Parameters | Name | Location | Required | Schema | | --- | --- | ---: | --- | | `limit` | `query` | no | `{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}` | | `cursor` | `query` | no | `{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}` | | `kind` | `query` | no | `{"anyOf":[{"enum":["single","bulk"],"type":"string"},{"type":"null"}],"title":"Kind"}` | #### Responses - **200** — Successful Response - `application/json` ```json { "$ref": "#/components/schemas/History" } ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **403** — Request is not permitted - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **404** — Verification not found or inaccessible - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **409** — Resolve the stated request conflict - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **413** — CSV exceeds the configured limit - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **422** — Fix the stated request parameters - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` ### POST /v1/verifications **Create or recover one CSV verification** No request body. SDK/dashboard compute the file length automatically. Transfer CSV bytes to upload.url using PUT, without API credentials. Storage enforces that exact length and the configured maximum; backend validation then starts automatically. CSV requires one column, an arbitrary optional first-record header, and syntactically valid email addresses in every subsequent record. Any defect rejects the complete file before checks or credits. Reuse the same UUID Idempotency-Key when retrying this creation request. Authentication scheme(s): `ApiKey`. #### Parameters | Name | Location | Required | Schema | | --- | --- | ---: | --- | | `Idempotency-Key` | `header` | yes | `{"type":"string","format":"uuid","title":"Idempotency-Key"}` | | `X-Upload-Content-Length` | `header` | yes | `{"type":"integer","minimum":1,"title":"X-Upload-Content-Length"}` | | `X-Upload-Filename` | `header` | no | `{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"X-Upload-Filename"}` | #### Responses - **201** — Successful Response - `application/json` ```json { "$ref": "#/components/schemas/Receipt" } ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **403** — Request is not permitted - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **404** — Verification not found or inaccessible - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **409** — Resolve the stated request conflict - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **413** — CSV exceeds the configured limit - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **422** — Fix the stated request parameters - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **200** — Recovered existing verification - `application/json` ```json { "$ref": "#/components/schemas/Receipt" } ``` ### GET /v1/verifications/{id} **Read verification progress** Authentication scheme(s): `ApiKey`. #### Parameters | Name | Location | Required | Schema | | --- | --- | ---: | --- | | `id` | `path` | yes | `{"type":"string","format":"uuid","title":"Id"}` | #### Responses - **200** — Successful Response - `application/json` ```json { "$ref": "#/components/schemas/Detail" } ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **403** — Request is not permitted - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **404** — Verification not found or inaccessible - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **409** — Resolve the stated request conflict - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **413** — CSV exceeds the configured limit - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **422** — Fix the stated request parameters - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` ### GET /v1/verifications/{id}/results **Download available finalized results** Authentication scheme(s): `ApiKey`. #### Parameters | Name | Location | Required | Schema | | --- | --- | ---: | --- | | `id` | `path` | yes | `{"type":"string","format":"uuid","title":"Id"}` | #### Responses - **200** — Finite CSV of available final outcomes; header-only if none. Columns: email,result,message,checked_at. Values: valid,invalid,catch_all,unknown,error. Unchecked cancelled addresses are excluded. - `text/csv` ```json {} ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **403** — Request is not permitted - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **404** — Verification not found or inaccessible - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **409** — Resolve the stated request conflict - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **413** — CSV exceeds the configured limit - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **422** — Fix the stated request parameters - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` ### POST /v1/verifications/{id}/cancel **Cancel remaining work** Authentication scheme(s): `ApiKey`. #### Parameters | Name | Location | Required | Schema | | --- | --- | ---: | --- | | `id` | `path` | yes | `{"type":"string","format":"uuid","title":"Id"}` | #### Responses - **200** — Successful Response - `application/json` ```json { "$ref": "#/components/schemas/Cancellation" } ``` - **401** — Fix authentication before retrying - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **403** — Request is not permitted - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **404** — Verification not found or inaccessible - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **409** — Resolve the stated request conflict - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **413** — CSV exceeds the configured limit - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **422** — Fix the stated request parameters - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **429** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **503** — Wait for Retry-After and retry the same request - `application/json` ```json { "$ref": "#/components/schemas/APIError" } ``` - **202** — Outstanding work is settling/refunding automatically - `application/json` ```json { "$ref": "#/components/schemas/Cancellation" } ``` ## Schemas The following component schemas are referenced by the endpoint contracts above. ### `APIError` ```json { "properties": { "issue": { "$ref": "#/components/schemas/Issue" }, "request_id": { "type": "string", "format": "uuid", "title": "Request Id" } }, "additionalProperties": false, "type": "object", "required": [ "issue", "request_id" ], "title": "APIError" } ``` ### `Cancellation` ```json { "properties": { "id": { "type": "string", "format": "uuid", "title": "Id" }, "status": { "type": "string", "enum": [ "uploading", "preparing", "verifying", "waiting", "cancelling", "completed", "completed_with_errors", "cancelled", "failed" ], "title": "Status" } }, "additionalProperties": false, "type": "object", "required": [ "id", "status" ], "title": "Cancellation" } ``` ### `Detail` ```json { "properties": { "id": { "type": "string", "format": "uuid", "title": "Id" }, "filename": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Filename" }, "submission_kind": { "type": "string", "enum": [ "single", "bulk" ], "title": "Submission Kind" }, "single_email": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Single Email" }, "outcome": { "anyOf": [ { "type": "string", "enum": [ "valid", "invalid", "catch_all", "unknown", "error" ] }, { "type": "null" } ], "title": "Outcome", "description": "Final single-email outcome, including operational errors. Null for bulk or unfinished checks." }, "created_at": { "type": "string", "format": "date-time", "title": "Created At" }, "completed_at": { "anyOf": [ { "type": "string", "format": "date-time" }, { "type": "null" } ], "title": "Completed At", "description": "Canonical time input processing, all address outcomes/cancellations and credit settlement finished. Null while unfinished or for historical jobs without a recorded timestamp. Excludes notification delivery and archival." }, "status": { "type": "string", "enum": [ "uploading", "preparing", "verifying", "waiting", "cancelling", "completed", "completed_with_errors", "cancelled", "failed" ], "title": "Status" }, "progress": { "$ref": "#/components/schemas/Progress" }, "input": { "anyOf": [ { "$ref": "#/components/schemas/Input" }, { "type": "null" } ] }, "issue": { "anyOf": [ { "$ref": "#/components/schemas/Issue" }, { "type": "null" } ] }, "upload": { "anyOf": [ { "$ref": "#/components/schemas/Upload" }, { "type": "null" } ] } }, "additionalProperties": false, "type": "object", "required": [ "id", "filename", "submission_kind", "single_email", "outcome", "created_at", "completed_at", "status", "progress", "input" ], "title": "Detail" } ``` ### `History` ```json { "properties": { "verifications": { "items": { "$ref": "#/components/schemas/Summary" }, "type": "array", "title": "Verifications" }, "next_cursor": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Next Cursor" }, "limits": { "$ref": "#/components/schemas/Limits" } }, "additionalProperties": false, "type": "object", "required": [ "verifications", "next_cursor", "limits" ], "title": "History" } ``` ### `Input` ```json { "properties": { "rows": { "type": "integer", "minimum": 1.0, "title": "Rows" }, "duplicates": { "type": "integer", "minimum": 0.0, "title": "Duplicates" } }, "additionalProperties": false, "type": "object", "required": [ "rows", "duplicates" ], "title": "Input" } ``` ### `Issue` ```json { "properties": { "code": { "type": "string", "title": "Code" }, "message": { "type": "string", "title": "Message" }, "row": { "anyOf": [ { "type": "integer", "minimum": 1.0 }, { "type": "null" } ], "title": "Row" } }, "additionalProperties": false, "type": "object", "required": [ "code", "message" ], "title": "Issue" } ``` ### `Limits` ```json { "properties": { "max_file_bytes": { "type": "integer", "title": "Max File Bytes" }, "max_rows": { "type": "integer", "title": "Max Rows" } }, "additionalProperties": false, "type": "object", "required": [ "max_file_bytes", "max_rows" ], "title": "Limits" } ``` ### `Progress` ```json { "properties": { "total": { "anyOf": [ { "type": "integer", "minimum": 0.0 }, { "type": "null" } ], "title": "Total" }, "completed": { "type": "integer", "minimum": 0.0, "title": "Completed" }, "errors": { "type": "integer", "minimum": 0.0, "title": "Errors" }, "cancelled": { "type": "integer", "minimum": 0.0, "title": "Cancelled" } }, "additionalProperties": false, "type": "object", "required": [ "total", "completed", "errors", "cancelled" ], "title": "Progress" } ``` ### `Receipt` ```json { "properties": { "id": { "type": "string", "format": "uuid", "title": "Id" }, "status": { "type": "string", "enum": [ "uploading", "preparing", "verifying", "waiting", "cancelling", "completed", "completed_with_errors", "cancelled", "failed" ], "title": "Status" }, "upload": { "anyOf": [ { "$ref": "#/components/schemas/Upload" }, { "type": "null" } ] } }, "additionalProperties": false, "type": "object", "required": [ "id", "status" ], "title": "Receipt" } ``` ### `Summary` ```json { "properties": { "id": { "type": "string", "format": "uuid", "title": "Id" }, "filename": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Filename" }, "submission_kind": { "type": "string", "enum": [ "single", "bulk" ], "title": "Submission Kind" }, "single_email": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Single Email" }, "outcome": { "anyOf": [ { "type": "string", "enum": [ "valid", "invalid", "catch_all", "unknown", "error" ] }, { "type": "null" } ], "title": "Outcome", "description": "Final single-email outcome, including operational errors. Null for bulk or unfinished checks." }, "created_at": { "type": "string", "format": "date-time", "title": "Created At" }, "completed_at": { "anyOf": [ { "type": "string", "format": "date-time" }, { "type": "null" } ], "title": "Completed At", "description": "Canonical time input processing, all address outcomes/cancellations and credit settlement finished. Null while unfinished or for historical jobs without a recorded timestamp. Excludes notification delivery and archival." }, "status": { "type": "string", "enum": [ "uploading", "preparing", "verifying", "waiting", "cancelling", "completed", "completed_with_errors", "cancelled", "failed" ], "title": "Status" }, "progress": { "$ref": "#/components/schemas/Progress" } }, "additionalProperties": false, "type": "object", "required": [ "id", "filename", "submission_kind", "single_email", "outcome", "created_at", "completed_at", "status", "progress" ], "title": "Summary" } ``` ### `Upload` ```json { "properties": { "method": { "type": "string", "const": "PUT", "title": "Method", "default": "PUT" }, "url": { "type": "string", "title": "Url" }, "expires_at": { "type": "string", "format": "date-time", "title": "Expires At" } }, "additionalProperties": false, "type": "object", "required": [ "url", "expires_at" ], "title": "Upload" } ``` --- --- title: "Authentication" url: https://docs.agentsverify.dev/authentication --- # Authentication Sign in to the [API key page](https://app.agentsverify.dev/dashboard/api-keys) and copy your workspace’s key. Store it in your server environment as `AGENTS_VERIFY_API_KEY`. Send it in the `X-API-Key` header on requests to `https://api.agentsverify.dev`: ``` curl --fail-with-body 'https://api.agentsverify.dev/v1/credits' \ --header "X-API-Key: ${AGENTS_VERIFY_API_KEY:?Set your API key}" ``` Keep keys out of URLs, logs, chat replies and application browser bundles. Your API key grants access to your workspace’s credits and verifications. Revoke a key in the dashboard if it is exposed. ## Try a request in the reference [](https://docs.agentsverify.dev/authentication#try-a-request-in-the-reference) Open the [API reference](https://docs.agentsverify.dev/api-reference), enter your key in its authentication field and select an operation. These requests use your actual workspace and normal credit rules. The reference does not persist your key across page reloads or send requests through a third-party proxy. Creating a verification returns a separate storage upload URL. The reference does not automatically upload a CSV. Follow the [quickstart](https://docs.agentsverify.dev/quickstart) for the complete two-stage transfer. ## Storage uploads [](https://docs.agentsverify.dev/authentication#storage-uploads) Send raw CSV bytes to the `upload.url` returned by creation. **Do not send `X-API-Key` or an `Authorization` header to storage.** Treat that upload URL as private. Use it only for its assigned file and exact byte length. ## Authentication errors [](https://docs.agentsverify.dev/authentication#authentication-errors) HTTP `401` means the API credentials were missing or rejected. Check the key and header before retrying. The customer API uses API keys; dashboard sign-in is managed separately. --- --- title: "Errors and retries" url: https://docs.agentsverify.dev/guides/errors-and-retries --- # Errors and retries API errors contain `issue.code`, `issue.message` and `request_id`. Keep the request ID when contacting [support](mailto:simon@agentsverify.net), and omit API keys and private upload URLs. | Response | What to do | | --- | --- | | `401` | Check the API key and `X-API-Key` header. | | `403` | Check the permitted browser origin and requested action. | | `404` | Check the saved verification ID and workspace. | | `409` | Read the issue and reconcile the existing request before retrying. | | `422` | Correct the specified headers, input or CSV defect. | | `429` or `503` | Respect `Retry-After` before retrying. | ## Recover an uncertain creation [](https://docs.agentsverify.dev/guides/errors-and-retries#recover-an-uncertain-creation) Save a UUID before the first creation request and send it as `Idempotency-Key`. If the response is lost, retry the same submission with that same identity and exact file length. The API can recover the existing verification instead of creating another one. A new request identity creates another verification and can charge again. Resubmitting is not a polling or backend retry mechanism. ## Resume a transfer or cancel work [](https://docs.agentsverify.dev/guides/errors-and-retries#resume-a-transfer-or-cancel-work) Storage uploads use a separate resumable protocol. After a confirmed storage `200` or `201`, continue polling the saved verification instead of uploading again. Follow the [quickstart](https://docs.agentsverify.dev/quickstart#resume-an-interrupted-upload) for incomplete transfers. Use bodyless `POST /v1/verifications/{id}/cancel` to cancel remaining work. Settlement and refunds may continue while the job is `cancelling`. See the [complete workflow](https://docs.agentsverify.dev/guides/verification-workflow) for credit and recovery rules. --- --- title: "Results and credits" url: https://docs.agentsverify.dev/guides/results-and-credits --- # Results and credits The [verification workflow](https://docs.agentsverify.dev/guides/verification-workflow#outcomes-credits-and-errors) defines the outcome and credit rules. Unknown is inconclusive; catch-all is risky. A `valid` result predicts low bounce risk and does not guarantee delivery. ## Read available results [](https://docs.agentsverify.dev/guides/results-and-credits#read-available-results) `GET /v1/verifications/{id}/results` returns available finalized CSV rows with columns `email,result,message,checked_at`. Partial downloads contain finished checks. A header-only response means no outcomes are available yet. Pending and unchecked cancelled addresses are excluded. Reading a saved result again does not start another check. A new submission creates new work and can charge again. ## Follow completion [](https://docs.agentsverify.dev/guides/results-and-credits#follow-completion) Poll `GET /v1/verifications/{id}` and respect `Retry-After`. Read `issue` for actionable guidance. If the issue is `credits_required`, adding credits resumes the file without another upload. The workflow documents all job states, outcome definitions, credit refunds and completion timestamps. See the [endpoint reference](https://docs.agentsverify.dev/api-reference) for exact response fields. ## Check your balance [](https://docs.agentsverify.dev/guides/results-and-credits#check-your-balance) `GET /v1/credits` returns your current available balance. It does not reserve credits for a later submission. Manage purchases in the [dashboard](https://app.agentsverify.dev/dashboard). --- --- 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": }`. 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-/`. 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. --- --- title: "Email verification, ready to build with." url: https://docs.agentsverify.dev/ --- # Email verification, ready to build with. One flow, any list A one-column CSV handles a single address or a larger list. The API validates the whole file, removes duplicates and schedules checks. Saved progress and results Follow your verification by ID. Download finalized results as they become available, and return to the same saved job later. Clear credit rules Read your balance before submitting. Unknown outcomes are inconclusive and refund their held credit. Built for agents too Read every guide as Markdown, discover the documentation through llms.txt, or use the OpenAPI contract directly. ## Choose your next step [](https://docs.agentsverify.dev/#choose-your-next-step) [Make your first request](https://docs.agentsverify.dev/quickstart)Get an API key and submit your first CSV. [Understand the workflow](https://docs.agentsverify.dev/guides/verification-workflow)Uploads, progress, recovery and cancellation. [Look up an endpoint](https://docs.agentsverify.dev/api-reference)Parameters, response schemas and an interactive playground. [Connect an AI agent](https://docs.agentsverify.dev/agents)Give your agent the same complete API instructions. Actual API requests go to `https://api.agentsverify.dev`. Manage keys, credits and saved verifications in the [dashboard](https://app.agentsverify.dev/dashboard). --- --- title: "Quickstart" url: https://docs.agentsverify.dev/quickstart --- # Quickstart Verify one address or a larger list with the same flow: create a verification, upload a CSV, then read saved progress and results. ## 1\. Get your key and check credits [](https://docs.agentsverify.dev/quickstart#1-get-your-key-and-check-credits) Copy your key from the [dashboard](https://app.agentsverify.dev/dashboard/api-keys) and store it as `AGENTS_VERIFY_API_KEY` in your terminal or server environment. ``` curl --fail-with-body 'https://api.agentsverify.dev/v1/credits' \ --header "X-API-Key: ${AGENTS_VERIFY_API_KEY:?Set your API key}" ``` The `credits` value is your available balance. This read does not reserve credits. For current file-size and row limits, call `GET /v1/verifications`. ## 2\. Prepare a CSV [](https://docs.agentsverify.dev/quickstart#2-prepare-a-csv) Create a one-column UTF-8 file named `contacts.csv`, with an explicit `email` header and your addresses below it: ``` emailperson@example.com ``` The address above is a format example. Use your own addresses for real verification. Standard CSV quoting, an optional initial BOM and LF or CRLF are supported. Blank records, extra columns or malformed addresses reject the whole file before checks or credit holds. Duplicates are checked once. ## 3\. Create and upload [](https://docs.agentsverify.dev/quickstart#3-create-and-upload) Generate a UUID and save it as `REQUEST_ID` before the first request. Reuse it when recovering that same submission. Creation is a bodyless POST. Compute the byte length from the actual file: ``` curl --request POST 'https://api.agentsverify.dev/v1/verifications' \ --fail-with-body \ --header "X-API-Key: ${AGENTS_VERIFY_API_KEY:?Set your API key}" \ --header "Idempotency-Key: ${REQUEST_ID:?Set and save a UUID first}" \ --header "X-Upload-Content-Length: $(wc -c < contacts.csv)" \ --header "X-Upload-Filename: contacts.csv" ``` HTTP `201` creates a verification; HTTP `200` recovers it. Save the returned `id`. When the receipt contains `upload`, PUT the CSV bytes to `upload.url` without API credentials. This Node.js example performs both stages. Save it as `upload.mjs` and run `node upload.mjs contacts.csv` with both environment variables set: ``` async function uploadCsv(filePath, apiKey, idempotencyKey) { const {readFile} = await import('node:fs/promises'); const {basename} = await import('node:path'); if (!apiKey || !idempotencyKey) { throw new Error('Set AGENTS_VERIFY_API_KEY and your saved REQUEST_ID'); } const csv = await readFile(filePath); if (csv.length === 0) throw new Error('The CSV file is empty'); const filename = encodeURIComponent(basename(filePath)); const created = await fetch('https://api.agentsverify.dev/v1/verifications', { method: 'POST', redirect: 'manual', headers: { 'X-API-Key': apiKey, 'Idempotency-Key': idempotencyKey, 'X-Upload-Content-Length': String(csv.length), 'X-Upload-Filename': filename } }); const receipt = await created.json(); if (created.status !== 200 && created.status !== 201) { throw new Error(receipt.issue?.message || 'API request rejected'); } if (receipt.upload) { const stored = await fetch(receipt.upload.url, { method: 'PUT', body: csv, credentials: 'omit', redirect: 'manual', headers: { 'Content-Type': 'text/csv', 'Content-Range': 'bytes 0-' + (csv.length - 1) + '/' + csv.length, 'X-Goog-Meta-Original-Filename': filename } }); if (stored.status === 308) { throw new Error('Upload incomplete: resume the saved session'); } if (stored.status !== 200 && stored.status !== 201) { throw new Error('Storage rejected the upload (HTTP ' + stored.status + ')'); } } return receipt.id;} const verificationId = await uploadCsv( process.argv[2] || 'contacts.csv', process.env.AGENTS_VERIFY_API_KEY, process.env.REQUEST_ID);console.log('Verification ID:', verificationId); ``` The example transfers a whole file. It does not resume incomplete transfers. Storage HTTP `200` or `201` confirms receipt. After confirmation, the job can briefly remain `uploading` while the backend detects completion. Continue polling instead of re-uploading. ## 4\. Follow progress and download results [](https://docs.agentsverify.dev/quickstart#4-follow-progress-and-download-results) Poll `GET /v1/verifications/{id}` and respect `Retry-After`. Read `issue` for actionable guidance. Whole-file validation and processing start automatically; no completion or batching call is needed. Download `GET /v1/verifications/{id}/results` for finalized CSV outcomes. Partial results contain finished checks; a header-only CSV means none are available yet. Read saved results again without submitting another verification. Continue with the [complete workflow](https://docs.agentsverify.dev/guides/verification-workflow), [results and credits](https://docs.agentsverify.dev/guides/results-and-credits) or [endpoint reference](https://docs.agentsverify.dev/api-reference). ## Resume an interrupted upload [](https://docs.agentsverify.dev/quickstart#resume-an-interrupted-upload) Send an empty PUT to the same private `upload.url` with `Content-Range: bytes */`. HTTP `200` or `201` means complete. A `308` response identifies persisted bytes in `Range`. Continue at the next byte, or byte zero if no Range is present, following the [storage resumption protocol](https://docs.cloud.google.com/storage/docs/performing-resumable-uploads#resume-upload). Keep omitting API credentials from storage requests. Recover an uncertain API creation using the original `Idempotency-Key`; a new identity creates new work and can charge again.