boltZharp Docs
crisis_alertAPI Reference

Incidents & Maintenance

List, report, acknowledge, resolve and comment on incidents, page people about them, and schedule maintenance windows.

Paths are relative to https://api.zharp.io/api/v1, and every request sends a key as Authorization: Bearer zh_live_… — see Authentication. Incident changes need a write key; maintenance changes need admin. Both need the resources:manage permission, which every role but Read-only has.

The incident lifecycle

An incident is ONGOING when it opens, INVESTIGATING once someone acknowledges it, and RESOLVED when it's over. Monitors open and close their own incidents (mode: AUTOMATIC); the ones people report are MANUAL. A resolved incident can be reopened within 24 hours of being resolved.

FieldValues
statusONGOING, INVESTIGATING, RESOLVED
modeAUTOMATIC (raised by a monitor), MANUAL (reported by a person or the public form)
categoryDNS, SSL, HTTP, PING, TCP, TIMEOUT, MAINTENANCE, LOGS, SYNTHETIC, DATABASE, CACHE, INFRASTRUCTURE, SECURITY, EMAIL, COMPLIANCE, UNKNOWN (default)
activities[].typeCOMMENT, ACKNOWLEDGMENT, RESOLUTION, ESCALATION, SYSTEM_LOG, TRACKED_EVENT

Incidents

GET/incidents
Scope: read
The workspace's incidents, newest first unless you sort otherwise, with paging, filters and search.

_count.activities counts comments. acknowledgedBy, resolvedBy and reportedBy are { name, email, photoUrl } when set.

Query parameters
page
integer
Page number, from 1. Default 1.
limit
integer
Per page, 1–100. Default 50.
status
string
One status or a comma-separated list: ONGOING,INVESTIGATING. Unknown values are ignored.
q
string
Text to find in the title, root cause, description or monitor name, ignoring case.
sort
string
newest (default), oldest, or longest — by how long each lasted, open ones counted up to now.
Request
curl "https://api.zharp.io/api/v1/incidents?status=ONGOING,INVESTIGATING&limit=20" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "Incidents retrieved successfully",
  "data": [
    {
      "id": 481,
      "title": "api.acme.io is down",
      "description": null,
      "rootCause": "HTTP 503 Service Unavailable",
      "status": "ONGOING",
      "mode": "AUTOMATIC",
      "monitorId": 77,
      "startedAt": "2026-10-26T08:14:02.000Z",
      "resolvedAt": null,
      "monitor": { "name": "API", "type": "HTTP" },
      "reportedBy": null,
      "reporterEmail": null,
      "acknowledgedBy": null,
      "resolvedBy": null,
      "_count": { "activities": 0 }
    }
  ],
  "meta": { "total": 60, "page": 1, "limit": 20, "totalPages": 3 }
}
Errors
  • 400limit above 100, or page / limit below 1.
GET/incidents/stats
Scope: read
How many of the workspace's incidents are in each status.
Request
curl "https://api.zharp.io/api/v1/incidents/stats" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "Incidents retrieved successfully",
  "data": { "ongoing": 2, "investigating": 1, "resolved": 57 }
}
GET/incidents/calendar
Scope: read
One month, day by day (UTC): how many incidents touched each day, how many monitors they affected, the downtime — overlapping incidents counted once — the share of the day without an open incident, and who was on call at noon.

uptimePercentage is null for days still to come; today counts up to now.

Query parameters
month
string
YYYY-MM. Defaults to the current month.
Request
curl "https://api.zharp.io/api/v1/incidents/calendar?month=2026-10" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": {
    "month": "2026-10",
    "days": [
      {
        "date": "2026-10-01",
        "incidentCount": 2,
        "affectedMonitors": 1,
        "downtimeSeconds": 840,
        "onCall": [{ "id": 12, "name": "Ada", "email": "ada@acme.io", "photoUrl": null }],
        "uptimePercentage": 99.03
      },
      …
    ]
  }
}
Errors
  • 400month isn't YYYY-MM.
GET/incidents/:id
Scope: read
One incident with everything about it: what was captured when it opened, who acknowledged and resolved it, and its whole timeline, newest first.

