Errors & Rate Limiting

HTTP status codes, error response shapes, and rate limits used across the HookSentry API.

Status codes

StatusMeaning
200 OKRequest succeeded
201 CreatedResource created
202 AcceptedEvent accepted for asynchronous delivery (ingest)
204 No ContentRequest succeeded, no response body (delete, logout, purge)
400 Bad RequestMalformed input — invalid email, missing required field, invalid sort column, unknown enum value
401 UnauthorizedMissing/invalid/expired token, missing API key, or invalid credentials
403 ForbiddenAuthenticated, but the caller's role or tenant doesn't allow this action
404 Not FoundResource doesn't exist, or (for cross-tenant lookups) doesn't exist for this tenant
409 ConflictUnique constraint violated — duplicate name, duplicate email, already-used invite
422 Unprocessable EntityRequest is well-formed but rejected by a business rule (destination inactive, disposable email blocked)
429 Too Many RequestsRate limit exceeded

Error body shape

Most error responses return a plain string body describing the problem, with a Content-Type of text/plain or application/json depending on the endpoint:

"Email 'admin@example.com' is already in use."

A handful of endpoints (disposable-email rejection on tenant creation) return a small JSON object instead:

{
  "error": "disposable_email",
  "message": "Please use a permanent email address."
}

204 No Content and 202/201-with-body responses never include an error body — check the status code first.

Multi-tenancy and 403 vs 404

HookSentry never leaks whether a resource exists outside the caller's tenant. As a rule:

  • Looking up a resource by an ID nested under another resource you already proved you own (e.g. a sender under a destination you fetched) returns 403 Forbidden if it belongs to another tenant.
  • Looking up a top-level ID directly generally returns 404 Not Found first if the record doesn't exist at all, then 403 Forbidden if it exists but belongs to another tenant.

Each endpoint in this reference states exactly which codes it returns.

Rate limiting

EndpointLimit
POST /api/v1/auth/login10 failed attempts per IP or per email / 5 minutes
POST /api/v1/tenants5 requests per IP / hour
POST /api/v1/invites/{token}/register10 requests per IP / hour

Rate-limited responses return 429 Too Many Requests with no Retry-After header — back off and retry after the window described in the endpoint's documentation.

Cloud-only anti-abuse checks:

On HookSentry Cloud, tenant creation additionally blocks disposable email domains (422 Unprocessable Entity) and applies a device-fingerprint/Cloudflare Turnstile check that can also return 429. These checks are inert on self-hosted deployments. See Tenants for the request fields involved.