API Reference

API: Errors & Rate Limits

Beacon uses conventional HTTP status codes to indicate success or failure. This page covers every status code the API returns, the error response format, rate limiting headers, and best practices for resilient integrations.

HTTP status codes

Code Name Description
200 OK The request succeeded. Returned for GET and PATCH requests.
201 Created A new resource was created successfully. Returned for POST requests.
401 Unauthorized The request is missing an API token or the token is invalid/revoked.
403 Forbidden The token is valid but does not have permission for this action. This can happen if you try to access a resource in a different workspace.
404 Not Found The requested resource does not exist. Check the ID or slug in the URL.
422 Unprocessable Entity The request body contains invalid data. The response includes field-level error messages.
429 Too Many Requests Rate limit exceeded. Wait and retry after the period indicated in the Retry-After header.
500 Internal Server Error Something went wrong on our end. If this persists, contact support.

Error response format

All error responses (4xx and 5xx) follow a consistent JSON structure:

{
  "message": "The given data was invalid.",
  "errors": {
    "title": [
      "The title field is required."
    ],
    "impact": [
      "The selected impact is invalid."
    ]
  }
}
Field Type Description
message string A human-readable summary of the error. Always present.
errors object An object mapping field names to arrays of error messages. Present on 422 responses. May be absent on other error codes.

Error examples

401 Unauthorized (missing or invalid token):

{
  "message": "Unauthenticated."
}

404 Not Found:

{
  "message": "No query results for model [StatusPage]."
}

422 Validation error:

{
  "message": "The given data was invalid.",
  "errors": {
    "status": [
      "The selected status is invalid. Valid values: operational, degraded, degraded_performance, partial_outage, major_outage, maintenance, unknown."
    ]
  }
}

Rate limiting

Beacon enforces rate limits to ensure platform stability. Limits are applied at two scopes:

Scope Limit Window
Per workspace (by token) 120 requests 1 minute
Per IP address 60 requests 1 minute

Rate limit headers

Every API response includes headers that indicate your current rate limit status:

Header Description
X-RateLimit-Limit The maximum number of requests allowed in the current window.
X-RateLimit-Remaining The number of requests remaining before the limit is reached.
Retry-After The number of seconds to wait before retrying. Only present on 429 responses.

Example response headers:

HTTP/1.1 200 OK
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
Content-Type: application/json

Handling 429 Too Many Requests

When you exceed the rate limit, Beacon returns a 429 response:

HTTP/1.1 429 Too Many Requests
Retry-After: 23
Content-Type: application/json

{
  "message": "Too Many Requests"
}

Your code should:

  • Read the Retry-After header to find out how long to wait.
  • Pause for that many seconds before retrying the request.
  • Do not retry in a tight loop -- this will extend the rate limit window.

Best practices

Exponential backoff

For transient errors (429, 500, 502, 503, 504), implement exponential backoff with jitter:

// Pseudocode: exponential backoff
max_retries = 5
base_delay  = 1  // seconds

for attempt in 1..max_retries:
    response = make_request()

    if response.status == 429:
        wait = response.headers["Retry-After"]
    elif response.status >= 500:
        wait = base_delay * (2 ** attempt) + random(0, 1)
    else:
        break

    sleep(wait)

Idempotency

PATCH requests are naturally idempotent -- sending the same update twice produces the same result. POST requests (creating incidents and updates) are not idempotent by default.

To avoid creating duplicate resources when retrying after network errors:

  • Check whether the resource was actually created before retrying a failed POST (the server may have processed it even if you did not receive the response).
  • Use unique titles or external identifiers to detect duplicates.
  • For incident updates, check the incident timeline to see if your update was already posted.

General error handling

  • Always check the HTTP status code before parsing the response body.
  • Log the full error response (message and errors object) for debugging.
  • Do not retry 401, 403, or 422 errors -- these indicate a problem with the request itself, not a transient failure.
  • Monitor your X-RateLimit-Remaining header to proactively throttle requests before hitting the limit.