AlphornAlphorn Docs

Integrations

Send alerts to Alphorn from Grafana, Prometheus Alertmanager, Uptime Kuma, GitHub Actions, Jenkins, Home Assistant, Sonarr, and other tools via webhooks.

Alphorn accepts standard HTTP webhooks, so it works with any tool that can send an HTTP request. This page shows how to connect popular services to Alphorn as notification sources.

For channel destinations (where Alphorn delivers notifications), see Channels.

Alphorn picks the title and message out of common JSON fields automatically. For tools whose payload doesn't fit that, the Create webhook form has built-in source presets (GitHub, Grafana, Prometheus Alertmanager, Sentry, Stripe) under Advanced: field templates, and you can write your own field templates for anything else.

Monitoring

Grafana

Grafana supports webhook contact points natively. Send alerts directly to Alphorn.

  1. In Grafana, go to Alerting → Contact points
  2. Click Add contact point
  3. Select Webhook as the type
  4. Set the URL to your Alphorn webhook URL
  5. Set method to POST
  6. Under Optional Webhook settings, set Authorization Header - Scheme to Bearer and Authorization Header - Credentials to your Alphorn API key

Grafana's default webhook payload has top-level title and message fields, which Alphorn picks up automatically, so no custom body is needed. To also tag notifications with the alert state, pick the Grafana source preset when creating the webhook. It adds the tags grafana,<state> (for example grafana,alerting or grafana,ok).

Prometheus Alertmanager

When creating the Alphorn webhook, pick the Prometheus Alertmanager source preset. Alertmanager's payload has no top-level title or message field, so without the preset the notification message is the raw JSON.

Then configure a webhook receiver in your Alertmanager config:

alertmanager.yml
receivers:
  - name: alphorn
    webhook_configs:
      - url: "https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
        send_resolved: true
        http_config:
          authorization:
            credentials: "alp_..." # your Alphorn API key

Uptime Kuma

See the dedicated Uptime Monitoring use case for setup instructions, including custom body templates for priority-based routing.

Healthchecks.io

  1. In your Healthchecks.io project, go to Integrations
  2. Add a Webhook integration
  3. Under Execute when a check goes DOWN, set the method to POST and the URL to your Alphorn webhook URL
  4. If the webhook has Require API key switched on, add a request header Authorization: Bearer alp_... with your Alphorn API key
  5. Set the request body to:
{
  "title": "$NAME is $STATUS",
  "message": "Check $CODE: $STATUS. Tags: $TAGS",
  "priority": 5,
  "tags": ["healthchecks"]
}
  1. Repeat for Execute when a check goes UP with the same method, URL, and header, but a lower priority (for example "priority": 2), so recoveries don't page anyone

Gatus

Gatus has native webhook alerting via its custom provider:

gatus-config.yaml
alerting:
  custom:
    url: "https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
    method: POST
    headers:
      Authorization: "Bearer ${ALPHORN_API_KEY}"
    body: |
      {
        "title": "[ENDPOINT_NAME] is [ALERT_TRIGGERED_OR_RESOLVED]",
        "message": "[ENDPOINT_GROUP] - [ENDPOINT_URL]",
        "priority": 4,
        "tags": ["gatus", "uptime"]
      }

endpoints:
  - name: website
    url: "https://example.com"
    conditions:
      - "[STATUS] == 200"
    alerts:
      - type: custom # without this, the custom provider never fires
        send-on-resolved: true

[ALERT_TRIGGERED_OR_RESOLVED] becomes TRIGGERED or RESOLVED, so the title tells you which one it is. The body is the same for both, so the priority can't change between them; it's set to 4 as a compromise. If you want resolved alerts to stay quiet, route on the title or drop send-on-resolved.

CI/CD

GitHub Actions

See the CI/CD Pipelines use case for full GitHub Actions and GitLab CI examples.

GitLab CI

See the CI/CD Pipelines use case.

Jenkins

Add a post-build step using curl. Store the API key as a Secret text credential (here with the ID alphorn-api-key) and set both variables in an environment block:

Jenkinsfile
pipeline {
  agent any
  environment {
    ALPHORN_WEBHOOK = 'https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT'
    ALPHORN_API_KEY = credentials('alphorn-api-key')
  }
  stages {
    stage('Build') {
      steps { sh 'make build' }
    }
  }
  post {
    failure {
      sh '''
        curl -fsS -X POST "$ALPHORN_WEBHOOK" \
          -H "Authorization: Bearer $ALPHORN_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "title": "Jenkins build failed",
            "message": "'"$JOB_NAME"' #'"$BUILD_NUMBER"' - '"$BUILD_URL"'",
            "priority": 5,
            "tags": ["ci", "jenkins", "failure"]
          }'
      '''
    }
  }
}

Infrastructure

Docker / Watchtower

