Error Handling
Learn how to handle errors effectively when working with the Metigan API. This guide covers error types, response formats, and best practices for robust error handling.
Error Response Types
Metigan API uses consistent error response formats to help you handle errors gracefully:
API Error Response
error-response.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Generic API Error Response
interface ApiErrorResponse {
success: false;
error: string;
message?: string;
statusCode?: number;
}
// Example error responses
{
success: false,
error: "invalid_api_key",
message: "The provided API key is invalid",
statusCode: 401
}
{
success: false,
error: "rate_limit_exceeded",
message: "You have exceeded your rate limit. Please try again later.",
statusCode: 429
}Validation Error Response
validation-error.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Validation Error Response
interface ValidationErrorResponse {
success: false;
error: "validation_error";
message: string;
validationErrors?: Array<{
field: string;
message: string;
}>;
}
// Example validation error
{
success: false,
error: "validation_error",
message: "Invalid request parameters",
validationErrors: [
{
field: "recipients",
message: "At least one recipient is required"
},
{
field: "subject",
message: "Subject cannot be empty"
}
]
}Handling Errors
Here's how to properly handle errors in your application:
error-handling.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import Metigan from 'metigan';
import type { EmailApiResponse } from 'metigan';
const metigan = new Metigan({
apiKey: process.env.METIGAN_API_KEY!
});
async function sendEmailWithErrorHandling() {
try {
const result = await metigan.email.sendEmail({
from: 'sender@example.com',
recipients: ['recipient@example.com'],
subject: 'Test Email',
content: '<p>Hello!</p>'
});
// Check if the response indicates success
if ('success' in result && result.success === true) {
console.log('✅ Email sent successfully!');
console.log('Tracking ID:', result.successfulEmails[0]?.trackingId);
return result;
} else {
// Handle API errors
handleApiError(result);
return null;
}
} catch (error) {
// Handle exceptions (network errors, timeouts, etc.)
handleException(error);
return null;
}
}
function handleApiError(error: EmailApiResponse) {
if (!('success' in error) || error.success !== false) {
return;
}
switch (error.error) {
case 'invalid_api_key':
console.error('⌠Authentication failed. Check your API key.');
break;
case 'rate_limit_exceeded':
console.error('⌠Rate limit exceeded. Please wait before retrying.');
// Implement retry logic with exponential backoff
break;
case 'validation_error':
console.error('⌠Validation error:', error.message);
if ('validationErrors' in error && error.validationErrors) {
error.validationErrors.forEach(err => {
console.error(` - ${err.field}: ${err.message}`);
});
}
break;
case 'insufficient_quota':
console.error('⌠Insufficient quota. Please upgrade your plan.');
break;
default:
console.error('⌠API Error:', error.error, error.message);
}
}
function handleException(error: unknown) {
if (error instanceof Error) {
console.error('⌠Exception:', error.message);
// Check for network errors
if (error.message.includes('network') || error.message.includes('fetch')) {
console.error('Network error. Check your internet connection.');
}
// Check for timeout errors
if (error.message.includes('timeout')) {
console.error('Request timeout. The server may be overloaded.');
}
} else {
console.error('⌠Unknown error:', error);
}
}Error Codes Reference
Common error codes you may encounter:
| Error Code | HTTP Status | Description |
|---|---|---|
| invalid_api_key | 401 | The API key is invalid or missing |
| validation_error | 400 | Request validation failed |
| rate_limit_exceeded | 429 | Rate limit exceeded |
| insufficient_quota | 402 | Email quota exceeded |
| server_error | 500 | Internal server error |
| service_unavailable | 503 | Service temporarily unavailable |
Retry Logic
For transient errors like rate limits or network issues, implement retry logic with exponential backoff:
retry-logic.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
async function sendEmailWithRetry(
emailParams: EmailParams,
maxRetries: number = 3,
initialDelay: number = 1000
): Promise<EmailApiResponse | null> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const result = await metigan.email.sendEmail(emailParams);
if ('success' in result && result.success === true) {
return result;
}
// Check if error is retryable
if ('error' in result) {
const retryableErrors = ['rate_limit_exceeded', 'server_error', 'service_unavailable'];
if (retryableErrors.includes(result.error) && attempt < maxRetries - 1) {
const delay = initialDelay * Math.pow(2, attempt);
console.log(`Retrying after ${delay}ms... (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
return result;
} catch (error) {
if (attempt < maxRetries - 1) {
const delay = initialDelay * Math.pow(2, attempt);
console.log(`Retrying after ${delay}ms... (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
return null;
}Important
Always validate and sanitize user input before sending API requests. Never expose API keys in client-side code. Use environment variables to store your API keys securely.