Errors
Learn how to handle errors from the Veil Mail API.
Error Response Format
All error responses follow a consistent format:
{
"error": {
"code": "validation_error",
"message": "The 'to' field is required",
"details": {
"field": "to",
"reason": "required"
}
}
}HTTP Status Codes
| Status | Description |
|---|---|
200 OK | Request succeeded |
201 Created | Resource created successfully |
204 No Content | Request succeeded, no content returned |
400 Bad Request | Invalid request parameters |
401 Unauthorized | Missing or invalid API key |
403 Forbidden | Access denied to resource |
404 Not Found | Resource does not exist |
422 Unprocessable Entity | Validation error or PII detected |
429 Too Many Requests | Rate limit exceeded |
500 Server Error | Internal server error |
Error Codes
| Code | Description |
|---|---|
authentication_error | Invalid or missing API key |
validation_error | Invalid request parameters |
not_found | Resource not found |
forbidden | Access denied |
pii_detected | PII found in email content |
rate_limit | Too many requests |
domain_not_verified | Sending domain not verified |
quota_exceeded | Monthly email quota exceeded |
server_error | Internal server error |
SDK Error Handling
The SDK provides typed error classes for different error scenarios:
error-handling.ts
import {
VeilMail,
VeilMailError,
AuthenticationError,
ValidationError,
NotFoundError,
PiiDetectedError,
RateLimitError,
ServerError,
} from '@veilmail/sdk';
const client = new VeilMail('veil_live_xxxxx');
try {
await client.emails.send({
from: 'hello@example.com',
to: 'user@example.com',
subject: 'Hello',
html: '<p>Content with potential PII</p>',
});
} catch (error) {
if (error instanceof AuthenticationError) {
// Invalid API key
console.log('Check your API key');
} else if (error instanceof ValidationError) {
// Invalid request parameters
console.log('Validation error:', error.message);
console.log('Details:', error.details);
} else if (error instanceof NotFoundError) {
// Resource not found
console.log('Resource not found');
} else if (error instanceof PiiDetectedError) {
// PII detected in email content
console.log('PII types found:', error.piiTypes);
} else if (error instanceof RateLimitError) {
// Rate limit exceeded
console.log('Rate limited, retry after:', error.retryAfter, 'seconds');
} else if (error instanceof ServerError) {
// Server error
console.log('Server error, try again later');
} else if (error instanceof VeilMailError) {
// Other API errors
console.log('Error code:', error.code);
console.log('Message:', error.message);
}
}Best Practices
Handle rate limits gracefully
Implement exponential backoff when you receive rate limit errors.
retry-logic.ts
async function sendWithRetry(params, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await client.emails.send(params);
} catch (error) {
if (error instanceof RateLimitError && i < maxRetries - 1) {
const delay = error.retryAfter ?? Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}Log errors for debugging
Include the error code and message in your logs.
logging.ts
} catch (error) {
if (error instanceof VeilMailError) {
logger.error('VeilMail API error', {
code: error.code,
message: error.message,
status: error.status,
details: error.details,
});
}
}Validate before sending
Validate email addresses and content on your end before making API calls to reduce validation errors.