Watchtower can send webhook notifications when containers are updated:

docker-compose.yml
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_NOTIFICATION_URL: "generic://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT?template=json&@Authorization=Bearer%20alp_..."

This is a shoutrrr generic webhook URL (generic:// uses HTTPS by default). Don't use the generic+https:// shortcut form here: it forwards all query parameters to the target, so template and @ headers would have no effect. template=json sends a JSON body with title and message, and query parameters starting with @ are sent as request headers, so @Authorization=Bearer%20alp_... carries your Alphorn API key (%20 is the space).

Ansible

Send notifications from Ansible playbooks using the uri module:

playbook.yml
- name: Notify Alphorn
  uri:
    url: "{{ alphorn_webhook }}"
    method: POST
    headers:
      Authorization: "Bearer {{ alphorn_api_key }}"
    status_code: [200, 201] # Alphorn returns 201 Created
    body_format: json
    body:
      title: "Playbook completed: {{ ansible_play_name }}"
      message: "Deployed to {{ inventory_hostname }}"
      priority: 2
      tags:
        - ansible
        - deploy

Terraform

Use a null_resource with a local-exec provisioner. The timestamp() trigger replaces the resource on every apply; without it, the provisioner runs only once, on first creation. ALPHORN_WEBHOOK and ALPHORN_API_KEY must be exported in the shell that runs terraform apply:

main.tf
resource "null_resource" "notify" {
  depends_on = [aws_instance.web]

  triggers = {
    always_run = timestamp()
  }

  provisioner "local-exec" {
    command = <<EOT
      curl -fsS -X POST "$ALPHORN_WEBHOOK" \
        -H "Authorization: Bearer $ALPHORN_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"title":"Infrastructure updated","message":"Terraform apply completed","priority":2,"tags":["terraform","infra"]}'
    EOT
  }
}

Home Automation

Home Assistant

Use the RESTful notification integration:

configuration.yaml
notify:
  - name: alphorn
    platform: rest
    resource: "https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
    method: POST_JSON # send the body as JSON (plain POST sends form data)
    title_param_name: title
    message_param_name: message
    headers:
      Authorization: !secret alphorn_authorization # "Bearer alp_..." in secrets.yaml
    data:
      tags:
        - homeassistant

Home Assistant may send data values as strings, and Alphorn ignores a priority that isn't a number. To set one, use the webhook's Priority template (for example a fixed 3) instead, or route by tags.

Then use it in automations:

automation:
  - trigger:
      platform: state
      entity_id: binary_sensor.front_door
      to: "on"
    action:
      service: notify.alphorn
      data:
        title: "Front door opened"
        message: "Front door opened at {{ now().strftime('%H:%M') }}"

Node-RED

Use an HTTP Request node:

  1. Add an HTTP Request node
  2. Set method to POST
  3. Set URL to your Alphorn webhook URL
  4. Connect a Function node before it to format the payload and set the headers:
msg.payload = {
  title: "Node-RED Alert",
  message: msg.payload.toString(),
  priority: 3,
  tags: ["nodered"],
};
msg.headers = {
  "Content-Type": "application/json",
  Authorization: "Bearer " + env.get("ALPHORN_API_KEY"),
};
return msg;

Media Servers

Sonarr / Radarr / Lidarr

These tools support webhook notifications:

  1. Go to Settings → Connect
  2. Add a Webhook connection
  3. Set the URL to your Alphorn webhook URL
  4. Select which events to trigger on (grab, download, rename, etc.)

Their payload has no title or message field, so without templates the notification has no title and the message is the pretty-printed JSON (cut to 4000 characters). Add field templates when creating the webhook, for example Title {eventType}: {series.title} for Sonarr or {eventType}: {movie.title} for Radarr (check the field names against a real delivery).

If your version can't set a custom Authorization header, create this webhook with the API key switched off (No API key (URL is the secret)) and keep the URL private.

Jellyseerr

Configure a webhook notification in the Jellyseerr settings pointing to your Alphorn webhook URL, and set Authorization Header to Bearer alp_... with your Alphorn API key.

Programming Languages

Any HTTP client can send to Alphorn. See the API Reference for examples in curl, JavaScript, Python, Go, PHP, and Ruby.

Not seeing your tool?

Alphorn accepts any HTTP POST request. If a service supports webhooks, outgoing notifications, or custom HTTP integrations, it can send to Alphorn. Use the Webhook integration and point it at your Alphorn webhook URL. If the tool can send custom headers, add Authorization: Bearer <your API key>; if it can't, create the webhook with No API key (URL is the secret) and keep the URL private. Tools that can only send plain text work too: Alphorn uses the body as the message and reads the title, priority, and tags from the X-Title, X-Priority, and X-Tags headers (see Plain Text).

If you've set up an integration not listed here, open a PR to add it to this page.

On this page