It also carries what the failing check captured — requestHeaders, requestBody, responseHeaders, responseBody, traceroute — and the AI post-mortem once one is written (aiPostMortem).

Path parameters
id
integerrequired
The incident's id.
Request
curl "https://api.zharp.io/api/v1/incidents/481" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": {
    "id": 481,
    "title": "api.acme.io is down",
    "status": "INVESTIGATING",
    "rootCause": "HTTP 503 Service Unavailable",
    "category": "HTTP",
    "startedAt": "2026-10-26T08:14:02.000Z",
    "acknowledgedAt": "2026-10-26T08:16:40.000Z",
    "resolvedAt": null,
    "acknowledgedBy": { "id": 12, "name": "Ada", "email": "ada@acme.io", "photoUrl": null },
    "resolvedBy": null,
    "monitor": { "id": 77, "name": "API", "type": "HTTP", … },
    "activities": [
      {
        "id": 9001,
        "type": "ACKNOWLEDGMENT",
        "message": "Status moved to Investigating",
        "status": "INVESTIGATING",
        "createdAt": "2026-10-26T08:16:40.000Z",
        "user": { "name": "Ada", "email": "ada@acme.io", "photoUrl": null },
        "attachments": []
      },
      …
    ],
    …
  }
}
Errors
  • 404No such incident in this workspace.
GET/incidents/:id/activities
Scope: read
The incident's timeline, newest first, a page at a time.

Here meta is inside data, next to the activities.

Path parameters
id
integerrequired
The incident's id.
Query parameters
page
integer
Default 1.
limit
integer
Default 50.
Request
curl "https://api.zharp.io/api/v1/incidents/481/activities?limit=20" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "Activities retrieved successfully",
  "data": {
    "activities": [
      {
        "id": 9002,
        "incidentId": 481,
        "userId": 12,
        "type": "COMMENT",
        "message": "Rolling back the deploy",
        "status": "INVESTIGATING",
        "metadata": null,
        "createdAt": "2026-10-26T08:20:11.000Z",
        "user": { "name": "Ada", "firstName": "Ada", "lastName": "L", "email": "ada@acme.io", "photoUrl": null },
        "attachments": []
      }
    ],
    "meta": { "total": 7, "page": 1, "limit": 20, "totalPages": 1 }
  }
}
Errors
  • 404No such incident in this workspace.
POST/incidents
Scope: writePermission: resources:manage
Report an incident. It opens as ONGOING and MANUAL, reported by the key's owner, and people are told the way you choose with reportTo: by default the monitor's escalation policy, else whoever is on call, else the whole team. The monitor's alert connections that send “down” alerts are notified too.
Body (JSON)
title
stringrequired
1–255 characters.
description
string
Optional.
monitorId
integer
The monitor it's about — one in this workspace.
category
string
One of the categories above. Default UNKNOWN.
isPublic
boolean
Whether it may show on public status pages. Default false.
reportTo
string
Who to tell. auto (default) as above; team for everyone; or one of group:ID, policy:ID, schedule:ID, user:ID, channel:ID — a team group, escalation policy, on-call schedule, member or alert connection in this workspace.
notifications
object
How people are reached: { "email": true, "push": true, "criticalAlert": false }. criticalAlert pages through phones' silent mode and implies push. Without it, the monitor's own setting is used.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents" \
  -H "Authorization: Bearer $ZHARP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Checkout failing for EU users",
    "description": "Card payments time out since 09:40 UTC.",
    "monitorId": 77,
    "reportTo": "policy:4"
  }'
