DocumentationError codes
Error codes
HTTP error format and common causes.
Error responses follow a uniform JSON format:
{
"statusCode": 403,
"message": "Missing required API key scope: email:send",
"path": "/emails/send",
"timestamp": "2026-06-30T12:00:00.000Z"
}
HTTP codes
| Code | Meaning |
|---|---|
| 400 | Validation failed (required field, invalid email) |
| 401 | Invalid or expired JWT or API key |
| 403 | Insufficient scope, role, or unauthorized tenant |
| 404 | Resource not found |
| 409 | Conflict (duplicate, invalid state) |
| 413 | Message too large (raw MIME > 10 MB) |
| 422 | Business rule (e.g. suppressed recipient) |
| 429 | Global rate limit or monthly quota exceeded |
Application error codes
Every error response also carries a machine-readable code alongside the HTTP status. Common codes:
| Code | Meaning |
|---|---|
VALIDATION_ERROR | A field failed validation (400) |
HTML_BODY_REQUIRED | No html/htmlBody and no template given (400) |
BATCH_LIMIT_EXCEEDED | More than 100 recipients in one call (400) |
HAS_EMAIL_HISTORY | Can't delete a template version or project that has send history — logs are append-only (400) |
TEMPLATE_NOT_FOUND | Unknown template slug or id (404) |
TEMPLATE_NOT_PUBLISHED | The template has no published version to send |
EMAIL_TOO_LARGE | The built message exceeds the 10 MB limit (413) |
QUOTA_EXCEEDED | Monthly email quota exceeded (429) |
Quota exceeded (429)
When you exceed 110% of the monthly limit:
{
"statusCode": 429,
"message": "Monthly email quota exceeded (115%). Upgrade your plan to continue sending.",
"quota": {
"limit": 100,
"used": 115,
"percentage": 115
}
}
Rate limit
In production: ~300 requests/minute per IP or JWT user (configurable). Headers:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1719763200
Public auth routes (/auth/login, /auth/register) have a stricter limit: 15 requests / 15 minutes.
SDK
The mailingcore-js package throws MailingCoreError with .status and .detail for client-side handling.