Reference
Errors
How the Emailit API reports errors. Response body formats, HTTP status codes and what they mean, and fixes for the error messages you'll see most.
The Emailit API uses HTTP status codes to tell you whether a request worked. Codes in the 2xx range mean success, 4xx codes mean something about the request needs to change, and 5xx codes mean something went wrong on our side. This page describes the error bodies, every status code the API returns and how to fix the most common errors.
Error response formats
Every error body is a JSON object with an error field. The exact shape depends on where the request failed. Write your error handling to read error, then message when it’s present, then any extra fields the endpoint documents.
Request errors
Authentication failures, permission errors, malformed JSON and other errors raised before an endpoint runs use the standard HTTP error format:
{
"statusCode": 401,
"error": "Unauthorized",
"message": "API key required"
}| Field | Description |
|---|---|
statusCode |
The HTTP status code. |
error |
The HTTP reason phrase, such as Unauthorized or Forbidden. |
message |
What went wrong, in plain language. |
Validation errors
When a query parameter or body field has the wrong type, is missing, or is out of range, the API rejects the request with 400 before it runs and lists each problem in details:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Validation error",
"details": [
{
"instancePath": "/limit",
"schemaPath": "#/properties/limit/maximum",
"keyword": "maximum",
"params": { "comparison": "<=", "limit": 100 },
"message": "must be <= 100"
}
]
}instancePath points to the field (/limit, /to, /attachments/0/filename), and message describes the rule it broke. On a few endpoints, such as Send an email, these errors return only {"error": "Bad Request"}.
Resource errors
Errors raised by an endpoint, such as a missing object or a duplicate name, return error and often message:
{
"error": "Email not found",
"message": "Email with ID 'em_4KYof1ZzXndZE2VPi0DgULiekG8' not found in your workspace"
}Some errors add fields that help you recover:
| Field | Returned with | Contains |
|---|---|---|
existing |
409 when you create a duplicate domain, API key, audience, contact or subscriber |
The object that already exists, so you can use it instead. |
usage |
422 when a plan limit is reached |
used, limit and, for audiences, plan. |
required_plan |
403 with error: "plan_required" |
The lowest plan that includes the feature, such as pro. |
code |
Some 403 and 422 errors |
A stable machine-readable code, such as unverified_workspace_recipient or events_offset_too_large. |
missing |
404 from Bulk update contacts |
The contact IDs that weren’t found. |
Send validation errors
Send an email and Forward an email check the whole message at once and return every problem in validation_errors:
{
"error": "Validation failed",
"validation_errors": [
"Missing required field: subject",
"Invalid to email address at index 1: ada@example"
]
}Field errors
Templates, campaigns and automations return validation problems grouped by field:
{
"message": "Validation failed",
"errors": {
"alias": ["Alias must contain only lowercase letters (a-z), numbers (0-9), underscores (_), and hyphens (-)"]
}
}Rate limit errors
429 responses from the sending endpoints include the limit you hit and how long to wait. See Rate limits.
{
"error": "Rate limit exceeded",
"message": "Too many requests. Maximum 2 messages per second allowed.",
"limit": 2,
"current": 2,
"retry_after": 1
}HTTP status codes
| Code | Meaning | Typical causes in the Emailit API |
|---|---|---|
200 |
OK | The request worked. Sends, updates, deletes and reads return 200. |
201 |
Created | A domain, API key, audience, subscriber, contact, template, webhook or other object was created. |
202 |
Accepted | A DMARC report upload was accepted for processing. |
204 |
No Content | A form was deleted. The response has no body. |
400 |
Bad Request | Invalid JSON, a missing required field, a value of the wrong type or out of range, an invalid Idempotency-Key, or no fields to update. |
401 |
Unauthorized | The API key is missing, invalid, deleted or regenerated, or an OAuth token expired. See Authentication. |
402 |
Payment Required | The workspace doesn’t have enough credits for the send, retry or verification. |
403 |
Forbidden | The key’s scope doesn’t allow the endpoint, a domain-restricted key sent from another domain, the workspace is suspended or not yet verified, the sending domain is paused, or the feature needs a higher plan. |
404 |
Not Found | The object doesn’t exist in this workspace, or a template alias has no published version. |
409 |
Conflict | An object with the same name or email already exists, or a request with the same Idempotency-Key is still running. |
413 |
Payload Too Large | The composed email is larger than 40 MB, or a DMARC report upload is larger than 10 MB. |
422 |
Unprocessable Entity | The request is valid but can’t be done right now: the from domain isn’t verified, an attachment couldn’t be fetched, the email’s status doesn’t allow cancel or retry, its content was already purged, or a plan limit was reached. |
429 |
Too Many Requests | The workspace hit its per-second or daily sending limit, or the hourly forward limit. |
500 |
Internal Server Error | Something failed on our side. Retry with backoff, and contact support if it persists. |
503 |
Service Unavailable | A temporary outage of a dependency, such as the idempotency store or the authentication database. Retry with backoff. |
Common errors and how to fix them
| Status | error |
Cause | Fix |
|---|---|---|---|
400 |
Validation failed |
A send is missing from, to, subject or content, or has an invalid address or attachment. |
Fix each item listed in validation_errors. |
400 |
Invalid JSON in request body (in message) |
The body isn’t valid JSON. | Check quoting and trailing commas, and send Content-Type: application/json. |
400 |
Invalid Idempotency-Key |
The key is longer than 256 characters or has characters other than letters, digits, - and _. |
Use a UUID or a similar safe value. |
402 |
Insufficient credits |
Credits ran out. Each recipient costs one credit. | Buy credits or turn on auto-refill. |
403 |
Workspace not verified |
The workspace is in sandbox mode and a recipient isn’t a workspace member. | Request production access. |
403 |
Domain paused |
Sending from this domain is paused because of its sending health. | Fix the bounce or complaint problem, then contact support. |
403 |
Domain not authorized |
The API key is restricted to another sending domain. | Send from the key’s domain or use another key. |
403 |
plan_required |
The feature, such as DMARC reports or webhook filters, isn’t on your plan. | Upgrade to the plan in required_plan. |
403 |
mjml_alpha |
The request creates or changes MJML, or calls an MJML endpoint. MJML is in alpha and open to the Emailit team only. | Use another editor or content type. See MJML editors and API. |
404 |
Template not found |
The template ID doesn’t exist, or the alias has no published version. | Publish a version of the template. |
409 |
… already exists |
You created an object with a name or email that’s already taken. | Use the object in existing, or pick another name. |
409 |
Idempotency key in progress |
Another request with the same key hasn’t finished. | Wait a moment and retry with the same key. |
413 |
Message too large |
The email, including attachments, is over 40 MB. | Send large files as links instead of attachments. |
422 |
Domain not verified |
The from address isn’t on a verified sending domain of this workspace. |
Verify the domain or change from. |
422 |
Attachment error |
An attachment url couldn’t be fetched within 30 seconds, isn’t reachable, or is larger than 25 MB. |
Check the URL is public and the file is small enough, or send content instead. |
422 |
Cannot cancel email, Cannot retry email, Cannot update email |
The email’s status doesn’t allow the action, it’s within 3 minutes of its scheduled time, or its content was purged. | Check the email’s status. See each endpoint for the rules. |
422 |
Page is too deep |
You paged past offset 2,500 of List events. | Narrow the results with type or created_at filters. |
429 |
Rate limit exceeded, Daily limit exceeded |
The workspace hit its sending limit. | Wait retry_after seconds. See Rate limits. |
Retry safely
- Retry
429,500and503responses after a delay. Use theretry-afterheader when it’s present, and exponential backoff otherwise. Rate limits has example code. - Don’t retry other
4xxerrors unchanged. They fail the same way until you fix the request. - When you retry a send after a timeout or a
5xxerror, reuse the sameIdempotency-Keyso the email isn’t sent twice.