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 — through a test list. Test lists are organization-level today and apply to every project (per-project test lists are not enabled yet). 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 layered: organization, then project, then use case, and the most specific wins. See Test mode and safe send. A use case can be in test mode even inside a live project. A test API key always forces test mode, whatever the organization, project or use case says.
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 | COMPLIANCE_ADDRESS_REQUIRED | The sending project has no postal address; marketing email and email under a use case recipients can opt out of carry it in the unsubscribe footer. Set it in Project Settings → Postal address. |
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.
Sync contacts and lists from your own system
Create lists, add subscribers, and keep contact details current from your CRM, app or database with the NevarMail lists and contacts API.
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.