# Status incidents API

6 operations under /api/v1. Errors are RFC 9457 problem+json with a stable `code` field. The complete schemas are in https://nebulactrl.com/api/v1/openapi.json.

## GET /status-incidents

List status incidents

Incidents written by people and posted to status pages, newest first, with their timelines.

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `status` (query, enum: active | investigating | identified | monitoring | resolved): Only incidents in this status; active = not resolved
- `pageId` (query, string (uuid)): Only incidents posted to this status page
- `cursor` (query, string): Opaque cursor from a previous page's nextCursor
- `limit` (query, integer (int64)): Page size (default 50, max 200)

Response 200: OK (PageStatusIncidentView)
  - `items` (StatusIncidentView[] | null, required)
  - `nextCursor` (string): Present when more items exist
Errors: 400 Bad Request; 401 Unauthorized; 403 Forbidden; 422 Unprocessable Entity; 500 Internal Server Error

## POST /status-incidents

Open a status incident

Opens an incident whose first timeline entry is `body` and posts it to the pages. Its impact moves the pages' overall state while it is not resolved. Requires the admin scope.

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `Idempotency-Key` (header, string): Client-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.

Request body (application/json, required): CreateIncidentInputBody
  - `body` (string, required): The first update of the timeline. Plain text, line breaks kept
  - `impact` (enum: none | minor | major | critical, required): How the page's overall state changes while the incident is active: critical = major outage, major = partial outage, minor = degraded, none = nothing
  - `pageIds` (string[] | null): The status pages to post it to
  - `serviceIds` (string[] | null): The affected services
  - `status` (enum: investigating | identified | monitoring | resolved): Default investigating
  - `title` (string, required)

Response 201: Created (StatusIncidentView)
  - `createdAt` (string (date-time), required)
  - `id` (string, required)
  - `impact` (enum: none | minor | major | critical, required)
  - `pageIds` (string[] | null, required): The status pages the incident is posted to
  - `resolvedAt` (string (date-time) | null, required)
  - `serviceIds` (string[] | null, required): The services it affects (shown as the affected components of each page that has them)
  - `status` (enum: investigating | identified | monitoring | resolved, required)
  - `title` (string, required)
  - `updatedAt` (string (date-time), required)
  - `updates` (StatusIncidentUpdateView[] | null, required): The timeline, newest first
Errors: 401 Unauthorized; 403 Forbidden; 404 Not Found; 409 Conflict; 422 Unprocessable Entity; 500 Internal Server Error

## GET /status-incidents/{incidentId}

Get a status incident

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `incidentId` (path, string, required)

Response 200: OK (StatusIncidentView)
  - `createdAt` (string (date-time), required)
  - `id` (string, required)
  - `impact` (enum: none | minor | major | critical, required)
  - `pageIds` (string[] | null, required): The status pages the incident is posted to
  - `resolvedAt` (string (date-time) | null, required)
  - `serviceIds` (string[] | null, required): The services it affects (shown as the affected components of each page that has them)
  - `status` (enum: investigating | identified | monitoring | resolved, required)
  - `title` (string, required)
  - `updatedAt` (string (date-time), required)
  - `updates` (StatusIncidentUpdateView[] | null, required): The timeline, newest first
Errors: 401 Unauthorized; 403 Forbidden; 422 Unprocessable Entity; 500 Internal Server Error

## PATCH /status-incidents/{incidentId}

Update a status incident

Changes the title, impact, pages or services; omitted fields stay. The status and timeline change with POST /status-incidents/{incidentId}/updates. Requires the admin scope.

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `incidentId` (path, string, required)

Request body (application/json, required): UpdateIncidentInputBody
  - `impact` (enum: none | minor | major | critical)
  - `pageIds` (string[] | null): Replaces the pages; [] withdraws the incident from every page
  - `serviceIds` (string[] | null): Replaces the affected services
  - `title` (string)

Response 200: OK (StatusIncidentView)
  - `createdAt` (string (date-time), required)
  - `id` (string, required)
  - `impact` (enum: none | minor | major | critical, required)
  - `pageIds` (string[] | null, required): The status pages the incident is posted to
  - `resolvedAt` (string (date-time) | null, required)
  - `serviceIds` (string[] | null, required): The services it affects (shown as the affected components of each page that has them)
  - `status` (enum: investigating | identified | monitoring | resolved, required)
  - `title` (string, required)
  - `updatedAt` (string (date-time), required)
  - `updates` (StatusIncidentUpdateView[] | null, required): The timeline, newest first
Errors: 401 Unauthorized; 403 Forbidden; 404 Not Found; 409 Conflict; 422 Unprocessable Entity; 500 Internal Server Error

## DELETE /status-incidents/{incidentId}

Delete a status incident

Deletes the incident and its timeline; it disappears from the pages. Requires the admin scope.

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `incidentId` (path, string, required)

Response 204: No Content
Errors: 401 Unauthorized; 403 Forbidden; 422 Unprocessable Entity; 500 Internal Server Error

## POST /status-incidents/{incidentId}/updates

Post an incident update

Adds a timeline entry and moves the incident to its status. `resolved` sets `resolvedAt` and ends the incident's effect on the pages' overall state; a later update with another status reopens it. Requires the admin scope.

Authentication: session cookie or `Authorization: Bearer nct_…` token.

Parameters:
- `Idempotency-Key` (header, string): Client-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
- `incidentId` (path, string, required)

Request body (application/json, required): PostIncidentUpdateInputBody
  - `body` (string, required): Plain text, line breaks kept
  - `status` (enum: investigating | identified | monitoring | resolved, required)

Response 201: Created (StatusIncidentView)
  - `createdAt` (string (date-time), required)
  - `id` (string, required)
  - `impact` (enum: none | minor | major | critical, required)
  - `pageIds` (string[] | null, required): The status pages the incident is posted to
  - `resolvedAt` (string (date-time) | null, required)
  - `serviceIds` (string[] | null, required): The services it affects (shown as the affected components of each page that has them)
  - `status` (enum: investigating | identified | monitoring | resolved, required)
  - `title` (string, required)
  - `updatedAt` (string (date-time), required)
  - `updates` (StatusIncidentUpdateView[] | null, required): The timeline, newest first
Errors: 401 Unauthorized; 403 Forbidden; 404 Not Found; 409 Conflict; 422 Unprocessable Entity; 500 Internal Server Error
