New Relic — Ingest Setup
This guide shows how to route New Relic alerts straight to Culprit using New Relic's workflow webhook destination.
Endpoint
POST https://ingest.theculprit.ai/ingest/<tenant_id>/<service_name>/newrelic
Replace <tenant_id> and <service_name> with the values shown on your
service's settings page.
Authentication
Requests must carry an ingest token in the Authorization header:
Authorization: Bearer <ingest_token>
New Relic workflow webhook destinations support custom headers, so the token
rides in the standard Authorization: Bearer header rather than the URL query
string.
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 shown.
To rotate a compromised token, click Rotate. The previous token remains valid for the grace period shown, giving you time to update New Relic without an interruption.
Setup in New Relic
New Relic workflow webhook payloads are user-defined Handlebars templates. You
must paste the recommended template below so Culprit receives the fields it
needs. The payload is template-driven: Culprit reads priority (the raw
New Relic priority field), not the stock template's remapped severity.
- Open Alerts → Workflows in New Relic One.
- Create or edit a workflow. Under Add destination, choose Webhook.
- Set Endpoint URL to your Culprit endpoint shown above.
- Under Custom Headers, add:
- Header:
Authorization - Value:
Bearer <ingest_token>
- Header:
- In the Payload field, replace the default content with this Handlebars template:
{ "condition_name": {{json accumulations.conditionName.[0]}},
"priority": {{json priority}},
"details": {{json issueTitle}},
"incident_id": {{json issueId}},
"incident_url": {{json issuePageUrl}},
"state": {{json state}},
"policy_name": {{json accumulations.policyName.[0]}} }
- Save the destination and enable the workflow.
How Culprit maps New Relic alerts
Field mapping
| New Relic template field | Culprit event field | Notes |
|---|---|---|
| details | message | Falls back to condition_name if details is absent |
| condition_name | event_type | The alert condition name |
| priority | severity | See severity table below |
| incident_id, incident_url, state, policy_name | context | All preserved for correlation and RCA |
Severity mapping
Culprit reads the priority field from our recommended template. The stock
New Relic template remaps HIGH to WARNING — Culprit handles both.
| priority value | Culprit severity |
|---|---|
| CRITICAL | critical |
| HIGH | high |
| MEDIUM or WARNING | warning |
| LOW | low |
| (unknown / absent) | high |
If priority is missing or unrecognized (for example a customized template that
drops the field), Culprit deliberately treats the alert as high rather than
discarding it — a misconfigured template surfaces as a noticeable incident
instead of silently going unmonitored. Keep priority in your template to get
the exact severity.
PII in any field (IP addresses, hostnames, email 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
New Relic sends (after template substitution):
{
"condition_name": "High error rate",
"priority": "CRITICAL",
"details": "High error rate on payments-service",
"incident_id": "abc-123",
"incident_url": "https://one.newrelic.com/launcher/...",
"state": "ACTIVATED",
"policy_name": "Production Alerts"
}
Culprit event (before tokenization):
{
"event_type": "High error rate",
"severity": "critical",
"source": "newrelic",
"message": "High error rate on payments-service",
"context": {
"incident_id": "abc-123",
"incident_url": "https://one.newrelic.com/launcher/...",
"state": "ACTIVATED",
"policy_name": "Production Alerts"
}
}
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, both details and condition_name are absent, or the payload does not match the expected shape |
| 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) |