incidentio
// Manage incidents via the incident.io REST API. Create, view, update, escalate, and resolve incidents. Check severities, statuses, and post incident updates. Requires INCIDENTIO_API_KEY environment variable.
Incident.io
Manage incidents, severities, statuses, and post updates via the incident.io REST API.
Setup
- Create an API key at Settings > API keys in the incident.io dashboard
- Ensure the key has scopes for managing incidents and viewing organization data
- Set the environment variable:
export INCIDENTIO_API_KEY="your-api-key"
API Basics
Base URL: https://api.incident.io
Important: The API has a v1/v2 split:
- v2 — Incidents, incident updates
- v1 — Severities, incident statuses, incident types
All requests use this auth pattern:
curl -s "https://api.incident.io/v2/..." \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
-H "Content-Type: application/json"
Rate limit: 1200 requests/minute per API key.
Pagination: Use page_size (max 250) and the after cursor from pagination_meta.after in responses.
List Severities
Severities are organization-specific. Always fetch them before creating an incident to get valid IDs.
curl -s "https://api.incident.io/v1/severities" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" | jq '.severities[] | {id, name, rank}'
List Incident Statuses
curl -s "https://api.incident.io/v1/incident_statuses" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" | jq '.incident_statuses[] | {id, name, category}'
Status categories: triage, live, learning, closed, declined, merged, canceled.
List Incident Types
curl -s "https://api.incident.io/v1/incident_types" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" | jq '.incident_types[] | {id, name, is_default}'
Create an Incident
Required fields: idempotency_key, visibility. A severity_id is needed to open an active incident.
curl -s -X POST "https://api.incident.io/v2/incidents" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "unique-key-123",
"name": "Database connection pool exhaustion",
"summary": "Primary DB connection pool at 100% causing request failures",
"severity_id": "SEVERITY_ID",
"visibility": "public",
"mode": "standard"
}' | jq '.incident | {id, reference, name, permalink}'
Optional fields:
incident_type_id— set a specific incident typeincident_status_id— override the default starting statusmode—standard(default),retrospective(no Slack announcement), ortest(no alerts)visibility—publicorprivatecustom_field_entries— array of{custom_field_id, values: [{value_link}]}incident_role_assignments— array of{incident_role_id, user: {id}}incident_timestamp_values— array of{incident_timestamp_id, value}
Always generate a unique idempotency_key per incident (e.g. a UUID or descriptive slug).
Get an Incident
curl -s "https://api.incident.io/v2/incidents/INCIDENT_ID" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
| jq '.incident | {id, reference, name, summary, status: .incident_status.name, severity: .severity.name, created_at, permalink}'
List Incidents
curl -s "https://api.incident.io/v2/incidents?page_size=25" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
| jq '.incidents[] | {id, reference, name, status: .incident_status.name, severity: .severity.name}'
Filter parameters (query string):
status_category[one_of]=live— filter by category (triage,live,learning,closed,declined,merged,canceled)status[one_of]=STATUS_ID— filter by exact status ID (repeatable)severity[one_of]=SEVERITY_ID— filter by severity (repeatable)severity[gte]=SEVERITY_ID/severity[lte]=SEVERITY_ID— filter by severity rankcreated_at[gte]=2024-01-01/created_at[lte]=2024-12-31— date rangemode[one_of]=standard— filter by modepage_size=N(max 250) andafter=CURSORfor pagination
Edit an Incident
Only provided fields are updated; omitted fields remain unchanged.
curl -s -X POST "https://api.incident.io/v2/incidents/INCIDENT_ID/actions/edit" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"incident": {
"summary": "Root cause identified: memory leak in connection pooler",
"severity_id": "NEW_SEVERITY_ID"
},
"notify_incident_channel": true
}' | jq '.incident | {id, reference, name, severity: .severity.name}'
Editable fields inside incident:
name,summary,severity_id,incident_status_idcall_url,slack_channel_name_overridecustom_field_entries,incident_role_assignments,incident_timestamp_values
Set notify_incident_channel: true to alert responders of the change.
Close an Incident
Closing is done by setting incident_status_id to a status with category closed. First, find the closed status ID:
curl -s "https://api.incident.io/v1/incident_statuses" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
| jq '.incident_statuses[] | select(.category == "closed") | {id, name}'
Then update the incident:
curl -s -X POST "https://api.incident.io/v2/incidents/INCIDENT_ID/actions/edit" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"incident": {
"incident_status_id": "CLOSED_STATUS_ID"
},
"notify_incident_channel": true
}' | jq '.incident | {id, reference, name, status: .incident_status.name}'
Post an Incident Update
curl -s -X POST "https://api.incident.io/v2/incident_updates" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"incident_id": "INCIDENT_ID",
"message": "Rolling restart in progress. Monitoring connection pool metrics."
}' | jq '.incident_update | {id, message, created_at}'
List Incident Updates
curl -s "https://api.incident.io/v2/incident_updates?incident_id=INCIDENT_ID&page_size=25" \
-H "Authorization: Bearer $INCIDENTIO_API_KEY" \
| jq '.incident_updates[] | {id, message, created_at}'
Common Workflows
Declare and manage an incident end-to-end
- Fetch severities —
GET /v1/severitiesto get valid severity IDs - Create incident —
POST /v2/incidentswith name, severity, visibility - Post updates —
POST /v2/incident_updatesas investigation progresses - Escalate if needed — Edit the incident to raise severity via
POST /v2/incidents/{id}/actions/edit - Resolve — Edit the incident status to a
closed-category status
Triage active incidents
- List live incidents —
GET /v2/incidents?status_category[one_of]=live - Get details —
GET /v2/incidents/{id}for each incident - Check updates —
GET /v2/incident_updates?incident_id={id}for latest status
Notes
- IDs are ULIDs (e.g.
01FCNDV6P870EA6S7TK1DSYDG0) - Severities, statuses, and types are organization-specific — always query them dynamically rather than hardcoding
- The
idempotency_keyon create prevents duplicate incidents; use a unique value per request mode: "test"creates test incidents that do not alert responders- The edit endpoint wraps fields inside an
incidentobject, unlike the create endpoint - Rate limit: 1200 req/min per API key
- Pagination: use the
aftercursor frompagination_meta.afterin responses