Errors
All errors follow a consistent JSON shape:
{
"status": 403,
"message": "You have reached your seat limit.",
"error": "SEAT_LIMIT_REACHED"
}
HTTP status codes
| Status | Meaning |
|---|---|
200 | OK |
201 | Created |
400 | Bad Request — missing or invalid fields |
401 | Unauthorized — missing or expired auth token |
403 | Forbidden — insufficient role or entitlement |
404 | Not Found |
409 | Conflict — duplicate resource |
429 | Too Many Requests — rate limit exceeded |
500 | Internal Server Error |
Machine-readable error codes
| Code | Status | Description |
|---|---|---|
SEAT_LIMIT_REACHED | 403 | Organization has hit its user seat cap |
FORM_LIMIT_REACHED | 403 | Organization has hit its form cap |
ROOM_LIMIT_REACHED | 403 | Organization has hit its room cap |
ALREADY_MEMBER | 409 | Email is already a member of the org |
INVITATION_PENDING | 409 | An invite for this email already exists |
INVALID_TOKEN | 401 | Auth token is missing, malformed, or expired |
INSUFFICIENT_ROLE | 403 | Action requires a higher role |
ENTITLEMENT_REQUIRED | 403 | Feature not available on current plan |
NOT_FOUND | 404 | Resource does not exist |
RATE_LIMITED | 429 | Too many requests from this IP |
Rate limits
| Endpoint | Limit |
|---|---|
POST /api/forms/public/:slug/submit | 10 requests / 15 min per IP |
POST /api/widget/submit | 10 requests / 15 min per IP |
GET /api/public/invitation/:token | 20 requests / 15 min per IP |
POST /api/public/accept-invitation | 10 requests / 15 min per IP |
POST /api/public/waitlist | 5 requests / hour per IP |