REST API response codes are the first signal that something happened when your application sends transactional email—but they are not always a final answer about inbox delivery. A successful API response may mean a provider accepted a message for processing, while the eventual SMTP result can still be deferred, bounced, quarantined, or delivered.

This guide explains the HTTP and SMTP status codes developers encounter when sending email through an API or SMTP relay. It focuses on practical interpretation: what each class of response means, whether to retry, what to log, and where DNS authentication fits into the debugging process.

The email delivery lifecycle behind REST API response codes

A transactional email request usually passes through several distinct stages. Understanding those stages prevents one of the most common mistakes in email engineering: treating an HTTP 2xx response as proof that the recipient received the email.

A typical lifecycle looks like this:

  1. Your application sends a request to an email provider's REST API, or submits a message to an SMTP relay.
  2. The provider authenticates the request and validates its structure, sender, recipients, and account-level rules.
  3. The provider accepts the message into a queue, renders any templates, applies tracking or suppression checks, and signs the message if configured.
  4. The provider's mail transfer agent connects to the recipient domain's MX server and attempts SMTP delivery.
  5. The receiving server accepts, temporarily defers, rejects, filters, or later bounces the message.

The first interaction uses HTTP when you call a REST API. The later delivery interaction uses SMTP. Each protocol has its own response-code system, and each response answers a narrower question than developers often assume.

For example, an HTTP 202 Accepted commonly means the API accepted a valid request for asynchronous processing. It does not mean the remote mailbox accepted the message. By contrast, an SMTP 250 after the final DATA command generally means the receiving SMTP server accepted the message for delivery—but even that can still be followed by spam filtering, mailbox rules, or later non-delivery notifications.

The practical lesson is to track delivery as a state machine rather than a single request outcome:

  • API request outcome: Did your provider accept the request?
  • Provider processing outcome: Was the message rendered, queued, and submitted?
  • Recipient SMTP outcome: Did the destination mail server accept it?
  • Mailbox outcome: Was it delivered to the inbox, another folder, quarantine, or rejected after acceptance?

A reliable sending integration records identifiers and events across these stages. When available, save the provider message ID returned by the API, your own application-level notification ID, the recipient address, the HTTP status, and any later delivery or bounce event.

How to read HTTP status-code families

HTTP status codes have three digits. The first digit tells you the broad category of the response, while the full code provides more specific semantics. Email APIs may add their own JSON error fields, machine-readable error codes, and request IDs, but the HTTP status remains the first classification to inspect.

1xx: informational responses

1xx responses are provisional protocol messages. Application code sending email through a normal HTTPS client rarely handles them directly. They are not normally a sign of submission success or failure.

If your logs show a 100 Continue, it typically relates to HTTP request handling rather than email processing. Do not build delivery logic around 1xx responses.

2xx: the API accepted or completed the request

A 2xx response means the API considered the request successful at the HTTP layer. The exact meaning depends on the code and the endpoint's contract.

Common examples include:

  • 200 OK: The request succeeded and the response contains a representation or result.
  • 201 Created: The request created a resource, such as a scheduled send, stored template, or API-managed object.
  • 202 Accepted: The API accepted the request for asynchronous processing.
  • 204 No Content: The request succeeded and the server has no response body to return.

For transactional email, 202 Accepted is particularly important. Message delivery is naturally asynchronous: rendering, queueing, routing, retrying, and communicating with remote MX servers can take time. A 202 therefore usually means, “the platform accepted responsibility for attempting this work,” not “the work has finished.”

Treat a successful status as a reason to persist the message ID and await downstream events, not as a reason to mark a customer notification as definitively delivered. If your system sends a password-reset email, you might mark the notification as submitted after a 202, then update it to delivered, deferred, or bounced only when later event data supports that outcome.

3xx: redirects are unusual for email APIs

3xx responses indicate redirection. A REST API for email sending should rarely return them during normal programmatic use. A redirect may occur because you called an outdated base URL, used HTTP instead of HTTPS, sent a request to a dashboard route rather than an API endpoint, or passed through a proxy that rewrites traffic.