Response
{
  "message": "Incident reported successfully",
  "data": {
    "id": 481,
    "workspaceId": 3,
    "monitorId": 77,
    "title": "api.acme.io is down",
    "description": null,
    "status": "ONGOING",
    "mode": "MANUAL",
    "isAcknowledged": true,
    "rootCause": "HTTP 503 Service Unavailable",
    "category": "HTTP",
    "isPublic": false,
    "reporterEmail": null,
    "startedAt": "2026-10-26T08:14:02.000Z",
    "acknowledgedAt": "2026-10-26T08:16:40.000Z",
    "resolvedAt": null,
    "reportedById": null,
    "acknowledgedById": 12,
    "resolvedById": null,
    "createdAt": "2026-10-26T08:14:02.000Z",
    "updatedAt": "2026-10-26T08:16:40.000Z"
  }
}
Errors
  • 400A field fails validation, or the reportTo target isn't in this workspace.
  • 403The key's scope is below write, or its owner is Read-only.
POST/incidents/:id/acknowledge
Scope: writePermission: resources:manage
Acknowledge it: the status moves to INVESTIGATING, the key's owner is recorded as who acknowledged it, and connections that send “acknowledged” alerts are told.
Path parameters
id
integerrequired
The incident's id.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/acknowledge" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": { "id": 481, "status": "INVESTIGATING", "isAcknowledged": true, "acknowledgedAt": "…", "acknowledgedById": 12, … }
}
Errors
  • 404No such incident in this workspace.
POST/incidents/:id/resolve
Scope: writePermission: resources:manage
Resolve it now, as the key's owner. Zapier's “incident resolved” trigger fires.

A monitor resolves its own incidents when its checks pass again — call this for incidents people reported, or to close one by hand.

Path parameters
id
integerrequired
The incident's id.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/resolve" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": { "id": 481, "status": "RESOLVED", "resolvedAt": "…", "resolvedById": 12, … }
}
Errors
  • 404No such incident in this workspace.
POST/incidents/:id/reopen
Scope: writePermission: resources:manage
Move a resolved incident back to ONGOING. Only within 24 hours of it being resolved. Nobody is notified.
Path parameters
id
integerrequired
The incident's id.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/reopen" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": { "id": 481, "status": "ONGOING", "isAcknowledged": false, "resolvedAt": null, … }
}
Errors
  • 404No such incident in this workspace.
  • 403It was resolved more than 24 hours ago — report a new incident instead.
POST/incidents/:id/comments
Scope: writePermission: resources:manage
Add a comment to the timeline as the key's owner. It doesn't change the status or notify anyone.
Path parameters
id
integerrequired
The incident's id.
Body (JSON)
content
stringrequired
The comment. At least one character.
attachments
object[]
Files to show with it: what uploading an attachment answered, as it came.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/comments" \
  -H "Authorization: Bearer $ZHARP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Rolled back to v1.4.1 — watching error rates."
  }'
Response
{
  "message": "…",
  "data": {
    "id": 9003,
    "incidentId": 481,
    "userId": 12,
    "type": "COMMENT",
    "message": "Rolled back to v1.4.1 — watching error rates.",
    "status": "INVESTIGATING",
    "createdAt": "2026-10-26T08:31:05.000Z",
    "user": { "name": "Ada", … },
    "attachments": []
  }
}
Errors
  • 400content is missing or empty.
  • 404No such incident in this workspace.
POST/incidents/:id/attachments
Scope: writePermission: resources:manage
Upload a picture or PDF for a comment. It isn't on the timeline until you post a comment with it.

Then post it: { "content": "Error rate during the outage", "attachments": [<that data>] }.

Path parameters
id
integerrequired
The incident's id.
Body (JSON)
file
filerequired
multipart/form-data. PNG, JPG, GIF, WebP or PDF, up to 10 MB.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/attachments"   -H "Authorization: Bearer $ZHARP_API_KEY"   -F "file=@error-rate.png"
Response
{
  "message": "Attachment uploaded successfully",
  "data": {
    "public_id": "incidents/481/xyz",
    "secure_url": "https://res.cloudinary.com/…/incidents/481/xyz.png",
    "url": "https://res.cloudinary.com/…/incidents/481/xyz.png",
    "format": "png",
    "bytes": 48211,
    "resource_type": "image",
    "original_filename": "error-rate"
  }
}
Errors
  • 400No file, or not one of those types.
  • 413Over 10 MB.
  • 404No such incident in this workspace.
