Skip to main content

Error Response Format

When an error occurs, the API returns a JSON response with an error object:
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email address format",
    "details": {
      "field": "to",
      "value": "invalid-email"
    }
  },
  "meta": {
    "timestamp": "2024-01-15T10:30:00.000Z",
    "requestId": "req_abc123",
    "path": "/api/v1/emails"
  }
}

HTTP Status Codes

StatusMeaning
200Success
201Created
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Insufficient permissions
404Not Found - Resource doesn’t exist
409Conflict - Resource already exists
422Unprocessable Entity - Validation failed
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Error Codes

Authentication Errors

CodeHTTP StatusDescription
UNAUTHORIZED401Missing or invalid API key
KEY_REVOKED401API key has been revoked
KEY_EXPIRED401API key has expired
FORBIDDEN403API key doesn’t have required permissions

Validation Errors

CodeHTTP StatusDescription
VALIDATION_ERROR400Request body validation failed
INVALID_EMAIL400Email address format is invalid
MISSING_REQUIRED_FIELD400Required field not provided
INVALID_PARAMETER400Query parameter is invalid

Domain Errors

CodeHTTP StatusDescription
DNS_VERIFICATION_FAILED400Domain DNS records not verified
DOMAIN_NOT_VERIFIED400Domain verification incomplete
FROM_DOMAIN_MISMATCH400From address must use verified domain
DOMAIN_NOT_FOUND404Domain not found in account

Email Sending Errors

CodeHTTP StatusDescription
SENDING_DISABLED403Email sending is disabled for domain
RECIPIENT_SUPPRESSED400Recipient is on suppression list
ATTACHMENT_NOT_FOUND400Referenced attachment doesn’t exist
ATTACHMENT_TOO_LARGE400Attachment exceeds size limit
TEMPLATE_NOT_FOUND404Template ID doesn’t exist
TEMPLATE_RENDER_ERROR400Template variable substitution failed

Contact Errors

CodeHTTP StatusDescription
CONTACT_NOT_FOUND404Contact doesn’t exist
CONTACT_ALREADY_EXISTS409Contact with email already exists in list
LIST_NOT_FOUND404Contact list doesn’t exist
INVALID_CUSTOM_FIELD400Custom field name or value invalid

Verification Errors

CodeHTTP StatusDescription
VERIFICATION_FAILED400Email verification could not complete
BATCH_TOO_LARGE400Batch verification exceeds limit
INSUFFICIENT_CREDITS402Not enough verification credits

Rate Limiting

CodeHTTP StatusDescription
RATE_LIMIT_EXCEEDED429Too many requests
When rate limited, check response headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2024-01-01T12:01:00Z
Retry-After: 60

Handling Errors in SDKs

import { MailBreeze, MailBreezeError } from "mailbreeze";

const mailbreeze = new MailBreeze({ apiKey: "sk_live_xxx" });

try {
  await mailbreeze.emails.send({
    from: "hello@yourdomain.com",
    to: "invalid-email",
    subject: "Test",
  });
} catch (error) {
  if (error instanceof MailBreezeError) {
    console.log(error.code);    // "INVALID_EMAIL"
    console.log(error.message); // "Invalid email address format"
    console.log(error.status);  // 400
  }
}
from mailbreeze import MailBreeze, MailBreezeError

client = MailBreeze(api_key="sk_live_xxx")

try:
    await client.emails.send(
        from_="hello@yourdomain.com",
        to="invalid-email",
        subject="Test",
    )
except MailBreezeError as e:
    print(e.code)     # "INVALID_EMAIL"
    print(e.message)  # "Invalid email address format"
    print(e.status)   # 400
client := mailbreeze.NewClient("sk_live_xxx")

email, err := client.Emails.Send(ctx, &mailbreeze.SendEmailParams{
    From:    "hello@yourdomain.com",
    To:      []string{"invalid-email"},
    Subject: "Test",
})

if err != nil {
    var mbErr *mailbreeze.Error
    if errors.As(err, &mbErr) {
        fmt.Println(mbErr.Code)    // "INVALID_EMAIL"
        fmt.Println(mbErr.Message) // "Invalid email address format"
        fmt.Println(mbErr.Status)  // 400
    }
}
use MailBreeze\MailBreeze;
use MailBreeze\Exceptions\MailBreezeException;

$mailbreeze = new MailBreeze('sk_live_xxx');

try {
    $mailbreeze->emails->send([
        'from' => 'hello@yourdomain.com',
        'to' => 'invalid-email',
        'subject' => 'Test',
    ]);
} catch (MailBreezeException $e) {
    echo $e->getCode();    // "INVALID_EMAIL"
    echo $e->getMessage(); // "Invalid email address format"
    echo $e->getStatus();  // 400
}
use mailbreeze::{Client, Error};

let client = Client::new("sk_live_xxx");

match client.emails().send(SendEmailParams {
    from: "hello@yourdomain.com".to_string(),
    to: vec!["invalid-email".to_string()],
    subject: Some("Test".to_string()),
    ..Default::default()
}).await {
    Ok(email) => println!("Sent: {}", email.id),
    Err(Error::Api { code, message, status }) => {
        println!("Code: {}", code);    // "INVALID_EMAIL"
        println!("Message: {}", message); // "Invalid email address format"
        println!("Status: {}", status);   // 400
    }
    Err(e) => println!("Other error: {}", e),
}

Retry Strategy

For transient errors (5xx status codes and rate limits), implement exponential backoff:
async function sendWithRetry(params, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await mailbreeze.emails.send(params);
    } catch (error) {
      if (error.status >= 500 || error.status === 429) {
        const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error; // Don't retry client errors
    }
  }
  throw new Error("Max retries exceeded");
}
The official SDKs include automatic retry logic with exponential backoff for transient errors.