Do not blindly follow redirects for authenticated POST requests without understanding the destination. Redirect behavior can vary by HTTP client and status code, especially for POST bodies. Verify the configured API base URL, use HTTPS, and consult the provider's API reference rather than copying a browser-oriented URL.

4xx: the request cannot be processed as sent

A 4xx response means the client request has a problem, lacks authorization, conflicts with a current state, or exceeds a limit. The key question is whether a retry with the same payload can succeed. Usually, it cannot.

The most important 4xx codes for email integrations are:

CodeTypical meaning in email sendingRetry unchanged?First action
400 Bad RequestInvalid JSON, missing field, malformed email address, invalid parameter valueNoFix the payload and validate inputs
401 UnauthorizedMissing, expired, invalid, or incorrectly formatted API credentialsNoCheck credentials and authorization header format
403 ForbiddenCredential is valid but lacks permission, sender/domain is not authorized, account restrictionNoCheck sender verification, scopes, account state, and policy
404 Not FoundWrong endpoint, nonexistent resource, invalid message/template IDNoCheck the URL, method, and resource ID
409 ConflictRequest conflicts with resource state, duplicate idempotency key, incompatible updateDependsRead the error body and reconcile state
413 Content Too LargeRequest body, attachment, or message exceeds a limitNoReduce attachment or message size
415 Unsupported Media TypeWrong Content-Type, often not JSON when JSON is expectedNoSend the documented media type and valid encoding
422 Unprocessable ContentValid syntax but failing semantic validation, such as invalid sender configurationNoCorrect the business-level validation error
429 Too Many RequestsRate limit or quota window exceededYes, laterRespect retry guidance and back off

A response body matters as much as the status code. A 400 can represent a malformed JSON document, but it can also be a semantically invalid recipient address depending on the API. Log the structured error code, field name, human-readable message, response headers, and provider request ID where one is supplied.

400 Bad Request and 422 Unprocessable Content

400 and 422 are often confused. In practice, APIs differ in how they divide validation failures between them. The useful distinction is operational:

  • A malformed request cannot be understood or processed as sent.
  • A structurally valid request may still fail validation because a value is unacceptable in context.

Examples of problems worth catching before your API call include:

Missing recipient address
An empty From address
A From domain your account has not authenticated
A malformed JSON payload
An attachment encoded incorrectly
A scheduled-send timestamp in the past
A template variable required by your template but not supplied

Client-side validation improves user-facing errors and reduces unnecessary requests, but it should not replace server-side validation. The email provider has information your application does not, including account permissions, suppression lists, sending limits, domain authorization, and content policies.

401 Unauthorized versus 403 Forbidden

401 usually points to authentication: an absent key, a revoked key, an accidental space in an environment variable, or the wrong authorization scheme. A common debugging step is to confirm that the deployment environment has the expected secret loaded and that your client sends it in the documented header.

403 means authentication succeeded but access is denied. In transactional email, plausible reasons include an unverified sending identity, an API key missing a required scope, a disabled account, a policy restriction, or an attempt to use a feature unavailable to the account.

Do not respond to either code by retrying in a tight loop. Repeating an invalid credential can produce noise, trigger security controls, and obscure the real failure. Alert an operator for unexpected 401 and 403 spikes.

404 Not Found and method mistakes

A 404 can mean the endpoint path is wrong, but it can also appear when a resource identifier is wrong or when an API intentionally hides inaccessible resources. Confirm all of the following:

  1. The base API URL is correct for the environment.
  2. The endpoint path and version match the current documentation.
  3. The HTTP method is correct: POST is not interchangeable with GET or PUT.
  4. Any path ID is the provider's ID, not your internal database ID.
  5. Your SDK version and manually configured URL do not conflict.

For a provider that supports both REST API submission and SMTP relay, keep the two configuration models separate. An SMTP hostname is not an HTTP API base URL, and an API key is not automatically an SMTP username and password.

429 Too Many Requests: retry deliberately

429 Too Many Requests is the response you should expect when an API rate limit is exceeded. It is a temporary condition, but it is not permission to retry immediately.

