Async Validation Jobs
Use asynchronous validation jobs for larger email lists that should be processed in the background. Jobs are Product Control Plane-owned public API workflows: the API authenticates withX-API-Key, reserves credits for unique submitted emails, validates asynchronously, finalizes charges for High-Value Validations, and refunds unused reserved credits.
Temporary SMTP Retry
If a recipient has valid DNS but the first SMTP attempt returns the explicitunknown_temporary status, the job pauses durably for 15 minutes and retries
that recipient. If it remains temporary, the job retries once more four hours
later. These retries complete before history, billing, result files, and
webhooks are finalized.
Policy, provider, budget, DNS, and transport unknowns are not eligible. If the
final attempt is still inconclusive, the final result remains uncharged
unknown. Synchronous single and bulk validation return immediately and do not
wait through this deferred retry window.
Fresh Evidence
Set"force_refresh": true on POST /v1/validate/batch to bypass the
control-plane domain-cache shortcut and the engine exact-email result cache.
The job stores this choice and uses it on initial and deferred attempts.
Omitted and false preserve normal cache-aware execution. Non-boolean values
return 400 with code: "invalid_force_refresh".
Authoritative suppression and recent-delivery evidence still take priority.
Provider limits and other caches remain in effect, so this option does not
guarantee a fresh SMTP observation for every address. Benchmark receipts do not
enable freshness automatically; request both options when needed.
Normal async credit reservation/refund rules still apply. The synchronous
30-day no-recharge window does not apply to async jobs. This option is for the
JSON batch endpoint, not the signed CSV upload workflow.
Endpoints
Required Scope
Scoped API keys needemail:validate:bulk. Legacy unrestricted keys retain compatible access until rotated.
Create Job
Use this JSON endpoint for scripts and SDKs that already have an array of emails. It accepts up to 500,000 submitted emails; valid duplicates are deduplicated before credit reservation. Each array member must be a string. Strings that fail the supported email syntax contract are skipped before credit reservation and reported in the creation response asinvalid_count; valid unique strings are reported as
email_count and queued for validation.
cURL
Idempotency-Key is optional and retained for 24 hours. Reuse the same opaque,
non-secret key when retrying the same logical job: the API returns the original
job response without creating another job or reserving credits again. Reusing a
key with different emails, webhook configuration, freshness, or benchmark-receipt mode
returns 409. An in-progress duplicate also returns 409 with Retry-After: 2.
For prospective accuracy acquisition, add
X-GTM-Benchmark-Receipt: email-benchmark-receipt-v6 and set
force_refresh to true. Version 6 signs that fresh evidence was requested,
along with exact mailbox identity, the bounded provider family, and the decisive
reviewed Microsoft SMTP route pattern and provenance version when available.
Version 5 preserves route provenance without the signed freshness claim;
version 4 preserves provider-family evidence; versions 2 and 3 preserve older
artifacts. Signing is preflighted
before credits are reserved. When the job finishes, benchmark_receipt
contains an ES256 compact JWS covering every ordered result row plus its
immutable decision_id, decided_at, decision_version, and
validation_source. The result CSV appends provider_family,
provider_family_version, benchmark_smtp_mx_route_pattern,
benchmark_smtp_provenance_version, and the three decision provenance columns.
The route pair is blank when the result did not obtain decisive reviewed
Microsoft SMTP evidence; do not infer it from mx_record. Receipt
payloads contain digests and aggregate metadata, never raw
addresses, domains, MX hosts, or verdicts.
Completed job results include unknown_reason_codes, a privacy-safe count map
using the same stable taxonomy as each result’s unknown_reason_code. Downloaded
result CSVs include the code and validation_retry_action alongside the existing
human-readable charge_reason. Retry only rows whose action is retry_later;
manual_review represents structural or provider-specific uncertainty.
Downloaded CSVs preserve tri-state evidence: smtp_valid and
is_domain_catch_all are true or false only when that signal was measured;
the cell is blank when validation did not establish the signal. A blank cell is
not equivalent to false.
Signed CSV Upload
Use this flow for large CSV files so the file body goes directly to Storage instead of through the API proxy.cURL
upload_url before the exact
upload_expires_at timestamp, then start processing. CSV input must be valid
UTF-8 without NUL bytes. A UTF-8 BOM is accepted; malformed UTF-8 and UTF-16
fail with an encoding-specific diagnostic before parsed-data metadata is
committed.
cURL
.prepare and .start suffixes. Reusing a key with the same
authenticated request returns the original successful JSON and sets
Idempotency-Replayed: true; changing the filename, webhook, batch, canonical
column mappings, or processing flags returns 409. An in-progress retry also
returns 409 with Retry-After: 2.
Prepare responses include upload_expires_at and replay only while that exact
signed capability remains valid (normally two hours). After it expires, the
same prepare key can create a fresh upload job, URL, and expiry.
Start-processing responses remain replayable for 24 hours. These endpoint-aware
windows prevent ambiguous network failures from creating duplicate jobs or
queueing the same uploaded file twice.
If the idempotency ledger is unavailable before the operation, the API returns
503 with code: "idempotency_unavailable"; retry the same request and key. If
the upload job or queue handoff succeeded but its replay record could not be
confirmed, the API returns 503 with
code: "idempotency_completion_failed"; retry the same key because the side
effect may already exist. Do not switch keys after an ambiguous completion.
Every signed-upload error includes a stable code. For prepare-upload, repair
invalid_filename, invalid_content_sha256, or invalid_webhook_url; retry
upload_prepare_failed with the same key. For start-processing, repair
missing_batch_id, missing_email_column, invalid_column_reference (the
field property identifies the input), or incomplete_contact_columns.
job_not_found means the batch is not available to this account, while
invalid_job_state means it already left the upload stage. Retry
processing_start_failed with the same key and bounded backoff.
Column references may be a header name or a zero-based integer index. String
references are trimmed, must contain a non-whitespace character, and may contain
at most 255 Unicode characters including surrounding whitespace. A canonical
nonnegative integer string of up to 15 digits, such as "2", is treated as
index 2; use a JSON integer for larger safe indexes. Other strings, including
numeric-prefix names such as 1st_email, remain literal header names.
Header-name matching is case-insensitive and must identify exactly one column.
If the selected name is duplicated, use its zero-based index instead; unrelated
duplicate headers do not affect the job.
For a missing name, a parse failure may include one high-confidence
Did you mean ...? hint when there is a uniquely best nearby header. The hint
is advisory: GTMAPIs never selects a fuzzy match, and ties or distant names
receive no suggestion.
If no delimiter can be detected and no header suggestion applies, the parse
failure may conditionally recommend re-exporting a multi-column file with a
comma, tab, semicolon, or pipe separator. GTMAPIs never guesses or silently
changes the delimiter; valid one-column files remain supported.
If you provide contact-name evidence, send both first_name_column and
last_name_column; GTMAPIs uses the pair for contact-pattern evidence and
rejects a missing or out-of-range explicit mapping instead of silently dropping
that accuracy signal. Omit both fields when the file does not contain names.
Duplicate mailbox rows are still validated and billed once. For contact-name
evidence, GTMAPIs prefers a complete first/last pair from one row over partial
or blank context. Equivalent pairs that differ only by case, accents, spacing,
or punctuation remain usable. If complete duplicate rows identify different
people, GTMAPIs suppresses name-based evidence for that mailbox rather than
guessing, voting, or combining names across rows. Original CSV rows remain
available in the result export.
List Jobs
cURL
invalid_page, invalid_limit, or
invalid_job_status. Repair the named filter before retrying.
Get Job Status
cURL
code: "job_not_found". Treat this as
terminal for that ID; do not continue polling it.
deferred_smtp_retry is an aggregate-only audit of up to two delayed retries
for explicit temporary SMTP unknowns, producing three total observations: the
initial pass, one 15 minutes later, and a final pass four hours after that. It is
omitted on older jobs. resolved
means a retry produced a final non-temporary result; it does not imply the
mailbox was valid or that an email was delivered. Enterprise gateways that
explicitly block recipient verification remain in the combined-evidence shadow
lane and are not repeatedly probed by this schedule.
benchmark_receipt is present only for an opted-in API batch after the final
CSV and immutable current-policy provenance are available. Verify its ES256
signature with https://api.gtmapis.com/.well-known/jwks.json, then recompute both the ordered result
projection and decision-provenance digest before using the artifact for an
accuracy claim.
Get Download URL
cURL
mode=url and follow the signed URL instead of pulling raw CSV content through MCP.
If results are still processing, the route returns job_not_ready and the
current job status; keep polling the job detail route. job_not_found means
the ID is unavailable, while job_file_not_available means the job exists but
the selected stored artifact does not.
Credit Behavior
- Credits are reserved up front for unique submitted emails.
- Only High-Value Validations are charged when processing completes.
- Role-based, catch-all, invalid, risky, and unknown results are refunded from the reservation.
- Failed-job recovery should refund unused reservations idempotently.
- Use
results.high_value,results.credits_consumed, andresults.credits_per_high_value_validationto measure cost per usable lead instead of raw cost per lookup.