REST API
The read-only REST API lets you pull your Asniher data into your own dashboards, scripts, Grafana panels or internal tools. It's included in Pro and Team.
- Base URL:
https://app.asniher.com/api/v1 - OpenAPI spec:
/api/v1/openapi.json
Authentication
Create a secret key under Dashboard → API & embeds. Owners and admins can create and revoke keys. The full key is shown once. Asniher stores only a hash of it.
Send the key as a bearer token:
curl https://app.asniher.com/api/v1/monitors \
-H "Authorization: Bearer ask_live_…"
Secret keys (ask_live_…) can read everything in your team. Keep them on your server and never put them in a web page. To show status on your website, use the embed widget instead.
If your team moves to the Free plan, its secret keys return 403 until you upgrade again.
Endpoints
| Method and path | Returns |
|---|---|
GET /monitors |
All monitors with current status and 24-hour uptime. |
GET /monitors/{id} |
One monitor with 24h, 7d, 30d and 90d uptime. |
GET /monitors/{id}/checks |
The check log: every check with time, region, result, status code, latency and error. |
GET /monitors/{id}/uptime?period=30d |
Uptime report for 24h, 7d, 30d or 90d, with hourly or daily buckets. |
GET /monitors/{id}/pings |
The latest pings of a heartbeat monitor, with exit status, duration and output. |
GET /incidents |
Incidents, newest first. Filter with status=open|resolved and monitor={id}. |
GET /incidents/{id} |
One incident with its timeline. |
Every response is JSON. A single resource or plain list comes back as { "data": … }.
Check log
curl "https://app.asniher.com/api/v1/monitors/$ID/checks?from=2026-10-01T00:00:00Z&limit=500" \
-H "Authorization: Bearer $ASNIHER_KEY"
{
"data": [
{ "time": "2026-10-23T09:14:00.000Z", "region": "eu-central", "ok": true, "statusCode": 200, "latencyMs": 182, "error": null, "attempt": 1 }
],
"nextCursor": "WyIyMDI2LTEwLTIzIDA5OjEz…",
"retentionDays": 30
}
from and to take ISO 8601 timestamps. By default they cover the last 24 hours. Individual checks are kept for 30 days. Hourly and daily aggregates, which the uptime report uses, are kept for 400 days.
Uptime report
{
"data": {
"period": "7d",
"bucketSize": "day",
"uptimePct": 99.982,
"checks": 10080,
"failedChecks": 2,
"avgLatencyMs": 176,
"buckets": [
{ "start": "2026-10-17T00:00:00.000Z", "uptimePct": 100, "checks": 1440, "failedChecks": 0, "avgLatencyMs": 171, "p95LatencyMs": 240 }
]
}
}
p95LatencyMs is per bucket. When a monitor runs from more than one region, it's the highest p95 among them.
Pagination
List endpoints that can be long return nextCursor. To get the next page, pass it back as cursor with the same filters. When nextCursor is null there are no more results. Use limit to set the page size: up to 1000 for checks and 200 for incidents.
Rate limits
Each key can make 120 requests per minute. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, the Unix time when the window resets. Over the limit you get 429 with a Retry-After header.
Errors
Errors return a JSON body such as { "error": "Monitor not found", "code": "not_found" }.
| Status | Meaning |
|---|---|
400 |
Invalid query parameter or cursor. |
401 |
Missing, invalid or revoked key. |
403 |
An embed key was used, or your plan doesn't include the API. |
404 |
The monitor or incident doesn't exist in your team. |
429 |
Rate limit exceeded. |