First inspect response headers and the error body. Some APIs include a Retry-After header with a delay in seconds or an HTTP date. Others publish limit, remaining, and reset details in provider-specific headers. Use those instructions when available.

If no retry guidance is returned, use exponential backoff with jitter. For example:

attempt 1: wait approximately 1 second
attempt 2: wait approximately 2 seconds
attempt 3: wait approximately 4 seconds
attempt 4: wait approximately 8 seconds

Add random jitter so many workers do not retry at the same instant. Cap retries, enforce a maximum queue age appropriate to the message type, and route exhausted jobs to a dead-letter queue or an alerting workflow.

A password reset is time-sensitive; retrying it for hours may create an unsafe or confusing user experience. A receipt or low-priority product notification may tolerate longer retry windows. Define retry policy by message class, not just by status code.

5xx: the provider or an upstream dependency had trouble

5xx responses indicate that the server could not fulfill an otherwise plausible request. They are usually candidates for retry, but not all 5xx responses should receive identical treatment.

Common examples:

  • 500 Internal Server Error: An unexpected server-side failure.
  • 502 Bad Gateway: A gateway or proxy received an invalid upstream response.
  • 503 Service Unavailable: Temporary overload, maintenance, or unavailable dependency.
  • 504 Gateway Timeout: A gateway did not receive a timely upstream response.

For transient 5xx failures, retry using exponential backoff and jitter. But first consider whether the initial request might have been processed despite the timeout. This is especially important for message-sending POST requests: a network failure after your client transmits the request can leave you uncertain whether the API accepted the message.

Idempotency prevents duplicate transactional email

A retryable failure can create a duplicate-send risk. Suppose your application submits an invoice email, the server queues it successfully, and the connection drops before your application receives the response. Your retry may queue the invoice a second time.

The best solution is idempotency. If your provider supports an idempotency mechanism, use it exactly as documented. Often this is a unique key associated with a request, allowing the server to recognize a safe repeat submission. If the provider does not offer one, implement application-level deduplication.

A practical application-side approach is to create a durable send record before calling the email API:

notification_id: inv_01J...
message_type: invoice_receipt
recipient: customer@example.net
business_event_id: order_78421
send_state: pending
attempt_count: 0

Use a uniqueness constraint based on the business event, recipient, and notification type where appropriate. For example, an order receipt might be unique per order and recipient, while a weekly digest should be unique per recipient and scheduled period.

When a request times out, do not simply send again. First determine whether you can query message status by your internal reference or inspect your outbound event stream. If the message was accepted, update your record rather than re-submitting it.

SMTP response codes: what happens after API acceptance

Once a provider attempts delivery, SMTP response codes describe how the next mail server responded. SMTP status codes are usually three digits, such as 250, 421, 450, or 550.

The first digit provides the core meaning:

  • 2xx: success or positive completion
  • 3xx: positive intermediate reply; more information is needed
  • 4xx: temporary failure; retry may succeed later
  • 5xx: permanent failure; do not retry unchanged

SMTP delivery has multiple commands, so a code must be read in context. A server can accept the connection and sender, reject one recipient, accept another recipient, then reject the message body. Log the SMTP command stage as well as the numeric code.

Common successful SMTP responses

220 means a server is ready. It commonly appears as the server greeting after a client opens an SMTP connection.

235 generally indicates successful authentication after an SMTP AUTH command.

250 is the most common successful SMTP response. It may appear after EHLO, MAIL FROM, RCPT TO, or the end of DATA. A final 250 after the message content means the server accepted responsibility for the message at that hop.

251 means the recipient is not local but the server will forward the message. It is successful from the sender's perspective, although it may be uncommon in modern mail flows.

A final SMTP 250 is stronger evidence than an API 202, but still should not be described as guaranteed inbox placement. The recipient system may place the message in spam, route it through a rule, quarantine it, or later generate a non-delivery notification.

Temporary SMTP failures: 4xx codes

A 4xx SMTP response is generally a soft bounce or deferral. The message may succeed if the sender retries later without changing the content.

Important examples include:

