The generic webhook source
The generic webhook source accepts a POST request with a JSON body from any monitoring tool. You tell Firefight where each field lives in the payload with a configurable mapping, so one mechanism covers Datadog, Grafana, Prometheus Alertmanager, and anything else that can send JSON to a URL.
Create a source
Section titled “Create a source”Go to Settings → Alert Sources and click Add source. Give it a name, pick the Generic webhook provider, and create it. Firefight generates a unique ingest URL and a secret token for this source. Copy both from the sources table. The URL has this shape:
https://<your Firefight host>/api/v1/alerts/<endpoint-path>The endpoint path is a random identifier unique to this source. Use the exact URL shown in Settings → Alert Sources.
Authentication
Section titled “Authentication”Every request must carry the source’s secret token in one of two headers. Firefight accepts either, so use whichever your tool can set.
| Header | Format |
|---|---|
Authorization | Bearer <token> |
X-Firefight-Token | <token> |
Requests with a missing or wrong token are rejected with 401. Requests to an unknown or disabled source URL get 404.
What a request looks like
Section titled “What a request looks like”With no custom mapping, Firefight reads these top-level keys from the payload:
{ "id": "evt-8271", "title": "High error rate on checkout", "description": "5xx rate above 5% for 10 minutes", "service": "checkout", "severity": "critical", "status": "firing", "environment": "production"}Sent with curl:
curl -X POST "https://<your Firefight host>/api/v1/alerts/<endpoint-path>" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "id": "evt-8271", "title": "High error rate on checkout", "service": "checkout", "severity": "critical", "status": "firing" }'A successful request returns a JSON body like {"ok": true, "received": 1, "failed": 0}. A payload where no mapped field resolves is rejected with 422, which tells you the mapping does not fit the payload. Bodies over 512 KB are rejected, and each source is rate limited (60 alerts per minute by default), returning 429 when exceeded so well-behaved tools retry later.
Field mapping
Section titled “Field mapping”Edit the source in Settings → Alert Sources to change where each field is read from. A mapping row pairs a Firefight field with a dot-path into the JSON payload. Path segments descend into nested objects, and numeric segments index into arrays, so alerts.0.labels.severity means the severity key inside labels of the first element of the alerts array.
| Firefight field | Default path | Used for |
|---|---|---|
title | title | The alert’s display title and the incident name |
description | description | The incident summary |
service | service | Routing conditions, grouping, and catalog lookups |
severity_raw | severity | Mapped to your incident severities via the source’s severity map |
status | status | Firing or resolved. Values like resolved, ok, recovered, and closed mark the alert resolved, anything else means firing |
external_id | id | Idempotency. The same id is never ingested twice |
fingerprint | fingerprint | Identity for deduplication. Generated from other fields when absent |
team | team | Routing conditions and catalog lookups |
environment | environment | Routing conditions and catalog lookups |
The same dialog also maps the provider’s severity strings, such as critical or P1, to your workspace’s incident severities. Unmapped values fall back to the workspace default severity.
Batched alerts with a batch path
Section titled “Batched alerts with a batch path”Some tools deliver several alerts in one POST as an array. Set the Batch path on the source to the dot-path of that array, and Firefight fans the request out so each element becomes its own alert. Field paths are then resolved relative to each element, not the whole body. A batch can carry up to 100 alerts per request.
Example: Prometheus Alertmanager
Section titled “Example: Prometheus Alertmanager”Alertmanager’s webhook receiver posts a body with an alerts array:
{ "status": "firing", "alerts": [ { "status": "firing", "labels": { "alertname": "HighErrorRate", "service": "checkout", "severity": "critical" }, "annotations": { "summary": "High error rate", "description": "5xx above 5%" }, "fingerprint": "a1b2c3d4e5f6" } ]}Set the batch path to alerts and map:
| Firefight field | Path |
|---|---|
title | labels.alertname |
description | annotations.description |
service | labels.service |
severity_raw | labels.severity |
status | status |
fingerprint | fingerprint |
Alertmanager sends status: "resolved" for the same fingerprint when the alert clears, which resolves the open alert in Firefight automatically.
Example: Grafana
Section titled “Example: Grafana”Grafana’s webhook contact point (unified alerting) uses an Alertmanager-compatible shape with an alerts array, where each element carries labels, annotations, status, and fingerprint. Use the batch path alerts and the same mapping as Alertmanager above. If your alert rules put a summary in annotations, map title to annotations.summary instead of labels.alertname.
Example: Datadog
Section titled “Example: Datadog”Datadog webhooks let you define the JSON payload yourself with template variables, so the simplest setup is to emit Firefight’s default field names directly. In Datadog, create a webhook integration with a custom payload:
{ "id": "$ID", "title": "$EVENT_TITLE", "description": "$EVENT_MSG", "status": "$ALERT_TRANSITION", "severity": "$ALERT_PRIORITY", "service": "checkout"}Set the Authorization header to Bearer <token> in the webhook’s custom headers. No field mapping is needed because the payload already uses the default paths. Datadog’s $ALERT_TRANSITION renders values like Triggered and Recovered, and Recovered marks the alert resolved in Firefight. Map Datadog priorities such as P1 to your severities in the source’s severity map.
Once alerts arrive, they follow the normal pipeline. See Routing rules for what happens next, and Testing your routing to dry-run before going live.