Incidents
Runframe V1 incident API. Create, update, acknowledge, resolve, page responders, and escalate incidents.
Manage the full incident lifecycle through the V1 API.
Identifiers
Incident endpoints accept two identifier formats:
| Format | Example | Notes |
|---|---|---|
| UUID | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | Internal ID |
| Incident number | INC-2026-044 | Human-readable string |
Both work interchangeably in any :id path parameter.
Create Incident
POST /api/v1/incidentsRequired fields: title, service_ids
{
"title": "Database connection pool exhaustion",
"description": "API returning 500s due to connection limit",
"severity": "SEV1",
"service_ids": ["SER-00001", "SER-00002"],
"team_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | 1-200 characters |
description | string | No | Detailed description |
severity | string | No | SEV0-SEV4, defaults to SEV3 |
service_ids | string[] | Yes | Public service keys (e.g. SER-00001). Use List Services to discover keys. |
team_id | string (UUID) | No | Team to assign |
Assignment happens automatically based on on-call schedules after creation.
Idempotency: Include Idempotency-Key header for replay-safe creates. See Authentication.
Response: Returns the created incident in the standard envelope.
List Incidents
GET /api/v1/incidents| Parameter | Type | Description |
|---|---|---|
limit | integer | Results per page (max 100, default 20) |
offset | integer | Pagination offset (default 0) |
status | string[] | Filter by status name (repeatable) |
severity | string[] | Filter by severity (repeatable) |
assigned_to | string (UUID) | Filter by current assignee |
resolved_by | string (UUID) | Filter by the user who resolved the incident |
team_id | string (UUID) | Filter by team |
created_after | string (ISO 8601) | Only incidents created at or after this timestamp |
created_before | string (ISO 8601) | Only incidents created at or before this timestamp |
resolved_after | string (ISO 8601) | Only incidents resolved at or after this timestamp |
resolved_before | string (ISO 8601) | Only incidents resolved at or before this timestamp |
Use Users to resolve a person name to a UUID before filtering by assigned_to or resolved_by.
Use GET /api/v1/teams?search=... to resolve a team name before filtering by team_id.
Response:
{
"success": true,
"data": {
"items": [
{
"id": "uuid",
"incident_number": "INC-2026-044",
"title": "...",
"description": "...",
"status": "investigating",
"severity": "SEV1",
"assigned_to": { "id": "uuid", "name": "Jane", "email": "jane@example.com" },
"team": { "id": "uuid", "name": "Platform" },
"created_at": "2026-04-18T10:30:00Z",
"acknowledged_at": null,
"resolved_at": null
}
],
"total": 42,
"has_more": true,
"next_offset": 20
}
}Get Incident
GET /api/v1/incidents/:idReturns full incident details with timeline.
Response includes a timeline array:
{
"timeline": [
{
"event_type": "CREATED",
"title": "Incident created",
"description": null,
"user": "Jane",
"created_at": "2026-04-18T10:30:00Z"
}
]
}Update Incident
PATCH /api/v1/incidents/:idField updates only. For status changes, use Change Status.
{
"title": "Updated title",
"description": "Updated description",
"severity": "SEV2",
"assigned_to": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}| Field | Type | Description |
|---|---|---|
title | string | New title |
description | string | New description |
severity | string | SEV0-SEV4 |
assigned_to | string (UUID) | Reassign to an engineer |
All fields are optional. Only included fields are updated.
Change Status
POST /api/v1/incidents/:id/statusCanonical endpoint for all status transitions. Resolving, closing, investigating, and monitoring all flow through here.
{
"status": "resolved",
"comment": "Fixed by rolling back deploy abc123"
}| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | Target status: new, investigating, fixing, monitoring, resolved, closed |
comment | string | No | Reason for change (max 500 chars) |
Valid transitions are enforced server-side. Some transitions require a comment.
Acknowledge Incident
POST /api/v1/incidents/:id/acknowledgeA dedicated action endpoint with acknowledgement-specific side effects: auto-assignment, acknowledgement timestamp, and SLA resolution. This is intentionally separate from the generic /status transition path.
No request body required. Idempotent — safe to call multiple times.
Response:
{
"success": true,
"data": {
"id": "uuid",
"incident_number": "INC-2026-044",
"acknowledged": true,
"acknowledged_at": "2026-04-18T10:35:00Z"
}
}Page Someone
POST /api/v1/incidents/:id/pageSend a real notification to a specific person. Urgency is derived from incident severity automatically.
{
"user_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"channel": "slack",
"message": "API is down, need your help"
}| Field | Type | Required | Description |
|---|---|---|---|
user_id | string (UUID) | Yes | Person to page |
channel | string | No | slack or email (default: slack) |
message | string | No | Custom message (max 500 chars) |
Status codes:
| Code | Meaning |
|---|---|
200 | Notification sent ({ sent: true, channel: "slack" }) |
409 | Recipient has no contact info for the requested channel |
502 | Notification provider (Slack/email) failed to deliver |
Add Timeline Event
POST /api/v1/incidents/:id/eventsAdd a timeline entry to an incident.
{
"message": "Identified root cause: connection pool leak in auth service"
}Escalate Incident
POST /api/v1/incidents/:id/escalateEscalate to the next level in the escalation policy. Sends real notifications to responders. No request body required.
Response:
{
"success": true,
"data": {
"id": "uuid",
"incident_number": "INC-2026-044",
"escalated": true,
"notified_users": ["uuid-1", "uuid-2"],
"current_level": 2,
"next_level": 3
}
}