Error Handling
Understand error responses and handle them gracefully.
Error Handling
Every error response from send0 follows a consistent structure. Every error includes a machine-readable code, a human-readable message, a status code, and a docs_url linking to more information.
Error response shape
{
"error": {
"code": "sender_not_verified",
"message": "The domain 'gmail.com' is not verified.",
"docs_url": "https://docs.send0.dev/errors/sender_not_verified",
"status": 422
}
}| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable explanation |
status | number | HTTP status code |
docs_url | string | Link to documentation for this error |
Validation errors
When a request fails validation, the response includes an errors array with details about each invalid field.
{
"error": {
"code": "validation_error",
"message": "Request validation failed.",
"status": 422,
"errors": [
{
"param": "to",
"code": "too_many_recipients",
"message": "Maximum 50 recipients allowed."
},
{
"param": "subject",
"code": "required",
"message": "Subject is required."
}
]
}
}Handling errors in the SDK
The SDK provides typed error classes so you can handle different failure modes precisely.
import { Send0, Send0APIError, Send0RateLimitError } from 'send0';
const send0 = new Send0('sk_live_...');
try {
await send0.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Hello',
html: '<p>Hello</p>',
});
} catch (err) {
if (err instanceof Send0RateLimitError) {
console.log(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof Send0APIError) {
console.log(`API error: ${err.code} — ${err.message}`);
}
}Error classes
The SDK exports the following error classes, all extending from the base Send0Error:
| Class | When it's thrown |
|---|---|
Send0Error | Base class for all SDK errors |
Send0APIError | API returned a non-2xx response |
Send0RateLimitError | API returned 429 (includes retryAfter) |
Send0NetworkError | Request failed due to a network issue |
Send0ConfigError | Invalid SDK configuration (e.g., missing API key) |
Send0WebhookVerificationError | Webhook signature verification failed |
Common error codes
| Code | Status | Description |
|---|---|---|
missing_api_key | 401 | No Authorization header provided |
invalid_api_key | 401 | API key not found or revoked |
validation_error | 422 | Request body failed validation |
sender_not_verified | 422 | The from domain is not verified |
too_many_recipients | 422 | More than 50 recipients in a single send |
suppressed_recipient | 422 | Recipient address is on the suppression list |
rate_limit_exceeded | 429 | Too many requests — check Retry-After header |
insufficient_credits | 402 | Monthly sending limit reached |
template_not_found | 404 | Template ID does not exist |
invalid_scheduled_at | 422 | Scheduled time is in the past |
Best practices
- Always check the
codefield for programmatic handling — never parse themessagestring. - Handle rate limits gracefully by respecting the
Retry-Afterheader or using the SDK's built-in retry logic. - Log the full error response in production for debugging. The
docs_urlfield links directly to relevant documentation. - Use test mode (
sk_test_keys) during development to trigger and handle errors without affecting production data.