Opsgenie — Ingest Setup
This guide shows how to send Opsgenie alerts to Culprit in real time using an Opsgenie Webhook integration.
Migration window: Atlassian has ended Opsgenie sales (June 2025) and ends support on April 5, 2027. Culprit keeps your alert flow working through the transition: this adapter ingests from Opsgenie today, and when you migrate to Jira Service Management, switch to the JSM Operations adapter — JSM Operations inherited Opsgenie's webhook engine, so the payload and setup are identical.
Endpoint
POST https://ingest.theculprit.ai/ingest/<tenant_id>/<service_name>/opsgenie
Replace <tenant_id> and <service_name> with the values shown on your
service's settings page.
Authentication is a Bearer header (Opsgenie webhook integrations can send custom headers):
Authorization: Bearer <ingest_token>
Setup in Opsgenie
- In Opsgenie, open Settings → Integrations.
- Click Add integration and choose Webhook.
- Give the integration a name (e.g.
Culprit). - Paste your Culprit endpoint URL into the Webhook URL field.
- Add a custom header named
Authorizationwith the valueBearer <ingest_token>. - In the action mapping, enable only "alert is created" and
"alert is closed". Other actions (acknowledge, add note, etc.) are
workflow chatter — Culprit rejects them with
400 unrecognized_payload, so leaving them enabled only produces failed deliveries in Opsgenie's log. - Tick "add alert description" so the alert description is included in the payload (Culprit uses it as the message fallback).
- Save the integration.
Getting your ingest token
- Open the Culprit dashboard → Services → select the service.
- In the Ingest token section, click Issue.
- Copy the token shown — it is displayed once. After you navigate away, only the token prefix is visible.
To rotate a compromised token, click Rotate. The previous token remains valid for the grace period shown, giving you time to update the Opsgenie webhook header without an interruption.
How Culprit maps Opsgenie webhooks
One webhook becomes one Culprit event. Only the Create and Close actions
are ingested.
| Opsgenie field | Culprit event field | Notes |
|---|---|---|
| alert.message | event_type | Falls back to opsgenie.alert |
| alert.priority | severity | P1 → CRITICAL; P2 → HIGH; P3 → MEDIUM; P4/P5 → LOW. When absent: Close → LOW, Create → MEDIUM |
| alert.message | message | Falls back to alert.description, then Opsgenie alert |
| action, alert.*, integrationName | context | action, alias, alertId, tinyId, entity, tags, integrationName, the alert's own source field, createdAt/updatedAt, and the full original body are preserved |
Other actions (Acknowledge, AddNote, AssignOwnership, ...) and
unknown shapes are rejected with 400 unrecognized_payload — they are never
vaulted. Alert state, not workflow activity, is what Culprit correlates.
Note on fidelity: Opsgenie de-duplicates alerts by alias before its webhook fires, so Culprit sees Opsgenie's alert stream, not the raw monitor signals behind it. For the highest-fidelity correlation, point your underlying monitoring tools (Prometheus, Datadog, ...) at their native Culprit adapters directly where practical.
PII in alert messages, descriptions, entities, or tags (email addresses, IP addresses, API keys) is detected and tokenized before any storage or notification. The original values are preserved encrypted and are visible only in the incident detail view after authentication.
Worked example — alert created
Opsgenie sends:
{
"action": "Create",
"integrationName": "Culprit",
"alert": {
"alertId": "052652ac-5d1c-464a-812a-7dd18bbfba8c",
"tinyId": "1810",
"alias": "checkout-db-conn-pool",
"message": "Connection pool exhausted on checkout-db",
"entity": "checkout-db-1.acme.internal",
"priority": "P1",
"tags": ["prod", "database"],
"createdAt": 1751414400000
}
}
Culprit event (before tokenization):
{
"event_type": "Connection pool exhausted on checkout-db",
"severity": "P1",
"source": "opsgenie",
"message": "Connection pool exhausted on checkout-db",
"context": {
"action": "Create",
"alias": "checkout-db-conn-pool",
"alertId": "052652ac-5d1c-464a-812a-7dd18bbfba8c",
"tinyId": "1810",
"entity": "checkout-db-1.acme.internal",
"tags": ["prod", "database"],
"integrationName": "Culprit",
"raw": { ... }
}
}
This event flows through the standard pipeline: encrypted vault storage → PII tokenization → storm check → embedding → correlation → root-cause analysis.
Successful response
{ "accepted": true, "ids": ["<vault_id>"] }
Error responses
| Status | Body | Meaning |
|---|---|---|
| 401 | { "error": "missing_auth" } | No Authorization header |
| 401 | { "error": "invalid_ingest_token" } | Token is incorrect or has been rotated/revoked |
| 400 | { "error": "unrecognized_payload" } | Body is not valid JSON, has no alert object, or the action is not Create/Close |
| 403 | { "error": "service_disabled" } | The service exists but monitoring is paused |
| 404 | { "error": "service_deleted_or_not_found" } | The service does not exist |
| 429 | { "error": "rate_limited" } | Storm protection active (sustained high volume) |