Integration setup
Connect your monitoring and notification tools to adoe. Each monitoring tool sends alerts to a webhook URL. adoe turns every alert into one standard format, with a service, an environment, a severity and a signal (the type of problem).
Prefer a guided setup? The onboarding steps in the dashboard connect each tool and create its webhook URL. This page describes the same setup, for reference and for scripted deployments.
How webhook URLs work
Every alert source has its own URL. The last part of the URL is a token:
https://<your-adoe-host>/webhooks/{source}/{token}
- The token identifies your organization and authenticates the request. Your tool does not need to send an extra header.
- Create the token on the Integrations page, on the Webhooks tab. You need the admin or editor role.
- Copy the full URL from that tab. It includes your host and the token.
- Generating a new token replaces the old one. Update your tools when you do this.
- A request with an unknown token gets a
401response.
The sources are sensu, splunk, pagerduty, grafana, uptime-com and railway.
Sensu Go
1. Create the handler
Create a pipe handler that forwards Sensu events to your adoe webhook URL. Replace the URL with the one from the dashboard.
# adoe-handler.yml (apply with: sensuctl create -f adoe-handler.yml)
type: Handler
api_version: core/v2
metadata:
name: adoe
namespace: default
spec:
type: pipe
command: >
curl -s -X POST
-H "Content-Type: application/json"
-d @-
https://<your-adoe-host>/webhooks/sensu/<your-token>
timeout: 30
filters:
- is_incident
Then add the handler to the checks you want adoe to see.
2. Fields adoe reads
| Sensu field | adoe field | Notes |
|---|---|---|
entity.labels.service | service | If the label is missing, adoe uses entity.name. |
entity.labels.environment or entity.labels.env | env | If both labels are missing, adoe uses entity.namespace. |
check.name | signal | For example cpu_high. |
check.status | severity | 0 (OK) becomes info, 1 becomes warning, 2 becomes critical. Any other value becomes warning. |
check.output | check_output | Stored with the alert as metadata. |
entity.name | host | Stored as metadata. SOPs can use it in templates. |
adoe does not read a severity label. Severity always comes from check.status. Add service and environment labels to your Sensu entities, so adoe can match each alert to the right SOP.
To let adoe read your check definitions, also connect the Sensu API on the Integrations page.
Splunk
1. Create a webhook alert action
In Splunk, open Settings, then Searches, Reports and Alerts. Create or edit a saved search. Then:
- Under Trigger Actions, choose Add Actions, then Webhook.
- Set the URL to your adoe webhook URL:
https://<your-adoe-host>/webhooks/splunk/<your-token>.
You do not need an Authorization header. The token in the URL authenticates the request.
2. Fields adoe reads
adoe reads these fields from the top level of the JSON body. It does not read them from the result object.
| Field | If it is missing | Example |
|---|---|---|
search_name | Required. A request without it is rejected. | Alert - api-backend - CPU high - prod |
service | Parsed from search_name | api-backend |
environment | Parsed from search_name | prod |
signal | Parsed from search_name | cpu_high |
severity | Set to warning | Must be critical, warning or info |
adoe also stores result.host as the alert's host. TODO(owner): confirm how customers add top-level service, environment, severity and signal fields to Splunk's webhook payload
3. Name your saved searches so adoe can parse them
When the fields are missing, adoe reads them from the saved search name. Use this pattern:
Alert - <service> - <signal words> - <environment>
- Service: the word after
Alert -. - Environment: the first of
prod,production,staging,stage,dev,development,qaortestfound anywhere in the name. - Signal: one of these phrases. "CPU high" or "CPU spike" gives
cpu_high. "Memory high" givesmemory_high. "Disk full" givesdisk_full. "Error rate" giveserror_rate_high. "Latency high" giveslatency_high. "500 error" giveshttp_5xx. Any other name givessplunk_alert.
Word order matters. "CPU high" gives cpu_high, but "High CPU" gives splunk_alert.
4. Example saved search
Save this search as Alert - api-backend - CPU high - prod. adoe then reads the service, signal and environment from its name.
index=metrics host=api-backend-* earliest=-5m
| stats avg(cpu_usage) as avg_cpu by host
| where avg_cpu > 90
To let adoe read saved search definitions and recent events, also connect the Splunk API on the Integrations page.
PagerDuty
1. Create a V3 webhook subscription
- Go to Services, then Service Directory, and select the service.
- Open the Integrations tab. Under Generic Webhooks (V3), choose Add a webhook.
- Set the webhook URL to
https://<your-adoe-host>/webhooks/pagerduty/<your-token>. Set the scope type to Service. - Select the
incident.triggeredandincident.resolvedevent types.
2. Add the signing secret (optional)
After you create the subscription, PagerDuty shows a signing secret. Paste it into the PagerDuty card on the Webhooks tab of the Integrations page. Each webhook token has its own secret.
adoe then checks the X-PagerDuty-Signature header on every request. This is an HMAC-SHA256 signature: a hash of the request body made with the shared secret. A missing or wrong signature gets a 401 response. If you do not set a secret, adoe skips this check.
The same card has a Send Test Alert button. It sends a test event through your webhook, signed with your secret if you set one.
3. Events adoe handles
incident.triggeredcreates an alert and starts processing it.incident.resolvedresolves every open alert linked to that PagerDuty incident.- adoe accepts other event types and ignores them.
adoe accepts both the V3 format (an event object) and the older V2 format (a messages list).
4. Fields adoe reads
| PagerDuty field | adoe field | Notes |
|---|---|---|
Service name (service.summary in V3, service.name in V2) | service | In V2, a service custom field takes priority. |
title | env | adoe looks for prod, production, staging, dev or qa in the title, then in the service name. In V2, an environment custom field takes priority. |
title | signal | A Sensu-style title such as check_name/host gives the check name. Other titles become lower case with underscores: "High CPU on api-backend" becomes high_cpu_on_api_backend. |
urgency | severity | high becomes critical. low becomes warning. |
To import past incidents and keep them in sync, also connect the PagerDuty API on the Integrations page.
Grafana
1. Add a webhook contact point
- In Grafana, go to Alerting, then Contact points, and add a contact point.
- Choose the Webhook integration.
- Set the URL to
https://<your-adoe-host>/webhooks/grafana/<your-token>.
Firing alerts start processing in adoe. A resolved notification closes the matching open alert. The webhook accepts any payload in the Alertmanager shape: an alerts list whose entries carry labels, annotations and status.
2. Labels adoe reads
| Label | adoe field | Notes |
|---|---|---|
alertname | signal | Lower case, with words joined by underscores. |
service, or else app, namespace or job | service | |
env, or else environment or stage | env | production becomes prod. |
severity | severity | critical, error, page, high, p1 and p2 become critical. info, low, none and p4 become info. Anything else becomes warning. |
instance, or else host or pod | host | adoe removes the port from instance. |
3. Connect the Grafana API
Also connect Grafana on the Integrations page. adoe uses the API to poll for firing alerts, read metrics during an investigation, and verify a fix. If an SOP is verified by a metric and Grafana is not connected, adoe will not run that SOP on its own. It recommends the SOP to a person instead.
Uptime.com
In Uptime.com, add a custom postback URL under Integrations. Use https://<your-adoe-host>/webhooks/uptime-com/<your-token>.
- Only
alert_raisedevents create alerts. adoe accepts other events and ignores them. - The service is the Uptime.com check name, or else the device name.
- The signal is
uptime_<check type>_<state>, for exampleuptime_http_down. - A check that is down gives
critical. A check that is up givesinfo.
Railway
In Railway, open Project Settings, then Webhooks, and add a webhook. Use https://<your-adoe-host>/webhooks/railway/<your-token>.
- Events whose type starts with
Deployment.,Volume.,CPU.orRAM.create alerts. adoe acknowledges other events and ignores them. - The signal is the event type in lower case with underscores.
Deployment.failedbecomesdeployment_failed. - The service is the Railway service name, or else the project name. The environment is the Railway environment name.
Deployment.failedandDeployment.crashedarecriticalunless the event sets its own severity.
Slack
adoe posts each alert to a Slack thread and updates it as work progresses. People can approve actions from Slack and use the /adoe command.
- Create a Slack app at
api.slack.com/apps. Give the bot these scopes:chat:write,channels:history,groups:historyandchannels:read. - Install the app to your workspace. Invite the bot to your alert channel.
- On the adoe Integrations page, open Slack. Paste the bot token (it starts with
xoxb-) and the app's signing secret. - In the Slack app settings, point these URLs at your adoe host:
- Interactivity request URL:
/api/slack/interactions - Slash command URL:
/api/slack/commands - Event subscriptions URL:
/api/slack/events
- Interactivity request URL:
adoe uses the signing secret to verify every button click, command and event from Slack.
Semaphore CI
Semaphore adds recent deployment context to alerts. adoe can then tell whether a deploy caused the alert. It looks for pipelines in the hour before the alert.
Semaphore is configured with environment variables on the adoe server, not in the dashboard. TODO(owner): how hosted customers connect Semaphore
1. Get your API token
In Semaphore CI, open Settings, then API Tokens, and create a token with read access. Then set:
SEMAPHORE_API_TOKEN=<your-api-token>
SEMAPHORE_ORG_URL=https://your-org.semaphoreci.com
2. Map services to projects
adoe finds a project on its own when its name exactly matches the service name in the alert. When the names differ, map them. First list your projects and their IDs:
curl -H "Authorization: Token <your-api-token>" \
https://your-org.semaphoreci.com/api/v1alpha/projects \
| jq '.[] | {name: .metadata.name, id: .metadata.id}'
Then map each service name to a project ID:
SEMAPHORE_PROJECT_MAP={"api-backend": "proj-abc123", "web-frontend": "proj-def456"}
Ready to test a connection? The API and webhook reference has curl payloads that send a test alert to each webhook.