Skip to main content

Error Handling Guide

Learn how to properly handle errors from the GTMAPIs validation API.

Error Response Format

All errors return an appropriate HTTP status code with JSON body:
Branch on code when it is present; error is written for people and may be clarified over time. Official clients preserve server-provided codes and fall back to a stable status-derived code when an older response does not include one.

Request Correlation

Every application response documented in OpenAPI includes an opaque X-Request-ID header. Preserve the ID from the terminal response and include it in support reports so the server-side trace can be located. Do not reuse an ID from an earlier retry when the final attempt fails before receiving an HTTP response; that network-only failure has no server-authored request ID. Official SDK errors, CLI errors, and MCP structured errors expose the sanitized identifier directly. It is diagnostic metadata only and never affects whether an address is valid, chargeable, suppressed, or safe to send.

HTTP Status Codes

For example, a validation request that cannot reserve credits returns code: "insufficient_credits"; a temporary validation dependency failure returns code: "validation_upstream_failed". When present, required is the reservation needed for the request and available is the balance observed by the API. Official SDKs, the CLI, and MCP preserve both fields; treat available as optional because older and synchronous responses may omit it. Official SDKs, the CLI, and the local MCP package automatically attach idempotency keys to single validation, synchronous bulk, and asynchronous job writes. Supply a durable caller key when the same logical request may be retried after a process restart or across agent turns. Reuse it only with the identical request body; changed semantics return idempotency_key_conflict. Clients retry network/timeouts, idempotency_request_in_progress, rate limits, and 5xx responses with bounded attempt budgets while preserving request identity. They do not retry bad input, authentication, insufficient credits, forbidden access, changed-body idempotency conflicts, or control_plane_route_misconfigured. The last code needs operator repair, so an automatic retry cannot make progress. Unknown future 5xx codes keep the status-based retry fallback.

Email Validation Codes

Every error from POST /v1/validate, POST /v1/validate/bulk, and POST /v1/validate/batch carries a stable code. Use these codes to decide whether to repair the request, split it, preserve its idempotency key, or retry: An email string with invalid syntax is not a request-shape error. It remains a successful validation response with result: "invalid", so bulk callers keep one result per submitted string.

Signed CSV Write Codes

The signed-upload preparation and processing-start routes use these additional codes. Preserve the same idempotency key when the action says to retry:

Catch-All Recovery Codes

Recovery start also uses job_not_found, invalid_job_state, and insufficient_credits. Its read and operational failures add these codes:

Asynchronous Job Read Codes

The list, detail, and download routes use these additional codes:

Email Outcome Codes

Outcome import reuses invalid_json and payload_too_large. Import, report, and EmailBison connector routes use these additional codes:

Recovery Feedback Codes

The gated catch-all recovery feedback import reuses invalid_json, payload_too_large, missing_outcomes, and too_many_outcomes.

Credit Balance Codes

API Gateway Codes

The public gateway uses these codes when it cannot reach the Product Control Plane. Preserve the request’s idempotency key for a retryable write.

Authentication and Access Codes

Every rejection from the shared gates — API key, scope, subscription, product availability, rate limit — carries a code. Each one has a different fix, so branch on the code rather than on the status alone: api_key_expired, api_key_inactive, and api_key_revoked are deliberately separate codes even where the human-readable error string is the same, because expiry is routine rotation, deactivation is reversible, and revocation is not. That distinction is only available in code. Codes are append-only. A code that exists keeps its meaning; a condition that later needs its own code gets a new one, so a switch you wrote today keeps matching everything it already handles.

Common Errors

400 Bad Request

Cause: Invalid request format or missing required fields

Missing Email Field

Solution: Include email field in request body

Invalid Email Syntax

Solution: Treat this HTTP 200 response as a completed validation. Do not retry or send to the address. Client-side format checks can improve form feedback, but the API result remains the validation source of truth.

Too Many Emails in Bulk Request

Solution: Split into batches of 100

401 Unauthorized

Cause: Missing or invalid API key

Missing API Key Header

Solution: Always include X-API-Key header

Invalid API Key

Solution: Verify API key format and validity

Revoked API Key

Solution: Generate a new API key from the dashboard

403 Forbidden

When a key lacks permission, the API returns the exact scope needed for the endpoint:
Do not retry this response with the same key. Add required_scope to the key, or rotate to a least-privilege key that includes it, and then retry. Branch on code; do not parse the human-readable error string. Other product or entitlement gates can also return 403 without required_scope. Treat those as non-retryable access failures and preserve the human-readable error for the operator.

429 Too Many Requests

Cause: Rate limit exceeded (10,000 requests/minute per API key or 1,000 requests/minute per IP)
Solution: Implement retry logic with exponential backoff

500 Internal Server Error

Cause: Unexpected server error
Solution: Retry request or contact support

503 Service Unavailable

Cause: Service temporarily unavailable (maintenance or overload)
Solution: Implement circuit breaker pattern

Validation Result Errors

Even with HTTP 200, emails can have validation issues:

Invalid Email

Handling:

Risky Email

Handling:

Unknown Verification

Handling:

Error Handling Patterns

Comprehensive Error Handler

Bulk Validation Error Handling

Monitoring and Logging

Log Errors for Analysis

Track Error Rates

Next Steps

Rate Limits

Understand rate limiting strategies

API Integration

Full integration patterns