Incidents and maintenance
Incidents and maintenance windows are written by people, not detected. They belong to a project and show on that project's status pages. Monitors going down do not open incidents by themselves.
Both are managed in the dashboard (Monitor → project → Incidents and
Maintenance) or through the API. The kamu CLI has no incident or
maintenance commands.
Incidents
An incident has a title, an impact, a status and a timeline of updates. Creating one posts its first update.
| Field | Values |
|---|---|
| Impact | minor (default), major, critical |
| Status | investigating (default), identified, monitoring, resolved |
| Monitors | Optional list of affected monitors |
Dashboard: New incident takes title, message, impact and monitors. Open an
incident from the list to see its timeline and post an update: pick the new
status and write a message. Posting resolved closes it.
Incidents cannot be edited or deleted once posted, neither in the dashboard nor through the API. Updates are append-only.
API
Through the front door with an access key (status.read to list,
status.manage to write):
BASE=https://app.kamuhub.com/api/status
AUTH="Authorization: Bearer $KAMU_ACCESS_KEY"
# open an incident
curl -X POST "$BASE/projects/<project-id>/incidents" -H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"title": "Checkout errors", "message": "Looking into failed payments.",
"impact": "major", "monitorIds": ["<monitor-id>"]}'
# post an update; status "resolved" closes it
curl -X POST "$BASE/incidents/<incident-id>/updates" -H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"status": "identified", "message": "Payment provider outage."}'
curl "$BASE/projects/<project-id>/incidents" -H "$AUTH" # latest 50
curl "$BASE/incidents/<incident-id>" -H "$AUTH" # with updates and monitors
Back-dating. A post-mortem written after the fact can carry the real
times: startedAt on create sets when the incident began, and at on an
update sets that update's time (a resolved update with at sets the resolved
time). Both are ISO 8601, must not be in the future, and at must not be
before the incident started.
curl -X POST "$BASE/projects/<project-id>/incidents" -H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"title": "API unavailable", "message": "Database unreachable.",
"impact": "major", "startedAt": "2026-10-26T12:00:00Z"}'
curl -X POST "$BASE/incidents/<incident-id>/updates" -H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"status": "resolved", "message": "Moved to a new host.", "at": "2026-10-26T16:18:00Z"}'
title and message are required on create; status and message on an
update. The API does not check the values of impact and status. Stick to
the ones above, because the status pages only treat resolved specially.
On status pages
Every public status page of the project shows the project's incidents. The linked monitors do not limit which pages show an incident.
- Active Incidents: every incident not yet
resolved, newest first, with its full update timeline and an impact badge. - Past Incidents (90 days): up to 20 incidents resolved in the last 90 days, with title, impact and resolve time.
- Any open incident switches the page banner to "Some systems are experiencing issues", whatever its impact and whatever the monitors show.
A project-level public status page (the project's own slug with public status enabled) shows monitors only, without incidents or maintenance.
Nobody is notified when you open or update an incident: alert rules and channels are not involved, and status pages have no email subscriptions.
Maintenance windows
A maintenance window announces planned work and silences uptime alerts for the monitors it covers.
| Field | Notes |
|---|---|
| Title | Required. |
| Description | Optional. |
| Starts / Ends | Required. Cannot be changed afterwards. |
| Monitors | The monitors whose alerts are suppressed. |
| Status | scheduled on creation. Set to completed or cancelled by hand. |
Dashboard: Schedule maintenance, then Complete, Cancel or Remove in the list.
API:
curl -X POST "$BASE/projects/<project-id>/maintenance" -H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"title": "Database upgrade", "description": "Postgres 17 to 18.",
"startsAt": "2026-11-02T22:00:00Z", "endsAt": "2026-11-02T23:00:00Z",
"monitorIds": ["<monitor-id>"]}'
curl -X PATCH "$BASE/maintenance/<id>" -H "$AUTH" \
-H "Content-Type: application/json" -d '{"status": "completed"}'
curl -X DELETE "$BASE/maintenance/<id>" -H "$AUTH"
curl "$BASE/projects/<project-id>/maintenance" -H "$AUTH"
How it behaves:
- Alert suppression is by time. Between the start and end time, uptime alerts for the linked monitors do not fire. Checks keep running and downtime still counts in uptime figures.
- Only
cancelledstops suppression early. Marking a windowcompletedbefore its end time does not; delete it instead, or let it run out. - Heartbeat monitors are not suppressed.
- The status never changes by itself. A window stays
scheduledwhile it is running unless you change it. - On status pages every window whose end time has not passed is listed under Scheduled Maintenance with its times, the stored status in brackets and the description. That includes cancelled windows, so delete a cancelled window if it should disappear from the page. Maintenance does not change the page banner.