Errors & Rate Limiting

Standard error response format, HTTP status codes, and rate limiting policies across all ZapTicket API endpoints.

Error Response Format

All error responses from the ZapTicket API follow a consistent JSON structure. The HTTP status code indicates the error category, and the body provides a human-readable message.

Error Response Shape
{
  "error": "A human-readable description of what went wrong"
}

The error field is always a string. It's designed to be useful for debugging during development — do not display it directly to end users in production.

HTTP Status Codes

The API uses the following status codes consistently across all endpoints:

Success Codes

  • 200 OK — Request succeeded. Response body contains the result.
  • 201 Created — Resource created successfully. Response body contains the new resource.

Client Error Codes

  • 400 Bad Request — Invalid request body, missing required fields, or validation failure.
  • 401 Unauthorized — No token provided, token expired, or token invalid.
  • 403 Forbidden — Token is valid but lacks permission for this action (wrong role, wrong workspace).
  • 404 Not Found — Resource doesn't exist or doesn't belong to the current tenant.
  • 409 Conflict — Action conflicts with current state (duplicate email, already converted, etc.).
  • 429 Too Many Requests — Rate limit exceeded. Back off and retry.

Server Error Codes

  • 500 Internal Server Error — Unexpected server failure. These are logged and monitored.

Error Examples

400 — Validation Error
{
  "error": "Field 'email' is required"
}
401 — Authentication Error
{
  "error": "Token has expired"
}
403 — Authorization Error
{
  "error": "Admin role required to access workspace settings"
}
404 — Not Found
{
  "error": "Conversation not found"
}
409 — Conflict
{
  "error": "A user with this email already exists"
}

Rate Limiting

ZapTicket applies rate limiting at multiple levels to protect the service and ensure fair usage. When you exceed a limit, the API returns 429 Too Many Requests.

Rate Limit Policies

  • Per-IP (general API) — 100 requests per minute
  • Per-site-key (widget endpoints) — 60 requests per minute
  • Auth endpoints (login/register) — 10 requests per 5 minutes per IP

429 Response

When rate limited, the response includes headers to help you determine when to retry:

Rate Limit Response Headers
HTTP/1.1 429 Too Many Requests
Retry-After: 32
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705316832
429 Response Body
{
  "error": "Rate limit exceeded. Try again in 32 seconds."
}
💡The Retry-After header contains the number of seconds to wait before retrying. The X-RateLimit-Reset header is a Unix timestamp for when the window resets.

Best Practices

  • Implement exponential backoff when receiving 429 responses
  • Cache responses where possible (e.g. widget config doesn't change often)
  • Use webhooks or SignalR for real-time updates instead of polling
  • Batch operations where the API supports it
⚠️Repeated rate limit violations (sustained abuse) may result in temporary IP blocks. If you need higher limits for a legitimate use case, contact support.