API Error Catalog

HTTP status codes and typical JSON bodies returned by the Notify send API.

Notify’s send endpoint is POST https://notify.cx/api/email/send. Errors return JSON with success: false, a human-readable error, and a machine-readable code when applicable.

Authenticate with the x-api-key header. Required body fields: to, subject, message.


Success (200)

{
  "success": true,
  "data": {
    "messageId": "01000194b1dd1c04-b51e7343-6808-4a68-b2af-845feae57f8b-000000"
  }
}

400 Bad Request

Invalid or incomplete payload, or a suppressed recipient.

Missing / invalid fields

{
  "success": false,
  "error": "Invalid request data: subject: Subject is required, to: Recipient email is required",
  "code": "INVALID_REQUEST_DATA"
}

Invalid from format

{
  "success": false,
  "error": "Invalid sender address format. Use an email or Name <email@domain.com>",
  "code": "INVALID_REQUEST_DATA"
}

Recipient on suppression list

{
  "success": false,
  "error": "Recipient user@example.com is on suppression list",
  "code": "RECIPIENT_SUPPRESSED",
  "data": {
    "suppressionDetails": {}
  }
}

What to do: Fix the JSON body. Check to / subject / message. For suppressions, remove the address from your list or suppression list handling before retrying.


401 Unauthorized

Missing or invalid API key.

Missing header

{
  "success": false,
  "error": "API key must be provided in x-api-key header",
  "code": "API_KEY_MISSING"
}

Invalid key

{
  "success": false,
  "error": "Invalid API key",
  "code": "INVALID_API_KEY"
}

What to do: Send x-api-key (not Authorization: Bearer). Copy a fresh key from Credentials.


403 Forbidden

Account or domain restrictions.

Unverified sender domain

{
  "success": false,
  "error": "Domain acme.com is not verified for your account. Please verify the domain before using it as a sender.",
  "code": "DOMAIN_NOT_VERIFIED"
}

Suspended account

{
  "success": false,
  "error": "This account has been suspended due to suspicious activity. Please contact support for more information.",
  "code": "ACCOUNT_SUSPENDED"
}

What to do: Verify the domain before using a custom from. For suspensions, contact hello@notify.cx.


429 Too Many Requests

Plan or trial rate limits.

Monthly quota

{
  "success": false,
  "error": "Monthly email limit exceeded",
  "code": "MONTHLY_LIMIT_EXCEEDED"
}

Trial hourly limit

{
  "success": false,
  "error": "Hourly email limit exceeded for trial accounts",
  "code": "HOURLY_LIMIT_EXCEEDED"
}

What to do: Back off and retry after the window resets. Check usage. Upgrade at pricing if you consistently hit the monthly cap (Free 1,000 / Pro 10,000 / Scale 100,000).


500 Internal Server Error

Unexpected server-side failure.

{
  "success": false,
  "error": "An unexpected error occurred",
  "code": "INTERNAL_SERVER_ERROR"
}

Other 500 variants may include messages like "Error retrieving user data" or "Error logging email" with the same INTERNAL_SERVER_ERROR code pattern.

What to do: Retry with exponential backoff. If it persists, check status.notify.cx and email hello@notify.cx with the request time and messageId if you have one.


Handling errors in code

const response = await fetch('https://notify.cx/api/email/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.NOTIFY_API_KEY!
  },
  body: JSON.stringify({
    to: 'user@example.com',
    subject: 'Hello',
    message: 'Hi there'
  })
});

const data = await response.json();

if (!response.ok) {
  console.error(response.status, data.code, data.error);
  // Branch on data.code: INVALID_API_KEY, MONTHLY_LIMIT_EXCEEDED, etc.
}

Related