Matrix: M30
Open in panel — /app/queues
Reference

Error Codes

PostMTA surfaces errors at two layers: the SMTP layer (during message delivery) and the REST API layer (when your application calls the PostMTA API). This page documents every error code you may encounter and how to resolve each class of error.

SMTP Error Codes

Overview

When PostMTA delivers a message to a recipient MTA, the recipient MTA responds with an SMTP reply code. PostMTA classifies these codes as described below. The table covers codes most commonly returned by major inbox providers and relay servers.

SMTP Reply Code Reference

CodeEnhanced CodeMeaningPostMTA Action
211System status / help replyInformation only; continue
214Help messageInformation only; continue
220Service ready (greeting)Expected greeting; continue
221Service closing channelNormal close; retry later
250Requested mail action okay (delivered)Delivered; record event
251User not local; will forwardTreated as delivered
354Start mail inputExpected; send body
4214.3.2Service not available — try again laterSoft bounce; enter retry schedule
4504.1.0–4.1.8Mailbox unavailable (temp: full, disabled, etc.)Soft bounce; enter retry schedule
4514.2.0–4.2.2Requested action aborted: local errorSoft bounce; enter retry schedule
4524.3.1Requested action not taken: insufficient storageSoft bounce; enter retry schedule
455Server cannot accommodate parametersSoft bounce; retry
5005.5.2Syntax error — command not recognisedHard bounce; do not retry
5015.5.2–5.5.4Syntax error in parameters or argumentsHard bounce; do not retry
5025.5.1Command not implementedHard bounce; do not retry
5035.5.1Bad sequence of commandsHard bounce; do not retry
5045.5.3Parameter not implementedHard bounce; do not retry
5505.1.1–5.7.1Requested action not taken: mailbox unavailableHard bounce; classify by sub-code
5515.1.6User not local; try forwarding pathTreated as delivered; forwarding
5525.3.0–5.3.4Requested mail action aborted: exceeded storage allocationSoft bounce; retry (mailbox full)
5535.1.1–5.1.7Requested action not taken: mailbox name not allowedHard bounce; invalid address
5545.0.0–5.7.1Transaction failed (spam, policy, etc.)Hard bounce; classify by sub-code

Enhanced Status Codes

The enhanced status code (e.g., 5.1.1, 4.5.3) provides a machine-readable sub-classification of the SMTP reply code. PostMTA maps these to internal bounce reasons:

Enhanced CodeSub-ClassHuman Readable
5.1.0Other address statusAddress parsing issue
5.1.1Bad destination mailbox addressMailbox does not exist
5.1.2Bad destination system addressDomain does not resolve or MX missing
5.1.6Destination mailbox has movedMailbox moved (forward not set up)
5.1.7Bad destination mailbox address syntaxMalformed address
5.2.1Mailbox disabled, not accepting messagesMailbox disabled/inactive
5.2.2Mailbox fullStorage quota exceeded
5.2.3Message length exceeds administrative limitMessage too large for recipient
5.3.0Other or undefined media errorGeneral media error
5.4.1Invalid destination route (no MX)No MX record for domain
5.5.3Too many recipientsToo many recipients per message
5.7.1Delivery not authorised — message refusedPolicy rejection (spam, content, etc.)

REST API Error Responses

Error Response Schema

All PostMTA REST API errors return a JSON body with a consistent structure:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "You have exceeded the rate limit of 1000 requests per minute.",
    "status": 429,
    "details": {
      "limit": 1000,
      "window": "1m",
      "retry_after_seconds": 42
    },
    "request_id": "req_01HXABC123DEF456"
  }
}

Error Code Reference

