Docs/Error Handling

Error Handling

FWD uses standard HTTP status codes and returns consistent JSON error responses. This guide covers error formats, common codes, and troubleshooting steps.

Error Response Format

All error responses follow this format:

Error response
{
  "error": "Human-readable error description"
}

Successful responses follow this format (for dashboard API routes):

Success response
{
  "success": true,
  "data": { ... },
  "message": "Operation completed successfully"
}

HTTP Status Codes

CodeMeaningCommon Causes
200SuccessRequest processed successfully
201CreatedResource created (API key, template, webhook)
400Bad RequestMissing fields, invalid email format, suppressed recipient, invalid domain format
401UnauthorizedMissing, invalid, or revoked API key
403ForbiddenPlan limit exceeded (domains, templates)
404Not FoundTemplate, webhook, or email not found
429Rate LimitedMonthly email limit reached
500Server ErrorInternal failure — retry with exponential backoff

Common Errors & Solutions

Missing API Key

401 Unauthorized
{ "error": "Missing API key. Include x-api-key header." }

Solution: Add the x-api-key header with your API key to every request.

Invalid API Key

401 Unauthorized
{ "error": "Invalid or revoked API key" }

Solution: Check that your API key is correct and has not been revoked. Generate a new key from the dashboard if needed.

Missing Required Fields

400 Bad Request
{ "error": "Missing fields: to, subject, and html or text required" }

Solution: Ensure your request body includes to, subject, and either html or text (or use templateId).

Suppressed Recipient

400 Bad Request
{ "error": "Email to user@example.com blocked: recipient is on suppression list (bounce)" }

Solution: The recipient's address previously bounced and was added to the suppression list. Remove it manually or contact support.

Unverified Domain

400 Bad Request
{ "error": "Domain 'yourdomain.com' is not verified. Add and verify it in your dashboard first." }

Solution: Verify your domain in the Domains section before using it as a custom sender.

Best Practices

  • Always check the HTTP status code before parsing the response body
  • Implement exponential backoff for 500 errors (retry after 1s, 2s, 4s…)
  • Monitor X-RateLimit-Remaining headers to avoid hitting limits
  • Log error responses for debugging — the error field contains actionable details
  • Use webhooks to track delivery status rather than polling