Skip to content

Errors

All error responses from the MailerDash API follow a unified format inspired by Stripe. This makes programmatic handling straightforward: you can tell what type of error occurred (and how to react) without parsing the text message.


{
"error": {
"type": "validation_error",
"code": "domain_unauthorized",
"message": "The from domain is not authorized for this key.",
"param": "from.email"
}
}
FieldTypeDescription
typestringError category (see table below). Determines the retry strategy.
codestringMachine-readable specific code.
messagestringHuman-readable description in English.
paramstring (optional)Field or parameter that caused the error, when applicable.
detailsarray (optional)List of sub-errors for multiple-validation cases.

The type field is categorical and lets you decide on a strategy without reading code or message:

typeHTTPWhen it occurs
validation_error400 / 422The request has invalid or missing fields. Do not retry without fixing.
authentication_error401Token missing, malformed, or invalid. Check the API key.
authorization_error403Authenticated but lacking permissions. The key does not have the required scope.
not_found_error404The requested resource does not exist.
rate_limit_error429Rate limit or monthly quota exceeded. Retry with backoff.
conflict_error409Conflict with the current state (e.g. resource already exists).
payload_too_large_error413The body exceeds the allowed size (e.g. attachments too large).
idempotency_error409The idempotency key was already used with a different payload.
smtp_error5xxError delivering the email via SMTP.
api_error5xxInternal server error. Retry with exponential backoff.

codetypeDescription
domain_unauthorizedauthorization_errorThe from domain is not authorized for this API key.
email_not_verifiedauthorization_errorThe account has not verified its email; sends are blocked until it does.
free_requires_verified_domainauthorization_errorThe free plan requires a verified domain to send.
monthly_quota_exceededrate_limit_errorThe plan’s monthly send quota has been reached.
rate_limit_exceededrate_limit_errorThe per-minute request limit (rate_per_min) has been exceeded.
codetypeDescription
max_domains_exceededvalidation_errorYou have reached the domain limit allowed by your plan.
domain_takenconflict_errorThe domain is already registered under another account on the platform.
reserved_domainvalidation_errorThe domain is reserved and cannot be registered by clients.
cname_delegation_disabledvalidation_errorCNAME delegation is not enabled for this account.
codetypeDescription
max_api_keys_exceededvalidation_errorYou have reached the API key limit for your plan.
key_not_linkedauthorization_errorThe user’s JWT has no linked API key for the requested resource.
already_revokedconflict_errorThe API key has already been revoked.
wrong_passwordauthentication_errorThe provided password is incorrect (operations requiring confirmation).
codetypeDescription
billing_unavailableapi_errorThe billing system is not available at this time.
no_billing_accountvalidation_errorThe account does not have an active Stripe subscription.
no_active_subscriptionvalidation_errorThere is no active subscription for this operation.
overage_not_offeredvalidation_errorThe current plan does not offer overage sends.
package_not_selectablevalidation_errorThe requested plan is not available for selection.
already_subscribedconflict_errorYou already have this plan active.
codetypeDescription
not_foundnot_found_errorThe resource does not exist.
unauthorizedauthentication_errorToken missing or invalid.
forbiddenauthorization_errorNo permission for this operation.
payload_too_largepayload_too_large_errorBody or attachments too large.
internal_errorapi_errorInternal server error.
bad_requestvalidation_errorMalformed request.

When a single request has several invalid fields, the response includes the details array:

{
"error": {
"type": "validation_error",
"code": "invalid",
"message": "Request validation failed",
"details": [
{ "code": "required", "message": "'subject' is required", "param": "subject" },
{ "code": "invalid_format", "message": "'from.email' must be a valid email", "param": "from.email" }
]
}
}

const res = await fetch('https://api.mailerdash.com/v1/mail/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MAILERDASH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ from: { email: 'noreply@mi-app.com' }, to: [...], subject: '...', text: '...' }),
});
if (!res.ok) {
const { error } = await res.json();
if (error.type === 'rate_limit_error') {
// Retry after a backoff — the Retry-After header may indicate when
console.warn('Rate limit alcanzado, reintentando en 60s...', error.code);
} else if (error.type === 'validation_error') {
// Do not retry — fix the request
console.error('Error de validación:', error.code, error.param);
} else if (error.type === 'authentication_error') {
// Check the API key
console.error('API key inválida o sin permisos');
} else {
console.error('Error inesperado:', error);
}
}

See the full endpoint reference at /reference/transactional/ and /reference/bulk/.