HTTP StatusError CodeDescriptionResolution
400BAD_REQUESTMalformed request body or missing required fieldFix request JSON; check field names and types
400VALIDATION_ERRORRequest passed schema validation but failed business-rule validationRead the message field for the specific violation
401AUTHENTICATION_REQUIREDNo API key provided or key is missing from the Authorization headerAdd Authorization: Bearer pmta_l...xxxx header
401INVALID_API_KEYAPI key does not exist or has been revokedGenerate a new API key in the dashboard
403INSUFFICIENT_PERMISSIONSAPI key does not grant the required permission scopeUse a key with the correct scopes or regenerate with more scopes
403WORKSPACE_SUSPENDEDWorkspace has been suspended due to policy violationContact support to resolve the suspension
404NOT_FOUNDThe requested resource does not exist or is not accessible with this keyVerify the resource ID; check that the key has access to the owning workspace
409CONFLICTRequest conflicts with existing resource stateRead the message field; usually requires a different operation order
422UNPROCESSABLE_ENTITYRequest is well-formed but semantically invalidCheck the details field for field-level errors
429RATE_LIMIT_EXCEEDEDToo many requests per minute or per dayImplement exponential backoff; see Retry-After header
429CREDIT_LIMIT_EXCEEDEDWorkspace has insufficient credits to sendTop up credits via dashboard or API
500INTERNAL_ERRORUnexpected server errorRetry with exponential backoff; report to support if persistent
503SERVICE_UNAVAILABLEPostMTA is temporarily unavailable (maintenance or overload)Retry after the interval indicated in the Retry-After header

Common Error Scenarios and Resolution

Connection Timeout

PostMTA will close a connection that receives no data for 30 seconds during the SMTP transaction. If you see timeout errors:

TLS Handshake Failure

If delivery attempts fail with a TLS negotiation error:

SSL alert: certificate verify failed (code: 20)
TLS connection could not be established

Resolution steps:

SPF / DKIM Failure at Recipient

When a recipient server reports SPF or DKIM failure:

Rate Limit Errors (429)

Rate Limit Types

Limit TypeDefaultScope
API requests1,000 req/minPer API key
Messages injectedVaries by planPer workspace
Webhook deliveries200 deliveries/minPer endpoint URL
Suppression imports1 import/hourPer workspace

Handling Rate Limits

When you receive a 429 response, read the Retry-After header (integer seconds) and delay accordingly. Implement exponential backoff for resilience:

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1750272030

Burst vs. Sustained Limits

PostMTA applies both burst (per-second) and sustained (per-minute/per-day) limits. Even if your per-minute average is within limit, a short burst above the burst threshold will return 429. Distribute message injection evenly rather than sending in large batches.

Authentication Errors (401 / 403)

Missing API Key

curl https://api.postmta.com/v1/keys
# Returns: 401 {"error": {"code": "AUTHENTICATION_REQUIRED", ...}}

Always include the Authorization header:

curl https://api.postmta.com/v1/keys \
  -H "Authorization: Bearer pmta_l...xxxx"

Wrong Key Scope

Using a key with insufficient scopes returns 403 INSUFFICIENT_PERMISSIONS. Available scopes:

Key Rotation

API keys can be rotated without downtime by creating a new key, updating your application, and then revoking the old key once traffic has switched over.

Quota Exceeded Errors

Credit Limit Exceeded (429)

{
  "error": {
    "code": "CREDIT_LIMIT_EXCEEDED",
    "message": "Workspace has insufficient credits. Required: 150. Available: 23.",
    "status": 429,
    "details": {
      "required": 150,
      "available": 23,
      "top_up_url": "/app/credits"
    }
  }
}

Top up via the dashboard at /app/credits or via the API:

curl -X POST https://api.postmta.com/v1/credits/topup \
  -H "Authorization: Bearer pmta_l...xxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10000, "payment_method_id": "pmt_01HXABC123DEF456"}'

Sending Domain Quota

Each workspace plan includes a maximum number of verified sending domains. Adding a new domain beyond this limit returns:

{
  "error": {
    "code": "DOMAIN_QUOTA_EXCEEDED",
    "message": "Plan limit of 5 sending domains reached. Upgrade to Growth to add more.",
    "status": 400
  }
}

IP Pool Quota

Each workspace plan includes a maximum number of dedicated IPs. Exceeding this returns:

{
  "error": {
    "code": "IP_POOL_QUOTA_EXCEEDED",
    "message": "Plan limit of 2 dedicated IPs reached.",
    "status": 400
  }
}