Sendry Docs

Error Codes

Every Sendry API error code with cause and resolution.

All API errors return JSON with this shape:

{
  "statusCode": 403,
  "code": "insufficient_scope",
  "message": "This API key requires 'full_access' scope or higher. Current scope: 'read_only'.",
  "details": {}
}

Authentication errors (401)

unauthorized

Status: 401

Cause: The Authorization header is missing, malformed, or the API key does not exist.

Fix:

  • Check that you're sending Authorization: Bearer <api_key>
  • Verify the key exists in your dashboard under API Keys
  • Ensure there are no extra spaces or characters in the key

expired_key

Status: 401

Cause: The API key has passed its expiration date.

Fix: Create a new API key in the dashboard and update your environment variable.


Authorization errors (403)

insufficient_scope

Status: 403

Cause: The API key's scope does not have permission to call this endpoint.

full_access > sending_access > read_only

Fix: Create an API key with the required scope. Scope requirements per endpoint:

  • Sending endpoints: sending_access or higher
  • Create/delete endpoints: full_access
  • Read endpoints: read_only or higher

domain_not_verified

Status: 403

Cause: The from address uses a domain that has not been verified with Sendry.

Fix:

  1. Add the domain in the dashboard under Domains
  2. Configure the DNS records (SPF, DKIM, DMARC)
  3. Click Verify and wait for DNS propagation
  4. Alternatively, use a test-mode API key for development

plan_limit_reached

Status: 403

Cause: Your plan's resource limit has been reached (e.g., max domains, API keys, templates, or webhooks).

Fix: Either delete unused resources or upgrade your plan.

Automation runs also use this code once a plan's monthly run quota is used up.


automation_not_available

Status: 403

Cause: Your plan includes no automation runs at all. The Free plan does not include automations, so every trigger, event, schedule, segment join, or manual run is refused before any run is created.

Fix: Upgrade to Pro or higher. Existing automations stay in place and start running again after the upgrade.


Payment errors (402)

payment_required

Status: 402

Cause: Your account is on a paid plan and has exceeded the monthly email quota, but no valid payment method is on file. Overage billing requires a payment method.

Fix: Add a payment method in the dashboard under Billing.


billing_suspended

Status: 402

Cause: Your account has been suspended due to a failed payment that was not resolved.

Fix: Update your payment method in the dashboard under Billing. Once payment succeeds, the account is automatically reinstated.


Rate limit errors (429)

daily_limit_reached

Status: 429

Cause: Your organization has hit the daily email sending limit for your plan.

PlanDaily limit
Free100
Pro+Unlimited

Fix: Wait until midnight UTC for the counter to reset, or upgrade to a paid plan.


monthly_limit_reached

Status: 429

Cause: Your organization has hit the monthly email quota on a plan without overage support (Free plan).

Fix: Upgrade to Pro or Business to enable overage billing, or wait until the next billing period.


overage_limit_reached

Status: 429

Cause: Your organization has hit the overage cap for this billing period. The cap is 3× the monthly quota.

PlanMonthly quotaMax overageTotal max
Pro50,000150,000200,000
Business200,000600,000800,000

Fix: Wait until the next billing period, or contact support to request a temporary limit increase.


rate_limited

Status: 429

Cause: Too many API requests in a short period.

Fix: Implement exponential backoff. The Retry-After response header tells you how many seconds to wait.

try {
  await sendry.emails.send(payload);
} catch (error) {
  if (error instanceof RateLimitError) {
    const delay = (error.retryAfter ?? 1) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
    // Retry
  }
}

See Rate Limits guide for full retry patterns.


Validation errors (422)

validation_error

Status: 422

Cause: The request body failed schema validation.

Response includes details:

{
  "statusCode": 422,
  "code": "validation_error",
  "message": "Request validation failed",
  "details": {
    "errors": [
      {"path": "/subject", "message": "Required"},
      {"path": "/to", "message": "Expected string or array of strings"}
    ]
  }
}

Fix: Check the details.errors array for which fields failed validation and why.


Request errors (413)

payload_too_large

Status: 413

Cause: The request body exceeds the size limit. Limits:

  • HTML body: 5 MB
  • Text body: 1 MB
  • Total email payload: typically 40 MB (including attachments)

Fix: Reduce HTML size or compress attachments. For large files, consider using a link to the file rather than attaching it.


Resource errors (404)

not_found

Status: 404

Cause: The requested resource does not exist or belongs to a different organization.

Fix: Check the resource ID. IDs are organization-scoped — you cannot access another organization's resources.


Server errors (500)

Status: 500

Cause: An internal server error occurred on Sendry's side.

Fix: These are transient. Retry with exponential backoff. Check status.sendry.online for active incidents.


ID formats

Resources use nanoid with type prefixes. If you're passing the wrong ID type, you'll get not_found.

ResourcePrefix example
Emailemail_abc123
Domaindom_abc123
Templatetmpl_abc123
Webhookwh_abc123
API keykey_abc123
Contactct_abc123
Audienceaud_abc123
Segmentseg_abc123
Campaigncp_abc123
Eventevt_abc123
Inboundinb_abc123

On this page