GET/incidents/:id/logs
Scope: read
The application log lines from around the incident: from the services in its monitor's logServiceNames, from a few minutes before it started until a few minutes after it ended (or now). Up to 500 lines, newest first.

An incident whose monitor names no log services answers with an empty list.

Path parameters
id
integerrequired
The incident's id.
Query parameters
before
integer
Minutes before it started, 1–60. Default 5.
after
integer
Minutes after it ended, 1–60. Default 5.
Request
curl "https://api.zharp.io/api/v1/incidents/481/logs?before=10" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "Logs retrieved successfully",
  "data": [{ "serviceName": "api", "environment": "production", "level": "error", "message": "upstream timed out", "timestamp": "…", "metadata": { … } }],
  "meta": { "before": 10, "after": 5 }
}
Errors
  • 404No such incident in this workspace.
POST/incidents/:id/escalate
Scope: writePermission: resources:manage
Page people about it now. An escalation policy target starts that policy; an on-call schedule pages whoever is on call; the team, a group, a member or an alert connection are notified straight away. The timeline records who escalated to whom.
Path parameters
id
integerrequired
The incident's id.
Body (JSON)
targets
string[]required
At least one of team, group:ID, policy:ID, schedule:ID, user:ID, channel:ID — each in this workspace.
channels
string[]required
How to reach people: any of email, push, critical (a critical push that sounds through silent mode). E-mail or push at least.
Request
curl -X POST "https://api.zharp.io/api/v1/incidents/481/escalate" \
  -H "Authorization: Bearer $ZHARP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": [
      "schedule:2",
      "user:12"
    ],
    "channels": [
      "push",
      "email"
    ]
  }'
Response
{
  "message": "Incident escalated successfully",
  "data": { "reached": ["whoever is on call on Primary", "Ada"] }
}
Errors
  • 400No targets, no way to reach them, or a target that isn't in this workspace.
  • 404No such incident in this workspace.
POST/public/incidents/report/:token
Scope: no key
The public “report an incident” form — no API key: the workspace's report link token is the credential. It opens a manual incident that follows the automatic response (the monitor's policy, else whoever is on call, else the team). Find the link in Incidents.
Path parameters
token
stringrequired
The token in the workspace's report link.
Body (JSON)
title
stringrequired
1–255 characters.
description
string
Optional.
email
string
The reporter's e-mail, so the team can get back to them.
monitorId
integer
The monitor it's about, if known.
Request
curl -X POST "https://api.zharp.io/api/v1/public/incidents/report/YOUR_REPORT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Can't log in", "email": "customer@example.com" }'
Response
{ "message": "Incident reported successfully", "data": { "id": 483, "status": "ONGOING", "mode": "MANUAL", … } }
Errors
  • 404The link is wrong or has been replaced.
  • 400A field fails validation — title is missing, say.
  • 429More than 5 reports an hour from one address, or 30 an hour into one workspace.

Maintenance windows

While a window is on, its monitors are under maintenance: their alerts and escalations stop, and status pages showing them say so. A window happens once, or repeats daily or weekly.

GET/maintenance
Scope: read
The workspace's maintenance windows, latest start first. Windows set on a single monitor's own settings aren't listed.
  • active — an occurrence is running right now.
  • nextOccurrence — the current or next occurrence; null once a one-off window has passed.
  • repeatConfig.days are weekdays, Sunday = 0, in the window's timezone.