CodeTypical interpretationWhat to do
421Service unavailable or connection is closingRetry later; inspect provider or receiver availability
450Mailbox unavailable temporarilyRetry later
451Local processing error or temporary policy/anti-spam issueRetry later; investigate repeated patterns
452Insufficient system storage or temporary resource limitRetry later
454Temporary authentication or TLS-related failure in some contextsRetry after checking configuration and remote guidance

Enhanced status codes provide useful additional detail. They often look like 4.2.0 or 4.7.1 alongside the three-digit code. The first digit still distinguishes temporary (4) from permanent (5) conditions. The middle digit broadly identifies a category, such as address status, mailbox status, mail system status, network/routing, protocol, content, or security/policy.

A response such as 451 4.7.1 may indicate a temporary policy or anti-spam deferral. It does not automatically mean your email content is malicious. However, repeated deferrals to a particular mailbox provider can point to reputation, authentication, volume, or content-quality issues worth investigating.

Permanent SMTP failures: 5xx codes

A 5xx SMTP response means the receiver rejected the attempted action as currently formed. Repeating the same message unchanged will usually fail again.

Common examples:

CodeTypical interpretationRecommended action
550Mailbox unavailable, recipient rejected, or policy rejectionSuppress invalid recipients; inspect enhanced code and text
551Recipient is not local; forwarding information may be suppliedCorrect the recipient if reliable forwarding data is available
552Mailbox full or message exceeds recipient-side limitsAvoid repeated retries; handle according to your policy
553Invalid mailbox name, invalid domain, or unacceptable sender/recipientValidate address and sender identity
554Transaction failed, often for policy, content, or routing reasonsInspect the full SMTP diagnostic and remediate cause
556Mailbox has no mail serviceTreat as an invalid or undeliverable recipient

Never classify a bounce from the three-digit code alone. SMTP servers reuse broad codes for many situations. A 550 might mean 5.1.1 recipient unknown, 5.7.1 policy rejection, or a provider-specific rule. The enhanced status code and diagnostic text usually reveal whether to suppress an address, fix authentication, reduce sending volume, or contact the recipient through another channel.

DNS authentication and delivery-related failures

HTTP response codes tell you whether an API call succeeded. SMTP codes tell you what a receiving mail server did. DNS authentication helps recipient servers decide whether mail claiming to come from your domain should be trusted.

The core records are SPF, DKIM, and DMARC. They do not eliminate all delivery problems, but missing or misconfigured records can contribute to policy rejections, spam placement, and inconsistent delivery.

SPF record syntax

SPF is published as a DNS TXT record at the domain that appears in the SMTP envelope sender, also called the return-path or MAIL FROM domain.

A simplified zone-file example is:

example.com. IN TXT "v=spf1 ip4:198.51.100.24 include:spf.email-provider.example -all"

The same value in many DNS dashboards would be entered as:

Type: TXT
Host: @
Value: v=spf1 ip4:198.51.100.24 include:spf.email-provider.example -all

The include: domain above is deliberately a placeholder. Use only the exact include value your sending provider documents. Do not copy an include from another provider or invent one based on a hostname.

SPF mechanisms are evaluated from left to right. The record should begin with v=spf1, and -all is a hard fail policy for sources not matched earlier. A soft-fail ending, ~all, is sometimes used during transition, but it is not a substitute for identifying every legitimate sender.

SPF has a DNS-lookup limit. Complex chains of include, a, mx, exists, redirect, and ptr mechanisms can exceed the permitted evaluation limit and produce an SPF permanent error. Keep your record understandable and consolidate sending systems where possible.

DKIM record syntax

DKIM uses a cryptographic signature added to each email and a public key published in DNS. The lookup name follows this pattern:

selector._domainkey.example.com

A representative DKIM public-key record has the form:

selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."

In practice, email providers often supply a selector and ask you to publish either a TXT record or CNAME records that delegate the selector to provider-managed DNS. Use the exact record type, host, target, and value supplied for your domain. A DKIM key is not a field you should edit manually unless you operate the signing infrastructure yourself.

Common DKIM mistakes include placing the selector at the root domain, omitting _domainkey, publishing a truncated public key, adding spaces incorrectly, or leaving an old key after rotating signing configuration. Query the exact selector name to verify publication.

DMARC record syntax

