Skip to content

This page covers the mechanics you need for reliable integrations. It assumes you already have a key from API overview.

POST /api/v1/incidents requires an idempotency_key in the request body. It is any string you choose that uniquely identifies this creation attempt, for example your alert’s ID or a UUID you generate.

The key protects you from duplicates when a request times out and you retry.

SituationResponse
First request with a key201 Created, a new incident
Repeated request with the same key200 OK, the incident created the first time

Idempotency keys expire after 24 hours. After that, reusing the same key creates a new incident, so treat keys as protection for retries, not as a long-term deduplication mechanism.

Every error is JSON with a single error object. The request_id identifies the request, so include it when you contact support.

{
"error": {
"type": "validation_error",
"message": "Validation failed: Name can't be blank",
"request_id": "9f2c1d4e-8a7b-4c3d-b5e6-0a1b2c3d4e5f",
"errors": [
{ "field": "name", "message": "can't be blank" }
]
}
}

The errors array appears only on validation errors and lists each failing field.

StatustypeWhen
400bad_requestA required parameter is missing
401unauthorizedThe token is missing, invalid, expired, or deactivated
403forbiddenThe token lacks the permission this endpoint checks
404not_foundThe resource does not exist in your workspace
422validation_errorThe request was well-formed but the data is invalid
429rate_limit_exceededYou exceeded 1,000 requests per minute for this key

List endpoints that can grow large, such as incidents and catalog entries, accept two query parameters.

ParameterDefaultMaximum
page1none
per_page25100

Every paginated response includes a pagination object.

{ "pagination": { "page": 2, "per_page": 25, "total": 132, "total_pages": 6 } }

The incident list also accepts filters as query parameters. Use severity_id, status_id, or lifecycle_stage with one of triage, active, closed, or canceled. Look up the IDs from GET /api/v1/severities and GET /api/v1/statuses.

First fetch the reference data you need. Severities, statuses, and types are specific to your workspace, so their IDs are too.

Terminal window
curl https://app.firefight.app/api/v1/severities \
-H "Authorization: Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA"
{
"severities": [
{ "id": "c7e2f9a1-3b4d-4c6e-8f0a-5d6b7c8e9f01", "name": "SEV1", "slug": "sev1", "rank": 1, "position": 1, "is_default": false },
{ "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "name": "SEV2", "slug": "sev2", "rank": 2, "position": 2, "is_default": true }
]
}

Now declare the incident. Only name, severity_id, and idempotency_key are required. Omitting status_id uses your workspace’s default status. You can also pass incident_type_id, declared_by_id with a member’s ID, visibility as public or private, custom_fields as a key-value object, and a free-form source string that tells responders where the incident came from.

Terminal window
curl -X POST https://app.firefight.app/api/v1/incidents \
-H "Authorization: Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "datadog-monitor-771204-1626601964",
"name": "Checkout latency spike in eu-west",
"summary": "p99 latency on the checkout service exceeded 4s.",
"severity_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"source": "datadog"
}'

The response is 201 Created with the full incident.

{
"incident": {
"id": "0d9b2c1e-7f3a-4b8e-9c5d-2a6e8f1b4d70",
"identifier": "INC-42",
"name": "Checkout latency spike in eu-west",
"summary": "p99 latency on the checkout service exceeded 4s.",
"status": { "id": "b1f6a2d4-8c3e-4f5a-9b7d-1e2c3a4b5d6f", "name": "Investigating", "lifecycle_stage": "active" },
"severity": { "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "name": "SEV2", "rank": 2 },
"type": null,
"lead": null,
"source": "datadog",
"declared_by": null,
"declared_at": "2026-07-18T09:12:44Z",
"detected_at": null,
"resolved_at": null,
"created_at": "2026-07-18T09:12:44Z",
"updated_at": "2026-07-18T09:12:44Z",
"custom_fields": {},
"visibility": "public"
}
}

Update it with PATCH /api/v1/incidents/:id. You can change name, summary, status_id, severity_id, incident_type_id, or assign a lead with lead_id. Moving the incident to a status in the closed stage resolves it, and moving a closed incident back to an active-stage status reopens it.

Terminal window
curl -X PATCH https://app.firefight.app/api/v1/incidents/0d9b2c1e-7f3a-4b8e-9c5d-2a6e8f1b4d70 \
-H "Authorization: Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA" \
-H "Content-Type: application/json" \
-d '{ "status_id": "f0e1d2c3-b4a5-4968-8776-655443322110", "summary": "Rolled back the 14:02 deploy. Latency recovered." }'

The response is 200 OK with the updated incident, including its resolved_at timestamp.