Rate Limits & Errors

Understand SentinMail API rate limits, error codes, and best practices for handling failures

Rate Limits

SentinMail enforces rate limits to protect the platform and ensure fair usage. Limits are applied per API key or per IP address (for public endpoints).

ScopeLimitApplies To
Authentication5 requests/minLogin, register, token refresh
Public subscribe3 requests/minPublic subscribe endpoint (per IP)
Email tracking60 requests/minOpen/click tracking pixels
General APIBased on planAll authenticated endpoints

When You're Rate Limited

The API returns 429 Too Many Requests:

Code
json
1{
2 "detail": "Request was throttled. Expected available in 45 seconds."
3}

How to handle it:

  1. Read the Retry-After header (if present) for the wait time
  2. Implement exponential backoff in your client
  3. Queue requests and process them at a sustainable rate

Example: Retry with Backoff

Code
javascript
1async function apiCall(url, options, maxRetries = 3) {
2 for (let attempt = 0; attempt < maxRetries; attempt++) {
3 const res = await fetch(url, options);
4 
5 if (res.status !== 429) return res;
6 
7 const retryAfter = res.headers.get('Retry-After');
8 const waitMs = retryAfter
9 ? parseInt(retryAfter) * 1000
10 : Math.pow(2, attempt) * 1000;
11 
12 await new Promise((resolve) => setTimeout(resolve, waitMs));
13 }
14 
15 throw new Error('Max retries exceeded');
16}

Error Codes

Standard HTTP Status Codes

StatusMeaningCommon Cause
200SuccessRequest completed
201CreatedResource created successfully
400Bad RequestInvalid request body, missing required fields
401UnauthorizedMissing or invalid API key
403ForbiddenPlan limit reached, insufficient permissions
404Not FoundResource doesn't exist or doesn't belong to your company
429Too Many RequestsRate limit exceeded
500Server ErrorSomething went wrong on our end

Error Response Format

All errors return a JSON body with a detail field:

Code
json
1{
2 "detail": "Human-readable error message."
3}

Some validation errors include field-level detail:

Code
json
1{
2 "email": ["This field is required."],
3 "template": ["Invalid pk \"bad-uuid\" - object does not exist."]
4}

Common Errors and Solutions

401 — Invalid API Key

Code
json
1{"detail": "Invalid API key."}

Check:

  • Is the X-API-Key header present?
  • Is the key copied correctly (no extra whitespace)?
  • Has the key expired?
  • Was the key deleted from the dashboard?

403 — Plan Limit Reached

Code
json
1{"detail": "Subscriber limit reached for your plan."}
Code
json
1{"detail": "Email quota exceeded for your plan."}

Solutions:

  • Check your current usage: GET /api/companies/<id>/plan/
  • Upgrade your subscription plan
  • Wait for your quota to reset (monthly)
  • Clean up unused subscribers

404 — Resource Not Found

Code
json
1{"detail": "Not found."}

Check:

  • Does the resource ID belong to the company associated with your API key?
  • Was the resource deleted?
  • Is the UUID formatted correctly?

400 — Validation Error

Code
json
1{"email": ["Enter a valid email address."]}

Check:

  • Are all required fields present?
  • Are UUIDs valid and correctly formatted?
  • Is the Content-Type: application/json header set?

Best Practices

  1. Always check status codes — don't assume success; check res.ok or res.status
  2. Implement retry logic — use exponential backoff for 429 and 5xx errors
  3. Don't retry 4xx errors — these are client errors; fix the request before retrying
  4. Log API responses — store error responses for debugging
  5. Monitor your usage — check GET /api/companies/<id>/plan/ periodically to avoid hitting limits unexpectedly
  6. Use idempotent operations — subscribing the same email twice is safe (returns success both times)

Pagination

All list endpoints return paginated responses (20 items per page):

Code
json
1{
2 "count": 2500,
3 "next": "https://api.sentinmail.app/api/emails/subscribers/?page=2",
4 "previous": null,
5 "results": [...]
6}

Iterate through pages by following the next URL until it's null.

rate-limitserrorsapitroubleshooting