Documentation menu

Docs/Error reference

Error Reference

All API errors return a JSON body with this shape:

json
{
  "error": "PLAN_LIMIT_REACHED",
  "message": "Monthly pause limit of 50 reached. Upgrade to Starter for 500 pauses/month.",
  "status_code": 402
}

Complete Error Code Table#

HTTP Status Error Code Description
400 INVALID_CHANNEL channel must be sms, email, or slack
400 INVALID_OPTIONS options must contain 2–5 strings
400 INVALID_CHOICE Response choice not in the pause's options list
401 INVALID_API_KEY Authorization header missing, malformed, or key not found
401 INVALID_CREDENTIALS Wrong email or password on login
402 PLAN_LIMIT_REACHED Monthly pause limit exhausted — upgrade plan
403 CHANNEL_NOT_ALLOWED Channel not available on current plan (e.g. email on Free)
404 PAUSE_NOT_FOUND pause_id does not exist or belongs to another developer
404 WEBHOOK_NOT_FOUND webhook_id does not exist or belongs to another developer
409 ALREADY_RESPONDED Pause already has a human response — cannot cancel
409 ALREADY_CANCELLED Pause is already cancelled
409 EMAIL_TAKEN Email is already registered on another account
410 TOKEN_EXPIRED Response token has passed its expiry timestamp
410 TOKEN_USED Response token was already used (single-use)
422 VALIDATION_ERROR Request body fails schema validation (field-level errors in detail)
429 RATE_LIMITED Sliding-window rate limit exceeded — includes Retry-After header
503 (Billing errors) Paddle/billing not configured on this instance

Rate Limiting#

Every endpoint is rate limited with a sliding window (Redis sorted set). The limits are layered:

  • Authenticated requests: 120 requests per 60 seconds per API key, with a 300/min per-IP backstop
  • Unauthenticated requests: 100 requests per 60 seconds per IP
  • Auth endpoints (login, register, password reset): 20 requests per 60 seconds per IP
  • Response: HTTP 429 with Retry-After: <seconds> header; successful responses carry X-RateLimit-Limit and X-RateLimit-Remaining

When rate limited:

json
{
  "error": "RATE_LIMITED",
  "message": "Too many requests. Slow down and try again shortly.",
  "status_code": 429
}

Handling Errors in Python#

python
import requests

resp = requests.post(
    "https://api.pausepoint.dev/v1/pause",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"recipient": "+15550100", "channel": "sms", "message": "Approve?", "options": ["Yes", "No"]}
)

if resp.status_code == 402:
    error = resp.json()
    print(f"Plan limit hit: {error['message']}")
elif resp.status_code == 429:
    retry_after = resp.headers.get("Retry-After", "60")
    print(f"Rate limited. Retry in {retry_after}s")
elif not resp.ok:
    error = resp.json()
    print(f"Error {resp.status_code}: {error.get('error')} — {error.get('message')}")
else:
    pause_id = resp.json()["pause_id"]