Errors
Every error code the API returns, what causes it and how to fix it.
Every error has the same shape. Branch on code in your code; message is for people and may change.
{
"error": {
"type": "validation_error",
"code": "invalid_from_address",
"message": "The from address can't be used. Use a verified domain, one of your sender handles, or the sandbox.",
"fields": {
"from": "Domain not verified"
},
"doc_url": "https://padimail.dev/errors#invalid_from_address",
"request_id": "req_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S"
}
}fieldsappears on validation errors, naming each field with its problem. Batch validation addserrors: one{ index, code, message }per invalid email.- Quote
request_id(also in theX-Request-Idheader) when you contact support. - Retry
429,500and503with backoff, waiting forRetry-Afterwhen it's sent. Don't retry other4xxerrors unchanged. The Node SDK retries for you. - The Resend-compatible API returns Resend's error shape instead, with our code in
pm_code. See Switch from Resend.
400: the request isn't valid
validation_failed
400 · validation_error
Some fields aren't valid. Check the fields listed and try again.
Cause. One or more fields are missing or in the wrong format. The fields object names each one with the problem.
Fix. Correct the fields listed in fields and send the request again.
invalid_from_address
400 · validation_error
The from address can't be used. Use a verified domain, one of your sender handles, or the sandbox.
Cause. The from address isn't one you can send from: its domain isn't added or verified, or the sender handle isn't yours.
Fix. Use an address on a verified domain, one of your sender handles, or onboarding@sandbox.padimail.app. If the domain is new, add the DNS records shown on its page and check again.
too_many_recipients
400 · validation_error
An email can have at most 50 recipients across to, cc and bcc.
Cause. to, cc and bcc together have more than 50 addresses.
Fix. Split the email into several, or use POST /v1/emails/batch to send one email per recipient.
missing_body
400 · validation_error
Add html, text or a template.
Cause. The email has no html, text or template.
Fix. Add html and/or text, or a template with its variables.
attachment_too_large
400 · validation_error
The email is larger than 40 MB with its attachments.
Cause. The whole message, with attachments encoded, is over 40 MB.
Fix. Make the attachments smaller, or link to the files instead of attaching them.
invalid_scheduled_at
400 · validation_error
scheduled_at must be between 1 minute and 30 days from now.
Cause. scheduled_at is less than 1 minute or more than 30 days away, or isn't an ISO 8601 time.
Fix. Send a time such as 2026-10-28T09:00:00+01:00 between 1 minute and 30 days from now.
template_variables_missing
400 · validation_error
Some required template variables are missing.
Cause. The template declares required variables that the request didn't include.
Fix. Pass every required variable in template.variables. POST /v1/templates/{id}/render lists what's missing.
handle_not_allowed
400 · validation_error
That handle can't be used.
Cause. The sender handle matches a protected brand, a reserved word or our blocklist.
Fix. Choose a handle that's clearly your own organisation's name.
missing_org
400 · validation_error
Choose an organisation (send the X-PM-Org header).
Cause. A dashboard request didn't say which organisation it was for.
Fix. This only affects the dashboard. Reload the page and choose an organisation.
401: the API key is missing or wrong
missing_api_key
401 · authentication_error
Send your API key in the Authorization header: Bearer pm_live_…
Cause. The request had no Authorization header.
Fix. Send Authorization: Bearer pm_live_… (or pm_test_…). Keys in the query string are refused.
invalid_api_key
401 · authentication_error
That API key isn't valid.
Cause. The key doesn't exist, or is mistyped.
Fix. Copy the key again, or create a new one under API keys in the dashboard. Keys are shown only once.
revoked_api_key
401 · authentication_error
That API key has been revoked. Create a new one in the dashboard.
Cause. Someone in your organisation revoked this key.
Fix. Create a new key under API keys and update your server's environment.
not_signed_in
401 · authentication_error
Sign in to continue.
Cause. A dashboard request was made without a signed-in session.
Fix. Sign in again.
402: payment needed
insufficient_credits
402 · payment_required
You don't have enough credits for this email.
Cause. Your credit balance can't cover this email, and you asked for quota_behavior: "reject".
Fix. Buy credits under Billing, or leave out quota_behavior so the email waits until credits arrive.
plan_limit_reached
402 · payment_required
Your plan's limit has been reached.
Cause. Your plan's limit is used up, and you asked for quota_behavior: "reject".
Fix. Upgrade your plan, wait for the limit to reset, or let the email wait instead of rejecting it.
403: not allowed
forbidden
403 · permission_error
You don't have permission to do this.
Cause. The key or member doesn't have permission for this. A sending-only key can only send, read and cancel emails.
Fix. Use a full-access key, or ask an owner or admin to change your role.
phone_verification_required
403 · permission_error
Verify your phone number before sending with a live key. Test keys work now.
Cause. Live keys work only after the organisation owner verifies a phone number.
Fix. Verify your phone under Verification. Test keys (pm_test_…) work in the meantime.
sandbox_recipient_not_verified
403 · permission_error
In the sandbox you can only send to your organisation's verified addresses. Verify your identity to send to anyone.
Cause. In the sandbox (Tier 0) you can only send to your organisation's own verified email addresses.
Fix. Send to a member's address, or verify your identity (Tier 1) to send to anyone.
tier_required
403 · permission_error
Your verification tier doesn't allow this yet.
Cause. This needs a higher verification tier than your organisation has.
Fix. Complete the next verification step under Verification. The error message says which tier is needed.
account_suspended
403 · permission_error
This organisation is suspended.
Cause. Our trust and safety team suspended the organisation.
Fix. Check your email for our message, or contact support with the request ID.
account_paused
403 · permission_error
Sending is paused for this organisation.
Cause. Sending is paused, by an automatic brake (high bounces or complaints) or by a member.
Fix. Open the dashboard: the banner explains why and what to do before sending resumes.
sender_not_allowed
403 · permission_error
This key can't send from that address.
Cause. The API key is restricted to one domain, and the from address uses another.
Fix. Send from the key's domain, or use a key without a domain restriction.
not_a_member
403 · permission_error
You aren't a member of this organisation.
Cause. You aren't a member of the organisation the request was for.
Fix. Switch to an organisation you belong to, or ask an owner for an invitation.
email_not_verified
403 · permission_error
Verify your email address first. We sent a code to it when you signed up.
Cause. The signed-in dashboard user hasn't verified their email address yet. Until they do, they can't create or join an organisation or act in one.
Fix. Enter the code from the verification email (or ask for a new one on the verification page), then try again.
404: not found
not_found
404 · not_found
We couldn't find that.
Cause. Nothing with that ID exists in this organisation and mode.
Fix. Check the ID, and that you're using a key from the right organisation. Test keys only see test data.
email_not_found
404 · not_found
We couldn't find that email.
Cause. No email with that ID exists in this organisation, or it's older than 90 days.
Fix. Check the ID and the key. Live and test emails are separate: a pm_test_ key can't see live emails.
domain_not_found
404 · not_found
We couldn't find that domain.
Cause. No domain with that ID exists in this organisation.
Fix. List your domains with GET /v1/domains to find the right ID.
template_not_found
404 · not_found
We couldn't find that template.
Cause. No template with that ID or alias exists in this organisation.
Fix. Check the ID or alias with GET /v1/templates.
webhook_not_found
404 · not_found
We couldn't find that webhook.
Cause. No webhook endpoint with that ID exists in this organisation.
Fix. List your endpoints with GET /v1/webhooks.
suppression_not_found
404 · not_found
We couldn't find that suppression.
Cause. No suppression with that ID exists, or it has already been removed.
Fix. Search with GET /v1/suppressions?address=….
api_key_not_found
404 · not_found
We couldn't find that API key.
Cause. No API key with that ID exists, or it's already revoked.
Fix. List your keys with GET /v1/api-keys.
invitation_not_found
404 · not_found
We couldn't find that invitation.
Cause. The invitation link is wrong, or the invitation was withdrawn.
Fix. Ask the person who invited you to send a new invitation.
organization_not_found
404 · not_found
We couldn't find that organisation.
Cause. That organisation doesn't exist, or you can't see it.
Fix. Choose an organisation from the switcher in the dashboard.
409: conflict
idempotency_conflict
409 · conflict
This Idempotency-Key was already used with a different request body.
Cause. The Idempotency-Key was used in the last 24 hours with a different request body.
Fix. Use a new key for a different request. Reuse a key only to retry exactly the same request.
domain_already_exists
409 · conflict
You've already added this domain.
Cause. Your organisation has already added this domain.
Fix. Open the existing domain instead of adding it again.
handle_taken
409 · conflict
That handle is taken.
Cause. Another organisation already uses this sender handle, or released it less than 90 days ago.
Fix. Choose a different handle.
email_already_sent
409 · conflict
This email has already been sent.
Cause. You tried to change or cancel an email that has already been handed over for delivery.
Fix. Only scheduled, waiting or held emails can be changed or canceled.
alias_taken
409 · conflict
Another template already uses that alias.
Cause. Another template in your organisation already uses this alias.
Fix. Pick a different alias, or change the other template's alias first.
already_member
409 · conflict
This person is already a member.
Cause. That person is already a member of the organisation.
Fix. Change their role on the Team page instead of inviting them again.
last_owner
409 · conflict
An organisation needs at least one owner. Make someone else an owner first.
Cause. This change would leave the organisation without an owner.
Fix. Make another member an owner first.
invalid_state
409 · conflict
This can't be done in the current state.
Cause. The resource isn't in a state that allows this, for example rescheduling an email that isn't scheduled.
Fix. Fetch the resource to see its current status, then try an action that fits it.
410: gone
content_expired
410 · gone
This email's content was deleted after your plan's retention period.
Cause. The email's content was deleted after your plan's retention period. Its status and events are still kept.
Fix. Keep your own copy of content you need for longer, or move to a plan with longer retention.
invitation_expired
410 · gone
This invitation has expired. Ask for a new one.
Cause. The invitation link is past its expiry date.
Fix. Ask for a new invitation.
422: content blocked
content_blocked
422 · unprocessable
This content can't be sent under our acceptable use policy.
Cause. Content scanning blocked the email under our acceptable use policy. The message says why in general terms.
Fix. Change the content. If you think it's a mistake, contact support with the request ID.
429: too many requests or over a limit
rate_limited
429 · rate_limit_error
Too many requests. Slow down and retry after the time in Retry-After.
Cause. Too many requests from this key in a short time (10 a second, bursts to 20, by default).
Fix. Wait for the time in Retry-After and try again. The Node SDK does this for you. Use batch sending for many emails.
daily_quota_exceeded
429 · rate_limit_error
You've reached today's sending limit.
Cause. Today's sending limit is used up, and you asked for quota_behavior: "reject".
Fix. Wait for the limit to reset at midnight in your organisation's time zone, or let the email wait instead of rejecting it.
monthly_quota_exceeded
429 · rate_limit_error
You've reached this month's sending limit.
Cause. This month's sending limit is used up, and you asked for quota_behavior: "reject".
Fix. Upgrade your plan or buy credits, or let the email wait.
warmup_limit_reached
429 · rate_limit_error
This sender's warm-up allowance for today is used up.
Cause. A new sender handle sends a little more each day while it warms up, and today's allowance is used.
Fix. Let the email wait for tomorrow's allowance, or send from a verified custom domain.
sandbox_limit_reached
429 · rate_limit_error
You've reached the sandbox limit of 50 emails today.
Cause. The sandbox allows 50 emails a day, and you asked for quota_behavior: "reject".
Fix. Verify your identity (Tier 1) for higher limits, or let the email wait until tomorrow.
deferred_queue_full
429 · rate_limit_error
Too many emails are already waiting for your limit. Cancel some or raise your limit.
Cause. So many emails are already waiting for your limit that no more can be added.
Fix. Cancel waiting emails you no longer need, or raise your limit by upgrading or verifying.
500: server error
internal_error
500 · api_error
Something went wrong on our side. Retry with backoff; quote the request ID if it keeps happening.
Cause. Something failed on our side.
Fix. Retry with backoff (the Node SDK does). If it keeps happening, contact support with the request ID.
501: not available yet
not_implemented
501 · not_implemented
This endpoint isn't available yet.
Cause. This endpoint isn't available yet.
Fix. Check the docs for the endpoint's status. The error links to the closest working alternative where there is one.
503: service unavailable
service_unavailable
503 · api_error
The service is busy. Retry with backoff.
Cause. The API is busy or in maintenance.
Fix. Retry with backoff. Check the status page if it lasts more than a few minutes.