Error Reference
All API errors return a JSON body with this shape:
{
"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 carryX-RateLimit-LimitandX-RateLimit-Remaining
When rate limited:
{
"error": "RATE_LIMITED",
"message": "Too many requests. Slow down and try again shortly.",
"status_code": 429
}
Handling Errors in 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"]