← Blog

Read service uptime status with the StillOnline REST API

Dashboards are fine for humans. Scripts, CI gates, internal bots, and runbooks need a stable HTTP contract: is the API green, when was the last probe, is there an open incident?

StillOnline REST API v1 exposes two read paths for liveness / uptime:

  1. PublicGET /v1/public/status/{slug} — no API key, customer-safe JSON.
  2. PrivateGET /v1/projects/{id}/checks — owner view with last_status, last_probed_at, pause state.

Base URL: https://api.stillonline.tech/v1. Interactive reference: /en/docs/api. For Cursor/Windsurf agents, see MCP setup.

Quick answer

StillOnline REST API v1 lets scripts read uptime without opening the dashboard: public GET /v1/public/status/{slug} needs no key; private GET /v1/projects/{id}/checks needs Bearer sk_live_… (Pro/Ultimate). Responses reflect stored probe results—StillOnline workers HTTP-get your health URL on a schedule. Owner down/recovery alerts stay in the UI (Telegram, Slack), not via these GET endpoints.

Choose the right endpoint

StillOnline splits customer-safe reads from owner reads on purpose: public JSON needs no secret; private lists need your API key and a Pro plan. Start from the row that matches who will consume the response.

NeedEndpointAuthBest for
Status page / widget / public botGET /public/status/{slug}NoneStakeholders, status embeds, open monitoring
Your checks + probe timestampsGET /projects/{id}/checksBearer sk_live_…Deploy scripts, on-call tools, private dashboards
API itself is upGET /healthNoneSmoke test of StillOnline API

Private endpoints need Pro ($9/mo) or Ultimate and a key from API settings. On Free there is no API key—use the web UI, or the public JSON when the status page is public.

Public status (no API key)

Read the same JSON that powers your hosted status page.

curl -sS "https://api.stillonline.tech/v1/public/status/my-saas"

Replace my-saas with your status page slug or project id (cuid from the dashboard URL).

Example response (200):

{
  "slug": "my-saas",
  "status": "operational",
  "updated_at": "2026-05-29T10:00:00.000Z",
  "components": [
    {
      "name": "API",
      "url": "https://api.example.com/health",
      "status": "operational",
      "uptime_7d": 99.9,
      "ssl_valid_until": null
    }
  ],
  "active_incident": null
}

Status values: operational, degraded, down, unknown (overall and per component).

Limits: 60 requests/minute per IP → 429 with Retry-After. Response cached ~60s (Cache-Control).

404 if the slug does not exist or visibility is private.

Use this in:

  • A release checklist curl before announcing deploy done
  • A simple uptime badge script
  • Any integration that must not hold secrets

Need a health URL first? 5-minute health check quickstart.

Private: list checks with last probe result

For your projects, authenticate with the API key:

curl -sS \
  -H "Authorization: Bearer sk_live_..." \
  "https://api.stillonline.tech/v1/projects/PROJECT_ID/checks"

Find PROJECT_ID via:

curl -sS \
  -H "Authorization: Bearer sk_live_..." \
  "https://api.stillonline.tech/v1/projects"

Example check object:

{
  "id": "clx…",
  "project_id": "clx…",
  "name": "API",
  "url": "https://api.example.com/health",
  "method": "GET",
  "interval_seconds": 300,
  "enabled": true,
  "last_status": "OPERATIONAL",
  "last_probed_at": "2026-05-29T09:57:10.362Z"
}

last_status reflects the latest external HTTP probe StillOnline ran against your URL — not your app’s inline /health handler unless that is what you monitor.

Common values: OPERATIONAL, DOWN, DEGRADED, UNKNOWN (internal enum; public JSON uses lowercase).

Paused checks

PATCH /checks/{id} with {"enabled": false} pauses one URL. After pause:

  • Probes stop
  • last_status may still show OPERATIONAL — last result before pause, not live health
  • Dashboard shows a Paused badge

Resume with {"enabled": true}. Project-wide pause uses dashboard Play/Pause (all checks).

Rate limits and errors

Scripts should backoff on 429 using Retry-After. The buckets below are per IP (public) or per API key (private)—they are independent, so a heavy public poll does not consume your private write quota.

BucketLimitApplies to
Public status60/min per IPGET /public/status/*
Private read120/min per API keyGET /projects, checks, incidents, …
Private write30/min per API keyPOST, PATCH, DELETE

On limit: HTTP 429, body includes RATE_LIMIT, header Retry-After (seconds).

Other codes:

  • 401 — missing or invalid Bearer key
  • 404 — wrong project/check id or soft-deleted project
  • 403 — plan limit (PLAN_LIMIT_*) or Free tier without API

Example: fail CI if production is down

#!/usr/bin/env bash
set -euo pipefail
SLUG="my-saas"
json=$(curl -sf "https://api.stillonline.tech/v1/public/status/${SLUG}")
status=$(echo "$json" | jq -r '.status')
if [[ "$status" != "operational" ]]; then
  echo "StillOnline reports: $status"
  exit 1
fi
echo "Status OK: $status"

For owner-only logic (e.g. skip if check is paused), use the private checks list and inspect enabled + last_status.

Write endpoints (brief)

Status reading is GET-only. When you also need to create monitors from code:

  • POST /projects — project + first check in one call
  • POST /projects/{id}/checks — add URL
  • POST /status-pages/{id}/incidents — open comms incident (active_incident in public JSON)

Full catalog: /en/docs/api. MCP wraps the same API: /en/docs/mcp.

Windows PowerShell note

Avoid curl -d '{"enabled":false}' with tricky quoting — use curl.exe with escaped quotes or send UTF-8 JSON bytes. Cyrillic in JSON bodies needs Content-Type: application/json; charset=utf-8. Details on the docs page under Windows PowerShell.

Owner alerts (not in the API)

The REST API reads probe results and status JSON. Down / recovery / 24h notifications to humans go through email, Telegram, or Slack in the dashboard — configure in account settings. Guides: Telegram · Slack. On Free, pick one owner channel; on Pro / Ultimate, enable all three.

Related guides

FAQ

When should I use StillOnline public vs private REST endpoints?

Use GET /public/status/{slug} for customer widgets, CI smoke tests, and anything that must not hold secrets—it mirrors your public status page. Use GET /projects/{id}/checks with Bearer auth when you need last_probed_at, pause state, and per-URL last_status (Pro/Ultimate only).

Does the StillOnline REST API ping my server on each GET?

No. These GET endpoints read stored probe results from StillOnline workers that HTTP-check your registered URL on an interval (for example 5 minutes on Free). Add a health URL before expecting meaningful JSON.

Can I fetch a private StillOnline status page without an API key?

No. GET /public/status/{slug} returns 404 when visibility is private. Use the private checks API with sk_live_… from API settings, or manage incidents in the StillOnline app.

Does StillOnline Free include REST API access?

No API key on Free—one URL and 24h history in the UI only. If your status page is public, the public status JSON still works without a key. Upgrade to Pro for private reads, writes, and MCP.

How is StillOnline REST different from stillonline-mcp?

Same underlying API and data model. REST fits scripts, CI, and backend services; MCP fits Cursor/Claude agents in the IDE. Both require Pro/Ultimate except the keyless public status GET.

Can I close StillOnline incidents via REST API?

You can create incidents with POST …/incidents (they appear in public JSON as active_incident). Closing an incident is UI-only in API v1—a documented current limitation, not a roadmap promise.