> For the complete documentation index, see [llms.txt](https://help.delpha.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.delpha.io/delpha-api-and-mcp/api/email.md).

# Email

The email operations validate an address and, when only a name and a company website are supplied, look for one. Validation checks an address that is supplied; the search derives candidate addresses from the supplied name and website domain.

Four dimensions are scored:

* **Completeness:** whether an address is present, and whether one could be found from the name and website.
* **Validity:** whether the address is syntactically well formed, its domain resolves, and the mailbox accepts mail.
* **Accuracy:** whether the address corresponds to the person named in the request.
* **Consistency:** the input value compared with its normalized version (not cross-source).

The result also carries two qualifications. `email_domain_qualification` reports whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address. `email_address_qualification` flags an address that is role-based (a shared functional mailbox such as `contact@`) or a known spam trap. Candidate addresses are returned ranked, each with a confidence score.

## Find, validate & qualify email

> Find, validate, and qualify a person's email address: send \`email\` to verify it, or \`first\_name\`, \`last\_name\` and \`website\` together to search for it. Submit an asynchronous job; the returned \`job\_id\` goes to \`getEmailResult\`, which yields the validated email, the \`email\_status\` (Valid / ...), \`email\_domain\_qualification\` (whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address; see \`getEmailResult\`), the qualified domain, the scores (validity / completeness / accuracy / consistency), and ranked suggestions (both inferred from the input and from the company website).\
> \
> Two modes — at least one must be fully satisfied:\
> &#x20; \- Validation mode: provide \`email\` alone to verify deliverability and qualify the domain.\
> &#x20; \- Recommendation mode: provide \`first\_name\`, \`last\_name\`, AND \`website\` together (all three required) to search for the address. Partial recommendation inputs are rejected with 400.\
> Supplying both an email and the recommendation triple runs both paths in the same job.\
> \
> This result comes from Delpha's own verification and a Delpha model; no contact database and no third-party database is used. Candidate addresses are generated from per-domain address patterns, not retrieved from a list of known addresses. The address you supply — or an address formed from the name and company website you supply — reaches the mail infrastructure of that address's own domain.\
> \
> A live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an \`Idempotency-Key\` already used with the same body within the last 24 hours — that returns the original \`job\_id\` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's \*\*Test mode\*\* section.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.2"},"tags":[{"name":"Email","description":"The email operations validate an address and, when only a name and a company website are supplied, look for one. Validation checks an address that is supplied; the search derives candidate addresses from the supplied name and website domain.\n\nFour dimensions are scored:\n- **Completeness:** whether an address is present, and whether one could be found from the name and website.\n- **Validity:** whether the address is syntactically well formed, its domain resolves, and the mailbox accepts mail.\n- **Accuracy:** whether the address corresponds to the person named in the request.\n- **Consistency:** the input value compared with its normalized version (not cross-source).\n\nThe result also carries two qualifications. `email_domain_qualification` reports whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address. `email_address_qualification` flags an address that is role-based (a shared functional mailbox such as `contact@`) or a known spam trap. Candidate addresses are returned ranked, each with a confidence score."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"EmailSubmitOutput":{"additionalProperties":true,"description":"Response after submitting a new email quality job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The job ID. Required if status <= 300.","title":"Job Id"},"message":{"description":"The message to return","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The status code to return","title":"Status Code","type":"integer"}},"required":["message","status","status_code"],"title":"EmailSubmitOutput","type":"object"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true},"EmailSubmitInput":{"description":"Payload to submit a new email quality job.","properties":{"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"default":null,"description":"RFC 5321 mailbox to validate (e.g. `jordan.rivera@delpha.io`). When provided, the tool verifies deliverability rather than searching. Optional; without it, `first_name`, `last_name` and `website` must all be set.","title":"Email"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Person's given name (e.g. `Jordan`). Combined with `last_name` and a company signal (`website`) to search for the address.","title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Person's family name (e.g. `Rivera`). Pair with `first_name`.","title":"Last Name"},"website":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"default":null,"description":"Company website associated with the person (e.g. `https://delpha.io/`). Used as the company signal when searching by name; the tool extracts and qualifies the domain.","title":"Website"}},"title":"EmailSubmitInput","type":"object"}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/email":{"post":{"tags":["Email"],"summary":"Find, validate & qualify email","description":"Find, validate, and qualify a person's email address: send `email` to verify it, or `first_name`, `last_name` and `website` together to search for it. Submit an asynchronous job; the returned `job_id` goes to `getEmailResult`, which yields the validated email, the `email_status` (Valid / ...), `email_domain_qualification` (whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address; see `getEmailResult`), the qualified domain, the scores (validity / completeness / accuracy / consistency), and ranked suggestions (both inferred from the input and from the company website).\n\nTwo modes — at least one must be fully satisfied:\n  - Validation mode: provide `email` alone to verify deliverability and qualify the domain.\n  - Recommendation mode: provide `first_name`, `last_name`, AND `website` together (all three required) to search for the address. Partial recommendation inputs are rejected with 400.\nSupplying both an email and the recommendation triple runs both paths in the same job.\n\nThis result comes from Delpha's own verification and a Delpha model; no contact database and no third-party database is used. Candidate addresses are generated from per-domain address patterns, not retrieved from a list of known addresses. The address you supply — or an address formed from the name and company website you supply — reaches the mail infrastructure of that address's own domain.\n\nA live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an `Idempotency-Key` already used with the same body within the last 24 hours — that returns the original `job_id` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's **Test mode** section.","operationId":"findAndValidateEmail","responses":{"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSubmitOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"Set to 'true' when this 202 replays a previously accepted request with the same Idempotency-Key (no new job, no additional charge).","schema":{"type":"string"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"402":{"description":"Payment required — the team has insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"409":{"description":"Conflict — the `Idempotency-Key` was already used with a different request body (`idempotency_key_reuse`: a new key admits the new body, the original body replays the original job), or the original request with this key is still being processed (`idempotency_in_progress`: the same request answers with the original job once that one is admitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"502":{"description":"Bad gateway — the upstream service returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSubmitInput"}}}}}}}}
```

## Get email validation result

> Fetch the result of a previously submitted \`findAndValidateEmail\` job by \`job\_id\`. On success, the \`result\` payload contains: the validated email (\`normalized\_value\`); \`email\_status\` (closed enum: \`"Valid"\`, \`"Invalid"\`, \`"Unknown"\`); \`email\_domain\_qualification\`, which reports two properties of the address's domain — whether it is a public/personal mail domain or a company domain, and whether it accepts mail at any address (closed enum: \`"nominative\@perso"\` = a public/personal mail domain that rejects unknown addresses; \`"catchall\@perso"\` = a public/personal mail domain that accepts any address; \`"nominative\@pro"\` = a company domain that rejects unknown addresses; \`"catchall\@pro"\` = a company domain that accepts any address, so acceptance is not evidence the mailbox exists; \`"Unknown"\` = the domain could not be classified, for instance because it greylisted the probe or its server failed temporarily); a top-level \`label\` summarising the outcome (closed enum: \`"OK"\`, \`"No"\`, \`"OddFormat"\`); the qualified domain; the four \`scores\` (validity, completeness, accuracy, consistency); and ranked \`suggestions\` (alternative addresses scored by likelihood) when no exact match is found.\
> \
> Reading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.2"},"tags":[{"name":"Email","description":"The email operations validate an address and, when only a name and a company website are supplied, look for one. Validation checks an address that is supplied; the search derives candidate addresses from the supplied name and website domain.\n\nFour dimensions are scored:\n- **Completeness:** whether an address is present, and whether one could be found from the name and website.\n- **Validity:** whether the address is syntactically well formed, its domain resolves, and the mailbox accepts mail.\n- **Accuracy:** whether the address corresponds to the person named in the request.\n- **Consistency:** the input value compared with its normalized version (not cross-source).\n\nThe result also carries two qualifications. `email_domain_qualification` reports whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address. `email_address_qualification` flags an address that is role-based (a shared functional mailbox such as `contact@`) or a known spam trap. Candidate addresses are returned ranked, each with a confidence score."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"EmailPullOutput":{"additionalProperties":true,"description":"Response after retrieving the status and result of an email quality job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"message":{"description":"A human-readable message describing the current state or outcome of the job.","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The HTTP status code representing the job's current state.","title":"Status Code","type":"integer"},"result":{"anyOf":[{"$ref":"#/components/schemas/EmailModel"},{"type":"null"}],"default":null,"description":"The result of the email quality job"},"process_time":{"anyOf":[{"minimum":0,"type":"number"},{"type":"null"}],"default":null,"description":"The total time taken to process the job, in seconds.","title":"Process Time"}},"required":["message","status","status_code"],"title":"EmailPullOutput","type":"object"},"EmailModel":{"additionalProperties":true,"description":"Model representing the details of an email field.","properties":{"label":{"description":"Label for the email.","enum":["No","OK","OddFormat"],"title":"Label","type":"string"},"normalized_value":{"description":"Normalized email value.","title":"Normalized Value","type":"string"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Provider of the email, if any.","title":"Provider"},"email_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Domain of the email. `null` when the address carries no parseable domain (a syntactically invalid address, which returns `label: \"No\"`).","title":"Email Domain"},"email_domain_qualification":{"$ref":"#/components/schemas/DomainQualification","description":"Qualification of the email domain."},"email_status":{"description":"Status of the email. Possible values: 'Invalid', 'Unknown', 'Valid'.","enum":["Invalid","Unknown","Valid"],"title":"Email Status","type":"string"},"email_address_qualification":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Address-level qualification of the mailbox, when one applies: `Spam Trap` (an address Delpha holds on a list of addresses used to detect unsolicited mail rather than read by a person) or `Role-based` (a shared functional mailbox such as `contact@`/`support@`, not a person). `null` means neither applies. ⚠️ This takes precedence over `email_domain_qualification`, which describes the DOMAIN rather than this address: a `Role-based` mailbox on a nominative professional domain is still role-based. The vocabulary may grow, so an unrecognised value is informational rather than an error.","title":"Email Address Qualification"},"suggestions":{"description":"Suggestions for the email.","items":{"$ref":"#/components/schemas/EmailSuggestion"},"title":"Suggestions","type":"array"},"website_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Website domain associated.","title":"Website Domain"},"website_domain_qualification":{"anyOf":[{"$ref":"#/components/schemas/DomainQualification"},{"type":"null"}],"default":null,"description":"Qualification of the website domain."},"suggestions_from_website":{"description":"Suggestions from the website.","items":{"$ref":"#/components/schemas/EmailSuggestion"},"title":"Suggestions From Website","type":"array"},"data_type":{"$ref":"#/components/schemas/DataType","description":"The type of data for this field"},"scores":{"$ref":"#/components/schemas/ScoresModel","description":"Scores for the field"}},"required":["label","normalized_value","email_domain_qualification","email_status","data_type","scores"],"title":"EmailModel","type":"object"},"DomainQualification":{"description":"Enum representing the possible qualifications for an email or website domain.\n\n- nominative@pro: domain is professional and returns invalid for fake emails\n- catchall@pro: domain is professional and returns valid for fake emails\n- nominative@perso: domain is personal and returns invalid for fake emails\n- catchall@perso: domain is personal and returns valid for fake emails\n- Unknown: grey listed or temporary issue with the server","enum":["nominative@pro","catchall@pro","nominative@perso","catchall@perso","Unknown"],"title":"DomainQualification","type":"string"},"EmailSuggestion":{"additionalProperties":true,"description":"Model representing a suggestion for an email.","properties":{"value":{"description":"Suggested email value.","title":"Value","type":"string"},"score":{"description":"Confidence score for the suggestion.","maximum":1,"minimum":0,"title":"Score","type":"number"}},"required":["value","score"],"title":"EmailSuggestion","type":"object"},"DataType":{"enum":["email","social_network","name","legal_id","phone","address","website"],"title":"DataType","type":"string"},"ScoresModel":{"description":"Model representing the scores for an email field.","properties":{"accuracy":{"default":-1,"description":"Accuracy score","maximum":1,"minimum":-1,"title":"Accuracy","type":"number"},"validity":{"default":-1,"description":"Validity score","maximum":1,"minimum":-1,"title":"Validity","type":"integer"},"completeness":{"default":0,"description":"Completeness score","maximum":1,"minimum":0,"title":"Completeness","type":"number"},"consistency":{"default":0,"description":"Consistency score","maximum":1,"minimum":0,"title":"Consistency","type":"integer"}},"title":"ScoresModel","type":"object"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/email/{job_id}":{"get":{"tags":["Email"],"summary":"Get email validation result","description":"Fetch the result of a previously submitted `findAndValidateEmail` job by `job_id`. On success, the `result` payload contains: the validated email (`normalized_value`); `email_status` (closed enum: `\"Valid\"`, `\"Invalid\"`, `\"Unknown\"`); `email_domain_qualification`, which reports two properties of the address's domain — whether it is a public/personal mail domain or a company domain, and whether it accepts mail at any address (closed enum: `\"nominative@perso\"` = a public/personal mail domain that rejects unknown addresses; `\"catchall@perso\"` = a public/personal mail domain that accepts any address; `\"nominative@pro\"` = a company domain that rejects unknown addresses; `\"catchall@pro\"` = a company domain that accepts any address, so acceptance is not evidence the mailbox exists; `\"Unknown\"` = the domain could not be classified, for instance because it greylisted the probe or its server failed temporarily); a top-level `label` summarising the outcome (closed enum: `\"OK\"`, `\"No\"`, `\"OddFormat\"`); the qualified domain; the four `scores` (validity, completeness, accuracy, consistency); and ranked `suggestions` (alternative addresses scored by likelihood) when no exact match is found.\n\nReading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.","operationId":"getEmailResult","responses":{"200":{"description":"Job succeeded — the result payload is populated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPullOutput"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPullOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"404":{"description":"Not found — no job exists for this id, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"409":{"description":"Conflict — the credit reservation expired before delivery; resubmit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"503":{"description":"Service unavailable — a downstream dependency was unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"504":{"description":"Gateway timeout — the job exceeded its processing ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"parameters":[{"name":"job_id","in":"path","required":true,"description":"Opaque job identifier returned by `findAndValidateEmail`.","schema":{"type":"string"}}]}}}}
```

## Submit a batch of email items

> Submit 1..100 email items for asynchronous batch processing as ONE job (never a per-item fan-out). Returns a \`job\_id\` immediately (202); poll \`GET /v1/email/batch/{job\_id}\` for status and results. Each item follows \`EmailSubmitInput\`; see that component for its fields. It uses the runtime validation of \`POST /v1/email\`. A payload with 0 items or more than 100 is rejected with 422.\
> \
> A live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an \`Idempotency-Key\` already used with the same body within the last 24 hours — that returns the original \`job\_id\` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's \*\*Test mode\*\* section.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.2"},"tags":[{"name":"Email","description":"The email operations validate an address and, when only a name and a company website are supplied, look for one. Validation checks an address that is supplied; the search derives candidate addresses from the supplied name and website domain.\n\nFour dimensions are scored:\n- **Completeness:** whether an address is present, and whether one could be found from the name and website.\n- **Validity:** whether the address is syntactically well formed, its domain resolves, and the mailbox accepts mail.\n- **Accuracy:** whether the address corresponds to the person named in the request.\n- **Consistency:** the input value compared with its normalized version (not cross-source).\n\nThe result also carries two qualifications. `email_domain_qualification` reports whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address. `email_address_qualification` flags an address that is role-based (a shared functional mailbox such as `contact@`) or a known spam trap. Candidate addresses are returned ranked, each with a confidence score."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"BatchSubmitOutput":{"additionalProperties":true,"description":"Response after submitting a batch quality job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The job ID. Required if status <= 300.","title":"Job Id"},"item_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Number of items accepted in the batch (present on success).","title":"Item Count"},"message":{"description":"The message to return","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The status code to return","title":"Status Code","type":"integer"}},"required":["message","status","status_code"],"title":"BatchSubmitOutput","type":"object"},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"EmailBatchSubmitInput":{"description":"Batch envelope for `POST /v1/email/batch`: `{\"items\": [...]}` (1..100 items, 422 beyond). Each item follows `EmailSubmitInput`; see that component for its fields. It uses the runtime validation of `POST /v1/email`.","properties":{"items":{"description":"The batch items (1..100), each a single-route input payload.","items":{"$ref":"#/components/schemas/EmailSubmitInput"},"maxItems":100,"minItems":1,"title":"Items","type":"array"}},"required":["items"],"title":"EmailBatchSubmitInput","type":"object"},"EmailSubmitInput":{"description":"Payload to submit a new email quality job.","properties":{"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"default":null,"description":"RFC 5321 mailbox to validate (e.g. `jordan.rivera@delpha.io`). When provided, the tool verifies deliverability rather than searching. Optional; without it, `first_name`, `last_name` and `website` must all be set.","title":"Email"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Person's given name (e.g. `Jordan`). Combined with `last_name` and a company signal (`website`) to search for the address.","title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Person's family name (e.g. `Rivera`). Pair with `first_name`.","title":"Last Name"},"website":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"default":null,"description":"Company website associated with the person (e.g. `https://delpha.io/`). Used as the company signal when searching by name; the tool extracts and qualifies the domain.","title":"Website"}},"title":"EmailSubmitInput","type":"object"}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/email/batch":{"post":{"tags":["Email"],"summary":"Submit a batch of email items","description":"Submit 1..100 email items for asynchronous batch processing as ONE job (never a per-item fan-out). Returns a `job_id` immediately (202); poll `GET /v1/email/batch/{job_id}` for status and results. Each item follows `EmailSubmitInput`; see that component for its fields. It uses the runtime validation of `POST /v1/email`. A payload with 0 items or more than 100 is rejected with 422.\n\nA live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an `Idempotency-Key` already used with the same body within the last 24 hours — that returns the original `job_id` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's **Test mode** section.","operationId":"submitEmailBatch","responses":{"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSubmitOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"Set to 'true' when this 202 replays a previously accepted request with the same Idempotency-Key (no new job, no additional charge).","schema":{"type":"string"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"402":{"description":"Payment required — the team has insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"409":{"description":"Conflict — the `Idempotency-Key` was already used with a different request body (`idempotency_key_reuse`: a new key admits the new body, the original body replays the original job), or the original request with this key is still being processed (`idempotency_in_progress`: the same request answers with the original job once that one is admitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"422":{"description":"Unprocessable entity — the request is well-formed but cannot be processed: a documented size/shape bound was violated (`validation_error`), or a legal-ID request names a registry / country Delpha cannot query (`unsupported_registry` — refused before any credit is reserved; the message lists the supported countries).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"502":{"description":"Bad gateway — the upstream service returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailBatchSubmitInput"}}}}}}}}
```

## Get email batch job status

> Poll a batch of email items submitted via \`POST /v1/email/batch\`. 202 while running (with \`item\_count\`/\`processed\_count\` progress); 200 once SUCCEEDED (with \`counts\`, a presigned \`result\_url\`, and \`result\_data\` inlined when <=1MB); 409 if the credit reservation expired before delivery (resubmit); 500 if the job failed; 504 past the 24h ceiling.\
> \
> Reading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.2"},"tags":[{"name":"Email","description":"The email operations validate an address and, when only a name and a company website are supplied, look for one. Validation checks an address that is supplied; the search derives candidate addresses from the supplied name and website domain.\n\nFour dimensions are scored:\n- **Completeness:** whether an address is present, and whether one could be found from the name and website.\n- **Validity:** whether the address is syntactically well formed, its domain resolves, and the mailbox accepts mail.\n- **Accuracy:** whether the address corresponds to the person named in the request.\n- **Consistency:** the input value compared with its normalized version (not cross-source).\n\nThe result also carries two qualifications. `email_domain_qualification` reports whether the address's domain is a public/personal mail domain or a company domain, and whether it accepts mail at any address. `email_address_qualification` flags an address that is role-based (a shared functional mailbox such as `contact@`) or a known spam trap. Candidate addresses are returned ranked, each with a confidence score."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"EmailBatchPullOutput":{"additionalProperties":true,"description":"Response for `GET /v1/email/batch/{job_id}`. Each `result_data.items[]` entry is keyed to its request item by `dispatch_key` (`{\"record_id\": \"<job_id>#<index>\"}`). On success its `result` is the SAME object `GET /v1/email/{job_id}` returns for a single item. On failure it carries an `error` string instead of `result`.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"message":{"description":"A human-readable message describing the current state or outcome of the job.","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The HTTP status code representing the job's current state.","title":"Status Code","type":"integer"},"counts":{"anyOf":[{"$ref":"#/components/schemas/CountsModel"},{"type":"null"}],"default":null,"description":"Item-level outcome counts (present only once the job has completed)."},"result_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Presigned URL (1h expiry) to download the full batch result JSON from S3.","title":"Result Url"},"result_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The full batch result JSON, inlined (opaque). Present only when status_code == 200 and the result file is <=1MB; otherwise omitted (fetch `result_url` instead). Shape: `{job_id, usecase, counts, items: [...]}`; its `result` is the SAME object `GET /v1/email/{job_id}` returns for a single item.","title":"Result Data"},"item_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Total number of items in the batch (present while the job is running).","title":"Item Count"},"processed_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Number of items processed so far (present while the job is running; may be absent early in the job's lifecycle).","title":"Processed Count"},"process_time":{"anyOf":[{"minimum":0,"type":"number"},{"type":"null"}],"default":null,"description":"The total time taken to process the job, in seconds.","title":"Process Time"}},"required":["message","status","status_code"],"title":"EmailBatchPullOutput","type":"object"},"CountsModel":{"description":"Item-level outcome counts for a completed batch job.","properties":{"total":{"description":"Total number of items submitted.","title":"Total","type":"integer"},"succeeded":{"description":"Number of items that succeeded.","title":"Succeeded","type":"integer"},"failed":{"description":"Number of items that failed.","title":"Failed","type":"integer"}},"required":["total","succeeded","failed"],"title":"CountsModel","type":"object"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/email/batch/{job_id}":{"get":{"tags":["Email"],"summary":"Get email batch job status","description":"Poll a batch of email items submitted via `POST /v1/email/batch`. 202 while running (with `item_count`/`processed_count` progress); 200 once SUCCEEDED (with `counts`, a presigned `result_url`, and `result_data` inlined when <=1MB); 409 if the credit reservation expired before delivery (resubmit); 500 if the job failed; 504 past the 24h ceiling.\n\nReading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.","operationId":"getEmailBatchResult","responses":{"200":{"description":"Job succeeded — the result payload is populated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailBatchPullOutput"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailBatchPullOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"404":{"description":"Not found — no job exists for this id, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"409":{"description":"Conflict — the credit reservation expired before delivery; resubmit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"503":{"description":"Service unavailable — a downstream dependency was unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"504":{"description":"Gateway timeout — the job exceeded its processing ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"parameters":[{"name":"job_id","in":"path","required":true,"description":"The unique identifier of the email batch job.","schema":{"type":"string"}}]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.delpha.io/delpha-api-and-mcp/api/email.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `build a script that syncs our docs to a CMS` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
