Skip to main content
The handling pattern depends on the language you use:
  • curl — inspect the HTTP status returned by curl -w "%{http_code}" and parse the response body with jq.
  • JavaScript SDK — SDK methods return { data, error } (or { success, error }). The error object has message and statusCode fields; branch on error?.statusCode.
  • Python SDKmailchannels.Emails.send (and other resource methods) raise typed exceptions that subclass mailchannels.exceptions.MailChannelsError. Catch the specific subclass to react to each status.
  • PHP SDK — SDK methods throw typed exceptions that subclass MailChannels\Exception\MailChannelsException. Catch the specific subclass to react to each status; use getStatusCode() and getMessage() on the caught exception.
The examples below show how each endpoint’s errors might be handled together in production code: surface transient 5xx failures so the caller (or a retry layer) can react, and fail fast on 4xx so the underlying request can be corrected.

Send API errors

StatusMeaningWhat to do
400 Bad RequestThe JSON body is malformed, a required field is missing, an email address is invalid, or non-transactional sending rules are not met.Compare the payload with the Email Structure guide and the API reference.
403 ForbiddenThe API key is missing, invalid, scoped incorrectly, not attached to the expected account, or the sending domain is not authorized.Confirm the X-Api-Key header, check the key scope, and verify Domain Lockdown.
413 Payload Too LargeThe encoded message, headers, and attachments exceed 30 MB.Reduce attachment size or count. See Attachments.
500 Internal Server ErrorA transient MailChannels service error.Retry with exponential backoff. Check status.mailchannels.net if the error persists.
502 Bad GatewayA transient infrastructure or network error.Retry with backoff and alert if repeated attempts fail.
status=$(curl -s -o /tmp/mc-resp.json -w "%{http_code}" \
  -X POST https://api.mailchannels.net/tx/v1/send \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $MAILCHANNELS_API_KEY" \
  -d @payload.json)

case "$status" in
  2*) ;;
  400|403|413)
    echo "Send rejected ($status):"
    jq -r '.errors // .message // empty' /tmp/mc-resp.json
    exit 1
    ;;
  500|502)
    echo "Send failed transiently ($status). Retry later."
    exit 1
    ;;
  *)
    echo "Unexpected status $status"
    exit 1
    ;;
esac

Suppression API errors

StatusMeaningWhat to do
400 Bad RequestA recipient, source, date filter, or request body is invalid.Validate recipient formatting and use a supported source: api, unsubscribe_link, list_unsubscribe, hard_bounce, or spam_complaint.
409 ConflictOne or more suppression entries already exist.Treat existing entries as success during idempotent imports, or query the suppression list before creating entries.
413 Payload Too LargeThe create request exceeds the 1,000-entry limit.Split imports into batches of 1,000 entries or fewer.
500 Internal Server ErrorA transient MailChannels service error.Retry with exponential backoff. Check status.mailchannels.net if the error persists.
503 Temporarily UnavailableSuppression service maintenance or temporary unavailability.Retry later with backoff.
# Assumes entries.json is already chunked to <= 1,000 entries per request.
status=$(curl -s -o /tmp/mc-resp.json -w "%{http_code}" \
  -X POST https://api.mailchannels.net/tx/v1/suppressions \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $MAILCHANNELS_API_KEY" \
  -d @entries.json)

case "$status" in
  2*) ;;
  409) ;;  # Entries already exist — idempotent success.
  400|413)
    echo "Suppression import rejected ($status):"
    jq -r '.message // empty' /tmp/mc-resp.json
    exit 1
    ;;
  500|503)
    echo "Suppression import failed transiently ($status). Retry later."
    exit 1
    ;;
  *)
    echo "Unexpected status $status"
    exit 1
    ;;
esac

Webhook API errors

StatusMeaningWhat to do
400 Bad RequestA webhook URL, batch ID, filter, or validation request is invalid.Check the URL, filter values, and batch ID before retrying.
404 Not FoundThe requested webhook batch or signing key does not exist. Applies to POST /webhook-batch/{batch_id}/resend, GET /webhook/public-key, and POST /webhook/validate.Confirm the resource ID exists before retrying.
409 ConflictA webhook endpoint is already enrolled for this customer (POST /webhook only).Treat as success for idempotent enrollment, or query existing webhooks with GET /webhook before enrolling.
500 Internal Server ErrorA transient MailChannels service error.Retry and check status.mailchannels.net if failures continue.
status=$(curl -s -o /tmp/mc-resp.json -w "%{http_code}" \
  -X POST "https://api.mailchannels.net/tx/v1/webhook?endpoint=$WEBHOOK_URL" \
  -H "X-Api-Key: $MAILCHANNELS_API_KEY")

case "$status" in
  2*) ;;
  409) ;;  # Endpoint already enrolled — idempotent success.
  400|404)
    echo "Webhook request rejected ($status):"
    jq -r '.message // empty' /tmp/mc-resp.json
    exit 1
    ;;
  500)
    echo "Webhook request failed transiently. Retry later."
    exit 1
    ;;
  *)
    echo "Unexpected status $status"
    exit 1
    ;;
esac