Request
curl "https://api.zharp.io/api/v1/maintenance" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": [
    {
      "id": 14,
      "workspaceId": 3,
      "name": "Database upgrade",
      "description": null,
      "startTime": "2026-11-01T02:00:00.000Z",
      "endTime": "2026-11-01T04:00:00.000Z",
      "timezone": "Europe/Paris",
      "scheduleType": "recurring",
      "repeatConfig": { "frequency": "weekly", "days": [0], "time": "03:00", "durationMinutes": 120 },
      "notificationConfig": null,
      "createdAt": "2026-10-20T10:00:00.000Z",
      "updatedAt": "2026-10-20T10:00:00.000Z",
      "_count": { "monitors": 3 },
      "recurring": true,
      "active": false,
      "nextOccurrence": { "startTime": "2026-11-01T02:00:00.000Z", "endTime": "2026-11-01T04:00:00.000Z" }
    }
  ]
}
GET/maintenance/:id
Scope: read
One window, with the monitors it covers.
Path parameters
id
integerrequired
The maintenance window's id.
Request
curl "https://api.zharp.io/api/v1/maintenance/14" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{
  "message": "…",
  "data": {
    "id": 14,
    "name": "Database upgrade",
    …,
    "monitors": [{ "maintenanceWindowId": 14, "monitorId": 77, "monitor": { "id": 77, "name": "API", "type": "HTTP", … } }],
    "recurring": true,
    "active": false,
    "nextOccurrence": { "startTime": "…", "endTime": "…" }
  }
}
Errors
  • 404No such window in this workspace.
POST/maintenance
Scope: adminPermission: resources:manage
Schedule a window over some monitors. If it's still to come, subscribers of the status pages that show those monitors are e-mailed about it.
Body (JSON)
name
stringrequired
1–100 characters.
description
string
Optional.
startTime
string (ISO 8601)required
When the (first) occurrence starts.
endTime
string (ISO 8601)required
When it ends — after startTime.
timezone
string
An IANA zone such as Europe/Paris; repeats keep this zone's local time. Default UTC.
repeatConfig
object | null
Omit or null for a one-off. { "frequency": "daily" } repeats every day at the same time (up to 24 hours long); { "frequency": "weekly" } repeats on the start's weekday (up to 7 days long). An object without a frequency is refused.
monitorIds
integer[]
The monitors it covers, all in this workspace.
Request
curl -X POST "https://api.zharp.io/api/v1/maintenance" \
  -H "Authorization: Bearer $ZHARP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Database upgrade",
    "startTime": "2026-11-01T02:00:00Z",
    "endTime": "2026-11-01T04:00:00Z",
    "timezone": "Europe/Paris",
    "repeatConfig": {
      "frequency": "weekly"
    },
    "monitorIds": [
      77,
      78,
      91
    ]
  }'
Response
{
  "message": "…",
  "data": {
    "id": 15,
    "name": "Database upgrade",
    "scheduleType": "recurring",
    "repeatConfig": { "frequency": "weekly", "days": [0], "time": "03:00", "durationMinutes": 120 },
    "monitors": [ … ],
    "recurring": true,
    "active": false,
    "nextOccurrence": { "startTime": "2026-11-01T02:00:00.000Z", "endTime": "2026-11-01T04:00:00.000Z" },
    …
  }
}
Errors
  • 400A field fails validation, an unknown field, an unknown time zone, an end before the start, or a repeat longer than its period.
  • 404A monitor id isn't in this workspace.
PUT/maintenance/:id
Scope: adminPermission: resources:manage
Change a window. Send only the fields to change — the same ones as creating it. monitorIds replaces the whole list; "repeatConfig": null stops it repeating. Subscribers aren't e-mailed again.
Path parameters
id
integerrequired
The maintenance window's id.
Request
curl -X PUT "https://api.zharp.io/api/v1/maintenance/14" \
  -H "Authorization: Bearer $ZHARP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "endTime": "2026-11-01T05:00:00Z"
  }'
Response
{ "message": "…", "data": { "id": 14, "endTime": "2026-11-01T05:00:00.000Z", … } }
Errors
  • 400As for creating one.
  • 404No such window, or a monitor id that isn't in this workspace.
  • 409The window belongs to one monitor — change it with that monitor's maintenanceWindows on PUT /monitors/:id.
DELETE/maintenance/:id
Scope: adminPermission: resources:manage
Delete a window. Its monitors go back to normal alerting at once.
Path parameters
id
integerrequired
The maintenance window's id.
Request
curl -X DELETE "https://api.zharp.io/api/v1/maintenance/14" \
  -H "Authorization: Bearer $ZHARP_API_KEY"
Response
{ "message": "…", "data": null }
Errors
  • 404No such window in this workspace.
  • 409The window belongs to one monitor — remove it from that monitor instead.