Errors & Rate Limits

How failures are shaped, the HTTP status codes you'll see, and exactly how requests are throttled.

Error response shape

Errors the app builds itself use the same envelope as everything else, with success: false:

{ "success": false, "message": "Human-readable description of what went wrong." }

A validation failure (HTTP 422) comes from Laravel’s own validator and has a slightly different, framework-standard shape — field names map to an array of messages:

{
  "message": "The name field is required. (and 1 more error)",
  "errors": {
    "name": ["The name field is required."],
    "wireguard_config": ["The wireguard config field is required when wireguard enabled is true."]
  }
}
Some hand-built 422s use the app’s own {success, message} shape instead of the framework’s {message, errors} shape — check for errors before assuming it’s present, and always read message, which is populated either way.

HTTP status codes

200OKSuccess.
201CreatedA resource was created (monitor, project, integration, etc).
401UnauthorizedMissing, invalid, or expired bearer token.
403ForbiddenToken doesn't have the required ability, plan doesn't allow this action, or the account is suspended.
404Not FoundThe resource doesn't exist, or exists but isn't owned by your account — these are deliberately indistinguishable, so a token can never probe for the existence of another account's data.
422Unprocessable EntityValidation failed, or a plan/business-rule limit was hit (monitor limit, integration limit, etc).
429Too Many RequestsRate limit exceeded — see below.
502Bad GatewayUsed specifically by Server Sources Sync Now when the upstream fetch itself fails.

Rate limits

Limits are enforced per named bucket, returned via standard X-RateLimit-Limit / X-RateLimit-Remaining headers, and a Retry-After header on a 429.

Public endpoints60 / minPlans, probe list, status pages — keyed by IP.
Authenticated API120 / minEverything under Bearer auth — keyed by user id, so one noisy account can't degrade others.
Probe/VPS agent endpoints60 / minHeartbeat and job-polling — keyed by probe/VPS id, not exposed to normal API consumers.