API Errors

Every StatusRadar API endpoint returns JSON. On failure you get a non-2xx HTTP status plus a JSON error body. This page documents the error body shape, the status codes the API uses, how validation errors are reported, and how rate limiting behaves.

Error response shape

API errors return a consistent JSON envelope. The HTTP status code carries the category; the body carries a human-readable message and, for validation failures, a per-field map.

{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "name": "Name is required",
    "type": "Invalid monitor type"
  }
}
Field Type Description
success boolean Always false on an error response.
message string Human-readable summary of what went wrong.
errors object Per-field validation messages. Empty ({}) when the error is not field-specific.

A successful response uses the mirror envelope, so you can branch on success:

{
  "success": true,
  "message": "Success",
  "data": { }
}

Always check the success flag (or the HTTP status) rather than assuming a 2xx body. The payload of a successful call lives under data.

Status codes

The API uses standard HTTP status codes.

Status Meaning When it happens
400 Bad Request Malformed or missing JSON body, unparseable input.
401 Unauthorized Missing, malformed, revoked, or invalid token. See Authentication.
403 Forbidden Authenticated, but not allowed: insufficient team role, plan quota reached, or a resource that belongs to another team/probe.
404 Not Found The resource does not exist, or it is not visible to your team.
422 Unprocessable Entity The request was well-formed but failed validation. The errors object lists the offending fields.
429 Too Many Requests Rate limit exceeded. Back off and retry.
500 Internal Server Error An unexpected server-side failure. Safe to retry with backoff.

400 Bad Request

Returned when the request body is missing or is not valid JSON, or when a required field group is entirely absent.

{
  "success": false,
  "message": "Invalid JSON input",
  "errors": {}
}

Make sure POST/PUT requests send Content-Type: application/json and a valid JSON body.

401 Unauthorized

Returned when the credential is missing or invalid. Note that auth schemes differ by API surface β€” User and Probe APIs use Authorization: Bearer <token>, OTLP uses X-App-Token, and RUM uses the api_key query parameter. Sending the wrong scheme to a surface returns 401.

{
  "success": false,
  "message": "Unauthorized",
  "errors": {}
}

See Authentication for the full scheme-per-surface table and common causes.

403 Forbidden

You are authenticated but not permitted. Common cases:

  • Your team role lacks the required capability (for example, a viewer trying to create a monitor β€” see Teams).
  • A plan quota is reached (for example, the server limit).
  • The resource belongs to a different team or probe.
{
  "success": false,
  "message": "Server limit reached. Please upgrade your plan to add more servers.",
  "errors": {}
}

404 Not Found

The resource does not exist, or it exists but is not owned by your current team. For privacy, resources outside your team are reported as not found rather than forbidden.

{
  "success": false,
  "message": "Monitor not found",
  "errors": {}
}

500 Internal Server Error

An unexpected server-side error. The message may include a brief reason. These are safe to retry after a short delay; if they persist, contact support.

{
  "success": false,
  "message": "Failed to create monitor",
  "errors": {}
}

Validation errors (422)

When a request is syntactically valid JSON but fails field validation, the API returns 422 with message: "Validation failed" and an errors object mapping each invalid field to a message. Multiple fields can fail at once.

curl -X POST https://api.statusradar.dev/v1/monitors \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"","type":"smtp"}'
{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "name": "Name is required",
    "type": "Invalid monitor type",
    "target": "Target is required"
  }
}

The errors keys are the request field names, so you can map them directly back to your form or payload. For example, when creating a monitor:

  • name β€” required.
  • type β€” must be one of http, https, ping, tcp, ssl, dns.
  • target β€” required, and for http/https it must pass URL validation (a bad URL returns 422 with errors.target describing the problem).

See Monitors for the full field list per monitor type.

Rate limiting (429)

API requests are rate limited per identifier (token plus client IP). The default API limit is 60 requests per 60-second window. Exceeding it returns HTTP 429:

{
  "success": false,
  "message": "Too many requests. Please try again later."
}

Limits are tracked in a fixed 60-second window. Other actions carry their own dedicated limits (for example, login is 5 per 15 minutes and registration is 3 per hour).

Handling 429

  • Back off exponentially. On a 429, wait before retrying and increase the delay on repeated failures (for example 1s, 2s, 4s).
  • Cache responses. Avoid polling the same read endpoint in a tight loop; cache results client-side where possible.
  • Batch where you can. Prefer list endpoints over many single-resource calls.
# Example: simple exponential backoff on 429 / 5xx
attempt=0
until response=$(curl -fsS -w '%{http_code}' -o /tmp/body \
  -H "Authorization: Bearer $STATUSRADAR_TOKEN" \
  https://api.statusradar.dev/v1/monitors) || [ "$attempt" -ge 5 ]; do
  attempt=$((attempt + 1))
  sleep $((2 ** attempt))
done

Error handling checklist

  • Branch on the success flag (or the HTTP status), never on the presence of data.
  • Read errors for field-level detail on 422 responses and surface it to the user.
  • Treat 401/403 as non-retryable: fix the credential or permission, do not loop.
  • Treat 429 and 5xx as retryable: back off and retry with a capped number of attempts.
  • Send Content-Type: application/json on all POST/PUT requests to avoid 400.

Next Steps