Why didn't my email send?
The most common cause is test mode blocking an unlisted recipient — here's how to tell, plus every other condition that can block a send and what each one looks like in the response.
The single most common reason an email "didn't send" is that your organization is in test mode, which only delivers to addresses on an explicit allow-list — every other send is blocked before it reaches the provider. Every new organization starts in test mode. Beyond that, a send can also fail because the recipient is suppressed, you've hit a plan or rate limit, or (on managed sending accounts) your domain isn't verified yet. Most of these return a distinct, machine-readable error code from the API; a few currently only return a descriptive message (see below) — either way, the fastest path to an answer is reading the response body, not guessing.
Are you still in test mode?
New organizations start in test mode, where mail only reaches recipients you've explicitly allow-listed — either through a test list or org_send_settings.allowed_test_emails. Sending to anyone else in test mode fails with:
{
"error": "Test mode: 1 recipient(s) are not in your test lists. Add them to a test list or switch to production mode.",
"code": "TEST_MODE_RECIPIENT_NOT_ALLOWED"
}(HTTP 422.) If you're testing against your own inbox and it's arriving fine but a colleague or customer isn't receiving anything, this is almost always why — add the address to a test list, or switch the organization (or the specific use case, if you've scoped it there) to production mode once you're ready to send real mail.
Test mode is scoped per use case, not just per account: a use case can be set to test mode even inside an otherwise-production organization, and vice versa is not possible — a test API key always forces test mode regardless of the org or use case setting.
Did the API return an error?
These conditions return a distinct HTTP status and a machine-readable code in the response body — check for these first:
| Status | Code | What it means |
|---|---|---|
422 | TEST_MODE_RECIPIENT_NOT_ALLOWED | Test mode is active and the recipient isn't allow-listed. |
422 | RECIPIENT_SUPPRESSED | The to address has bounced, unsubscribed, or complained before — see Bounces and suppressions. |
422 | MARKETING_NOT_ENABLED | A marketing-type send was attempted without marketing enabled and a CAN-SPAM postal address set (Settings → Marketing). |
400 | CC_BCC_NOT_SUPPORTED_FOR_TEMPLATE | A templated send included cc or bcc — send one request per recipient instead. |
A cc or bcc address that's suppressed is dropped silently from that one send rather than blocking it — only a suppressed to address rejects the whole message. See Send a transactional email for the full request/response reference these come from.
Four other conditions can also block a send — an unverified domain on a managed account, an account paused for review, a managed account's IP-warmup cap for the day, and a used-up monthly plan allowance — but on POST /api/v1/email/send today they currently surface as a generic 500 response rather than a distinct status and code: you'll get a clear message describing exactly which of the four it is, just not a machine-readable code field to branch on programmatically yet. Match on the message text in the meantime:
| What it means | Message contains |
|---|---|
| Unverified domain on a managed account | "Sending is locked until your domain is authenticated" — see Domains |
| Account paused for review | "Sending is paused while we review this account's recent delivery results" |
| Managed account's daily IP-warmup cap reached | "Today's warm-up limit for this account is" — see Emails going to spam |
| Monthly plan allowance used up | "Plan limit exceeded" |
Is the recipient suppressed?
Before sending to an address you're unsure about, check it directly:
GET /api/v1/suppressions/check?email=someone@example.comThis returns whether the address is currently suppressed and why, without requiring you to page through the whole suppression list. See Bounces and suppressions for how addresses end up on that list in the first place, and for what to do about a RECIPIENT_SUPPRESSED response.
Have you hit a sending limit?
Two separate ceilings can block a send, distinguishable by the message text (see the table above): a managed account's IP pool still warming up ("Today's warm-up limit for this account is...", temporary, resets the next day) and your plan's monthly email allowance being used up ("Plan limit exceeded...", resets on the monthly cycle or requires a plan upgrade). Neither is the API request rate limit (60 requests/minute, unrelated to email volume) — see Why am I getting 429 errors? for that one specifically.
Is your domain verified?
This only applies if NevarMail provisioned your sending account for you (a managed account) rather than you connecting your own ESP. A managed account with no verified domain is blocked on every send attempt ("Sending is locked until your domain is authenticated...") until you complete domain verification — see Domains. BYO accounts aren't gated this way by NevarMail; your own provider's rules still apply.
How do you check what happened to a specific message?
If the API returned success but you still don't see the message land, look it up directly:
GET /api/v1/analytics/messages/:messageIdmessageId is the id field from the send response, not the provider's own message ID. It returns the message's status (sent, failed, rejected, pending, or cancelled for a scheduled send) plus its event timeline. See Read your analytics for the full response shape.
- I sent a test email to myself and it worked, but my customer says they never got theirs. Why?
- This is almost always test mode: your own address is likely allow-listed for testing, and everyone else's isn't. Check whether your organization or use case is still in test mode, and add the recipient to a test list or switch to production.
- The API returned a 200 but the recipient never got the email. What happened?
- Check the message's status field in the response, and the sdkCall.method it carries if status is "rejected" — a suppressed or non-compliant marketing send can return a soft rejection inside a 2xx-shaped call rather than an HTTP error, depending on which endpoint you called. Look up GET /api/v1/analytics/messages/:messageId for the definitive answer.
- What's the difference between the IP-warmup limit and the plan quota limit?
- The IP-warmup limit is a temporary, per-day cap on managed accounts still building sending reputation, and it resets tomorrow. The plan quota is your monthly email allowance being used up, which resets on your billing cycle or requires an upgrade. Neither currently returns a distinct error code on the send API -- match on the message text (see the error table above) until they do.
- Can I bypass test mode for a single send without changing my account settings?
- No — test mode is set at the organization or use-case level, not per request. A test API key forces test mode regardless of what the org or use case is set to, but there's no per-request override to send live from an otherwise test-mode account.
Verify a “from” address
Set up the addresses you send from, get them verified, and understand why an unverified sender cannot send.
Why are my emails going to spam?
The four things mailbox providers actually check — domain authentication, sending reputation, recipient engagement, and content — and where to look at each one.