DMARC is published at _dmarc under the domain used in the visible From: header. A basic monitoring policy looks like this:

_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"

A stricter policy may look like:

_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; adkim=s; aspf=s"

p=none requests monitoring rather than enforcement. p=quarantine asks receivers to treat failing mail suspiciously, while p=reject requests rejection for mail that fails DMARC evaluation. Receiver behavior is ultimately local policy, so treat DMARC as an important signal rather than a magical delivery guarantee.

DMARC depends on identifier alignment. A message can pass SPF or DKIM in a technical sense but still fail DMARC if the authenticated domain does not align with the visible From: domain. For transactional email, use a From domain you control and authenticate the actual sending configuration used by the provider.

Practical tools for diagnosing email response codes

Troubleshooting is faster when you separate API, DNS, SMTP, and content checks instead of treating “email did not arrive” as one generic problem.

Useful tools include:

  • curl or an API client such as Postman or Insomnia for reproducing the REST request and preserving response headers.
  • Application logs and structured observability tools for correlating request IDs, message IDs, retries, and customer events.
  • dig, nslookup, or host for checking DNS records from the command line.
  • MXToolbox for inspecting MX, SPF, DKIM, DMARC, blacklist, and SMTP-related diagnostics.
  • mail-tester.com for sending a test message and reviewing authentication, content, and configuration signals.
  • A seed mailbox set across major providers for checking real-world placement, headers, and rendering.

For example, query an SPF record with:

dig TXT example.com +short

Query a DMARC record with:

dig TXT _dmarc.example.com +short

Query a DKIM selector with:

dig TXT selector1._domainkey.example.com +short

If you use a DNS provider dashboard, remember that its host field may automatically append the zone name. Entering _dmarc.example.com in a zone already named example.com can accidentally create _dmarc.example.com.example.com. Check the resolved name with dig rather than relying only on the dashboard preview.

A repeatable troubleshooting workflow

When an email API request or delivery attempt fails, use a disciplined sequence. It reduces guesswork and prevents unnecessary retries.

Step 1: classify the first failure

Start with the earliest relevant event:

  • Did the REST API return 2xx, 4xx, 5xx, or time out?
  • Did SMTP submission to your relay succeed?
  • Was the message accepted by the provider but later deferred or bounced?
  • Was it accepted by the recipient server but not visible in the inbox?

Do not skip directly to DNS troubleshooting when your API response was 401, for example. Authentication credentials are the immediate issue.

Step 2: capture the complete diagnostic context

For API failures, preserve:

HTTP status
Response body
Response headers
Provider request ID
Your notification ID
Timestamp in UTC
Endpoint and method
Non-secret payload metadata

For SMTP failures, preserve:

SMTP three-digit code
Enhanced status code
Full diagnostic text
Recipient domain
SMTP stage: connection, MAIL FROM, RCPT TO, or DATA
Message ID and provider event ID
Timestamp in UTC

Redact API keys, SMTP passwords, authorization headers, message bodies containing sensitive information, and personally identifiable data before putting logs into tickets or shared channels.

Step 3: decide retry versus remediation

Use the nature of the error, not optimism, to decide what happens next.

Retry candidates usually include:

  • HTTP 429, 500, 502, 503, and 504
  • SMTP 421, 450, 451, and 452
  • Network timeouts where idempotency or reconciliation prevents duplicates

Fix-before-retry candidates usually include:

  • HTTP 400, 401, 403, 404, 413, 415, and 422
  • SMTP 550, 551, 553, 554, and 556
  • Persistent authentication, alignment, sender-identity, or policy failures

Step 4: look for patterns, not isolated codes

One 451 to one recipient domain is usually not an emergency. A rising percentage of 451 4.7.x responses across a major mailbox provider is a pattern requiring investigation.

Break metrics down by recipient domain, sending domain, message type, IP pool when applicable, template version, region, and time window. This makes it easier to identify whether a change in content, authentication, sending volume, or upstream provider availability coincides with a delivery decline.

Step 5: verify authentication and content quality

