Skip to content

Errors and request ids

Every error has the same flat body:

{
"statusCode": 422,
"name": "validation_error",
"message": "subject: Required",
"code": "validation_failed",
"request_id": "req_..."
}
  • statusCode, name and message are Resend’s fields, so code that branches on error.name keeps working.
  • code is Duta’s, and finer grained. Branch on it in new code.
  • message is written for a developer. Log it, but do not show it to your users.
  • detail, when present, carries more, such as every failure in a batch.
  • request_id identifies the request.

Every response carries an X-Request-Id header, and every error body the same value as request_id. Paste it into the search on the Logs screen to see the request, the response and the key that made it. Quote it when you ask for help.

codeHTTPnameMeaning
unauthorized401invalid_api_keyThe API key is missing, wrong or revoked.
forbidden403invalid_accessThe key cannot do this. A sending key tried to manage the account, or the action is not allowed.
not_found404not_foundNothing with that id exists in this account.
validation_failed422validation_errorThe request body or a parameter is invalid. message names the field.
domain_not_verified403validation_errorThe from address is on a domain that has not verified yet.
from_domain_not_allowed403invalid_from_addressThe from address is on a domain this account cannot send from.
recipient_suppressed422validation_errorThe recipient is on the suppression list.
recipient_not_confirmed422validation_errorA sandbox send to an address that has not confirmed it wants this account's test mail.
rate_limited429rate_limit_exceededToo many requests. Wait for the Retry-After header and try again.
quota_exceeded429monthly_quota_exceededA plan limit was reached, such as the daily limit, the overage cap or the number of domains.
conflict409validation_errorThe request clashes with the current state, such as a plan change already in progress.
payment_required402application_errorThe account needs a paid plan for this.
account_paused403invalid_accessSending is paused on this account. The dashboard says why.
content_rejected422security_errorThe message was refused by content screening.
platform_halted503application_errorSending is halted across Duta. Retry later.
payload_too_large413validation_errorThe request body is over 14 MB.
length_required411validation_errorThe request body has no Content-Length header.
idempotency_conflict409invalid_idempotent_requestThe Idempotency-Key was used with a different body, or its first request is still running.
provider_error502application_errorThe upstream mail provider failed or timed out. Safe to retry.
internal_error500internal_server_errorSomething failed inside Duta. Quote the request_id to support.

Retry rate_limited, platform_halted, provider_error and internal_error after a wait, with backoff. Also retry concurrent_idempotent_requests (code idempotency_conflict) after waiting for the in-flight request to finish. Send an Idempotency-Key so a retry cannot send twice. The rest mean the request needs to change first, and repeating it will fail the same way.