Get started
Errors
Error responses have the shape {statusCode, name, message}. The full list of error names, their HTTP status and how to handle them.
Pidgely uses conventional HTTP status codes: 2xx for success, 4xx for a problem with the request, 5xx for a problem on our side. Errors have this body:
{
"statusCode": 422,
"name": "validation_error",
"message": "to: at least one recipient is required"
}nameis stable and machine-readable: branch on it, never onmessage.messageis meant for humans. For validation errors it starts with the field, for examplesubject: is too longor[3].to: …inside a batch.- Every response carries an
X-Request-Idheader. Send your own (up to 64 characters) to correlate logs, and include it when you contact support.
Error names
| Status | name |
When | What to do |
|---|---|---|---|
| 400 | invalid_idempotency_key |
Idempotency-Key longer than 256 characters |
Use a shorter key |
| 401 | missing_api_key |
No Authorization: Bearer … header |
Send the key |
| 401 | restricted_api_key |
A sending_access key called an endpoint that needs full_access |
Use a full-access key for that call |
| 403 | invalid_api_key |
The key does not exist or was revoked | Check the key and the environment |
| 403 | validation_error |
The request is valid but not allowed: from domain not verified, key restricted to another domain, plan limit on domains reached, domain already added or verified by another account, sending paused or account suspended |
Read message; verify the domain or fix the account state |
| 404 | not_found |
The resource does not exist in your account (also returned for ids that are not valid UUIDs) | Check the id |
| 409 | invalid_idempotent_request |
The Idempotency-Key was used before with a different request |
Use a new key for a new request |
| 409 | not_cancelable, not_reschedulable |
The email is no longer scheduled (already sent or canceled) | Nothing to cancel or update |
| 409 | alias_taken |
Another template already uses this alias | Choose another alias |
| 409 | broadcast_not_draft, broadcast_not_cancelable, broadcast_in_progress |
The broadcast is in a state that does not allow the operation | See Broadcasts |
| 422 | validation_error |
A field is missing or invalid, the JSON is malformed, or the body is too large | Fix the request; message names the field |
| 422 | invalid_attachment |
An attachment has neither content nor path |
Provide one of them |
| 429 | rate_limit_exceeded |
Too many requests per second | Wait Retry-After seconds and retry |
| 429 | daily_quota_exceeded |
The daily quota (UTC day) is used up | Wait for the next UTC day or upgrade |
| 429 | monthly_quota_exceeded |
The monthly quota is used up | Wait for the next month or upgrade |
| 500 | application_error |
Unexpected error on our side | Retry with backoff (with the same Idempotency-Key for sends) |
Retrying
- Retry
429and5xxwith exponential backoff. For429 rate_limit_exceeded, honourRetry-After. - Don't retry other
4xxerrors unchanged: they fail the same way every time. - Make sends safe to retry with an
Idempotency-Key: a network timeout then never turns into a duplicate email. Responses with5xxare not stored, so a retry with the same key runs again.
Native API errors
The native /v1 API uses a different shape, with the field that failed and the request id:
{
"error": {
"code": "validation_error",
"message": "at least one recipient is required",
"field": "to",
"request_id": "8f2c1a7d9e3b4c60"
}
}Codes there are the internal ones (domain_not_verified, tenant_paused, plan_limit, idempotency_key_reused, rate_limited, insufficient_scope, …), with the same statuses: 401 missing key, 403 forbidden, 404 not found, 409 conflict, 422 validation, 429 rate or quota. The main API is the recommended surface for new code.
Request limits
| Limit | Value |
|---|---|
POST /emails and POST /emails/batch body |
50 MiB |
POST/PATCH on templates and broadcasts |
5 MiB |
| Other write endpoints | 1 MiB |
| Built message (headers, bodies and attachments, after encoding) | 40 MiB |
| Request timeout | 60 seconds |
A body over its limit gets 422 validation_error with request body too large.