Skip to content

Public REST API

Checkstack exposes its plugins’ procedures through two HTTP surfaces. Pick whichever shape suits your client - the REST surface is friendlier for ad-hoc curl/Python calls, the native oRPC surface supports batching.

Authentication for both surfaces uses an Application API key. Create the key first via the UI (see API keys) and pass it on every request.

The same contracts are exposed through two HTTP shapes:

MountShapeBody / params
/api/{pluginId}/oRPC native wire protocol - POST a {procedure: input} envelope. Supports batching multiple procedures per request.{"getSystems": {}}
/rest/{pluginId}/{procedure}REST / OpenAPI - one procedure per request. Method depends on the procedure (see table below).varies

The machine-readable schema for the REST surface is published at /api/openapi.json (paths listed there are under /rest/...). The method for each endpoint comes directly from the contract definition - always trust the spec over this page.

Use the Authorization header with the Bearer scheme:

Authorization: Bearer ck_{applicationId}_{secret}
Section titled “Calling REST endpoints (recommended for ad-hoc clients)”

The HTTP method follows REST conventions, derived from the procedure name and operationType in the contract:

Procedure shapeHTTP methodInput goes to
Query (read)GETURL query params, bracket-notation encoded
create* / add* mutationPOSTJSON body
update* mutationPATCHJSON body
delete* / remove* mutationDELETEJSON body
Bulk query (getBulk*, or any query taking a large array)POSTJSON body

Query (GET, bracket-notation params):

Terminal window
curl "https://your-checkstack-instance.com/rest/healthcheck/getSystemHealthStatus?systemId=YOUR_SYSTEM_ID" \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET"

Nested object inputs and arrays use bracket notation:

Terminal window
# Input: { filter: { status: "active" }, ids: ["a", "b"] }
curl "https://your-checkstack-instance.com/rest/foo/getItems?filter[status]=active&ids[0]=a&ids[1]=b" \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET"

Create (POST):

Terminal window
curl -X POST https://your-checkstack-instance.com/rest/incident/createIncident \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"title": "Database down", "severity": "high"}'

Update (PATCH):

Terminal window
curl -X PATCH https://your-checkstack-instance.com/rest/incident/updateIncident \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"id": "inc_123", "status": "resolved"}'

Delete (DELETE):

Terminal window
curl -X DELETE https://your-checkstack-instance.com/rest/incident/deleteIncident \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"id": "inc_123"}'

Bulk query (POST despite being read-only):

Terminal window
curl -X POST https://your-checkstack-instance.com/rest/healthcheck/getBulkSystemHealthStatus \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"systemIds": ["sys_1", "sys_2", "sys_3"]}'

All oRPC endpoints are available at /api/{pluginId}/ and accept JSON POST requests.

Terminal window
curl -X POST https://your-checkstack-instance.com/api/catalog/ \
-H "Authorization: Bearer ck_YOUR_APP_ID_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"getSystems": {}}'
const API_BASE = "https://your-checkstack-instance.com";
const API_KEY = "ck_YOUR_APP_ID_YOUR_SECRET";
// Call a single procedure
async function callRpc<T>(
pluginId: string,
procedure: string,
input?: unknown
): Promise<T> {
const response = await fetch(`${API_BASE}/api/${pluginId}/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ [procedure]: input ?? {} }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || `HTTP ${response.status}`);
}
const result = await response.json();
return result[procedure];
}
// Usage examples
const systems = await callRpc("catalog", "getSystems");
const health = await callRpc("healthcheck", "getHealthChecks");

oRPC supports batching multiple procedure calls in a single request:

const response = await fetch(`${API_BASE}/api/catalog/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
getSystems: {},
getGroups: {},
}),
});
const { getSystems, getGroups } = await response.json();
import requests
API_BASE = "https://your-checkstack-instance.com"
API_KEY = "ck_YOUR_APP_ID_YOUR_SECRET"
def call_rpc(plugin_id: str, procedure: str, input_data=None):
response = requests.post(
f"{API_BASE}/api/{plugin_id}/",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={procedure: input_data or {}},
)
response.raise_for_status()
return response.json()[procedure]
# Usage
systems = call_rpc("catalog", "getSystems")

Each plugin exposes its procedures at both /api/{pluginId}/ (oRPC wire format) and /rest/{pluginId}/{procedure} (REST). Common plugins include:

PluginoRPC mountREST mountExample procedures
catalog/api/catalog//rest/catalog/...getSystems, getGroups
healthcheck/api/healthcheck//rest/healthcheck/...getHealthChecks, getHistory
maintenance/api/maintenance//rest/maintenance/...getWindows, scheduleWindow
incident/api/incident//rest/incident/...getIncidents, createIncident

oRPC returns structured error responses:

{
"code": "FORBIDDEN",
"message": "Missing access: catalog.catalog.read"
}

Common error codes:

  • UNAUTHORIZED: Missing or invalid API key
  • FORBIDDEN: Valid key but missing required access
  • NOT_FOUND: Procedure or resource not found
  • BAD_REQUEST: Invalid input parameters

Applications use the same RBAC system as users. To call an endpoint, the application must have a role with the required access rule. Access rule format:

{pluginId}.{accessRuleId}

Example: To call catalog.getSystems, the application needs a role with catalog.catalog.read access rule.