Skip to content

Error Codes

All API errors follow a consistent format:

{
"status": "error",
"error": {
"code": "VALIDATION_ERROR",
"message": "The from_email field is required.",
"details": {
"from_email": ["The from_email field is required."]
}
}
}

Error reference

UNAUTHENTICATED — 401

Your API key is missing, invalid, or has been revoked.

{ "code": "UNAUTHENTICATED", "message": "Invalid or missing credential." }

Fix: Check your Authorization: Bearer YOUR_API_KEY header. Ensure the credential is active and not revoked.


FORBIDDEN — 403

Your credential doesn’t have the required permission for this action.

{ "code": "FORBIDDEN", "message": "This credential does not have the 'send' permission." }

Fix: Create a credential with the required permission, or add the permission to the existing one.


NOT_FOUND — 404

The requested resource doesn’t exist.

{ "code": "NOT_FOUND", "message": "Message not found." }

CONFLICT — 409

The resource already exists.

{ "code": "CONFLICT", "message": "This domain is already registered." }

VALIDATION_ERROR — 422

The request body failed validation. The details field contains per-field error messages.

{
"code": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"details": {
"from_email": ["The from_email field is required."],
"subject": ["The subject may not be greater than 998 characters."]
}
}

RATE_LIMITED — 429

You’ve exceeded your organization’s send rate limit.

{ "code": "RATE_LIMITED", "message": "Rate limit exceeded. Retry after 60 seconds." }

The response includes a Retry-After header with the number of seconds to wait.

Fix: Implement exponential backoff and respect the Retry-After header.


ATTACHMENT_TOO_LARGE — 422

A single attachment exceeds your plan’s size limit.

{
"code": "ATTACHMENT_TOO_LARGE",
"message": "Attachment \"report.pdf\" exceeds the maximum size of 10 MB."
}

MESSAGE_TOO_LARGE — 422

The total message size (body + all attachments) exceeds the platform limit.

{
"code": "MESSAGE_TOO_LARGE",
"message": "Total message size exceeds the maximum of 25 MB."
}

INTERNAL_ERROR — 500

An unexpected server error occurred. These are rare and usually transient.

Fix: Retry with exponential backoff. If the error persists, contact support.


Error handling examples

const response = await fetch('https://api.emitlo.com/api/v1/messages', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ /* ... */ }),
});
if (!response.ok) {
const { error } = await response.json();
switch (error.code) {
case 'RATE_LIMITED':
const retryAfter = response.headers.get('Retry-After');
await sleep(parseInt(retryAfter) * 1000);
// retry...
break;
case 'VALIDATION_ERROR':
console.error('Validation failed:', error.details);
break;
default:
throw new Error(`API error: ${error.message}`);
}
}