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

StatusDescription
200 OKRequest succeeded
201 CreatedResource created successfully
204 No ContentRequest succeeded, no content returned
400 Bad RequestInvalid request parameters
401 UnauthorizedMissing or invalid API key
403 ForbiddenAccess denied to resource
404 Not FoundResource does not exist
422 Unprocessable EntityValidation error or PII detected
429 Too Many RequestsRate limit exceeded
500 Server ErrorInternal server error

Error Codes

CodeDescription
authentication_errorInvalid or missing API key
validation_errorInvalid request parameters
not_foundResource not found
forbiddenAccess denied
pii_detectedPII found in email content
rate_limitToo many requests
domain_not_verifiedSending domain not verified
quota_exceededMonthly email quota exceeded
server_errorInternal 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.