Check SPF, DKIM, and DMARC resolution from public DNS. Then inspect a delivered test message's headers for authentication results. A message can have correct DNS records but still be signed with an unexpected domain or use a misaligned From address.

Next review the message itself: subject line, links, tracking domains, HTML-to-text balance, attachment size, recipient consent, and sudden volume changes. Content alone is rarely the entire explanation, but it can combine with weak authentication or low reputation to create mailbox-provider filtering.

Build response-code handling into your email architecture

The strongest email systems do not scatter retry rules across individual application routes. They centralize sending, error classification, queueing, observability, and suppression decisions.

A practical architecture includes:

  1. An application event creates a durable notification job.
  2. A worker submits the job through a REST API or SMTP relay.
  3. The worker stores the provider message ID and immediate HTTP or SMTP result.
  4. Retryable failures return to a delayed queue with bounded attempts and jitter.
  5. Permanent failures go to a reviewable failure state rather than silently disappearing.
  6. Delivery, bounce, complaint, and suppression events update the notification record.
  7. Dashboards monitor acceptance rate, deferral rate, hard-bounce rate, latency, and error-code distribution.

If you need implementation details for a specific sending integration, review the provider's REST API and SMTP setup documentation before hard-coding headers, hostnames, port numbers, or credential formats. Those values vary by platform and can change independently of the underlying HTTP and SMTP standards.

Common mistakes when interpreting email API errors

Several habits make debugging slower and can harm deliverability.

Marking messages as delivered after HTTP 202

A 202 Accepted confirms asynchronous acceptance, not inbox placement. Use a state such as submitted or queued, then update it when downstream data is available.

Retrying every failure

Blind retries turn malformed payloads and invalid recipients into higher costs, noisy logs, and potential duplicate sends. Retry only transient errors and use idempotency controls.

Suppressing an address after every SMTP 5xx

A 550 5.1.1 recipient-unknown response is a strong suppression candidate. A 550 5.7.1 policy rejection may instead indicate an authentication or reputation issue affecting valid addresses. Read the enhanced code and diagnostic text.

Treating DNS records as a one-time setup task

DNS authentication can drift when domains, subdomains, providers, selectors, or sending paths change. Include DNS checks in deployment and migration procedures.

Ignoring response headers and correlation IDs

The status code alone is often insufficient. Rate-limit headers, request IDs, retry guidance, and structured validation fields can reduce a multi-hour investigation to a targeted configuration fix.

Conclusion

REST API response codes tell you whether an email platform accepted, rejected, throttled, or failed to process a request at the API boundary. SMTP response codes tell you how the next mail server handled a delivery attempt. Neither should be interpreted in isolation.

Build your integration around the full lifecycle: validate requests, distinguish permanent from temporary failures, retry with backoff and idempotency, collect complete diagnostics, and use downstream delivery events to determine final outcomes. Combine that operational discipline with correctly published SPF, DKIM, and DMARC records, and response codes become actionable signals rather than opaque production errors.

FAQ

Does HTTP 202 mean an email was delivered?

No. HTTP 202 Accepted generally means the API accepted the message for asynchronous processing. The provider may still queue it, retry it, or receive a later SMTP rejection from the recipient's mail server.

Should I retry a 429 Too Many Requests response?

Yes, but not immediately. Honor Retry-After or other documented rate-limit headers when present. Otherwise use capped exponential backoff with jitter, and make sure repeated submissions cannot create duplicate messages.

What is the difference between an SMTP 450 and 550 error?

450 is a temporary SMTP failure and can often be retried later. 550 is a permanent failure in most contexts, but its enhanced status code and diagnostic text determine whether the cause is an invalid mailbox, policy rejection, authentication problem, or another issue.

Which DNS records should a transactional email sender configure?

At minimum, configure the SPF and DKIM records required by your sending infrastructure, plus a DMARC record for the visible From domain. Verify the records resolve publicly and that SPF or DKIM aligns with the domain in the From header.

Why did the API return success but the recipient never saw the email?

The API may have successfully accepted the request while a later stage failed or filtered the message. Check provider delivery events, SMTP diagnostics, suppression status, DNS authentication, recipient-side rules, and spam or quarantine folders before concluding that the API failed.