Skip to main content
Dispatcharr’s Integrations feature enables event-driven automation by executing webhooks, custom scripts, or plugin actions in response to system events like channel start, recording end, or client connections.

Overview

The Integrations system supports three types of connections:
  • Webhooks - HTTP POST requests to external services
  • Custom Scripts - Execute shell scripts or binaries with event data
  • Plugin Actions - Trigger plugin actions when events occur
Each integration can subscribe to specific events and receives detailed event payloads.

Supported Events

Dispatcharr triggers integrations for these system events:
  • channel_start - Channel stream started
  • channel_stop - Channel stream stopped
  • channel_reconnect - Channel reconnected after interruption
  • channel_error - Channel encountered an error
  • channel_failover - Channel switched to backup stream
  • stream_switch - Stream source changed
  • recording_start - DVR recording started
  • recording_end - DVR recording finished
  • epg_refresh - EPG data refreshed
  • m3u_refresh - M3U playlist refreshed
  • client_connect - Client connected to stream
  • client_disconnect - Client disconnected from stream
  • login_failed - Failed login attempt
  • epg_blocked - EPG access blocked (network policy)
  • m3u_blocked - M3U access blocked (network policy)

Creating Webhook Integrations

1

Navigate to Integrations

Go to SettingsIntegrations in the Dispatcharr UI.
2

Create new integration

Click New Integration and configure:
  • Name: Descriptive name (e.g., “Discord Notifications”)
  • Type: Select Webhook
  • URL: Target endpoint (e.g., https://discord.com/api/webhooks/...)
  • Method: POST (default)
  • Headers: Optional custom headers (e.g., Authorization: Bearer token)
3

Subscribe to events

Switch to the Event Triggers tab and enable events:
☑ channel_start
☑ channel_error
☑ recording_end
4

Customize payload (optional)

In the Payload Templates tab, define custom payloads using Jinja2 templates:
{
  "content": "Channel {{ channel_name }} started streaming",
  "embeds": [
    {
      "title": "{{ event_type }}",
      "color": 3066993,
      "fields": [
        {"name": "Channel", "value": "{{ channel_name }}"},
        {"name": "Time", "value": "{{ timestamp }}"}
      ]
    }
  ]
}
5

Test and enable

Use the Test button to send a dummy payload. Enable the integration when ready.

Event Payloads

Each event delivers a JSON payload with contextual data:

Channel Events

{
  "event_type": "channel_start",
  "timestamp": "2026-03-03T12:34:56.789Z",
  "channel_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "channel_name": "CNN HD",
  "channel_number": "101",
  "stream_url": "http://provider.com/stream",
  "profile_used": "FFmpeg Transcode"
}

Client Events

{
  "event_type": "client_connect",
  "timestamp": "2026-03-03T12:34:56.789Z",
  "channel_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "channel_name": "ESPN HD",
  "client_ip": "192.168.1.100",
  "user_agent": "VLC/3.0.18",
  "connection_id": "conn_xyz123"
}

Recording Events

{
  "event_type": "recording_end",
  "timestamp": "2026-03-03T14:00:00.000Z",
  "channel_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "channel_name": "HBO HD",
  "recording_id": "rec_abc789",
  "program_title": "Game of Thrones S08E06",
  "duration_seconds": 3600,
  "file_path": "/data/recordings/game_of_thrones.mkv",
  "file_size_bytes": 5368709120
}

Refresh Events

{
  "event_type": "epg_refresh",
  "timestamp": "2026-03-03T06:00:00.000Z",
  "source_name": "XMLTV Provider",
  "source_id": 123,
  "programs_updated": 15420,
  "duration_seconds": 45
}

Custom Payload Templates

Use Jinja2 templates to transform event data for external services:

Discord Webhook

{
  "username": "Dispatcharr",
  "avatar_url": "https://dispatcharr.com/logo.png",
  "embeds": [
    {
      "title": "🎬 {{ event_type|replace('_', ' ')|title }}",
      "description": "Channel **{{ channel_name }}** ({{ channel_number }})",
      "color": {% if event_type == 'channel_error' %}15158332{% else %}3066993{% endif %},
      "timestamp": "{{ timestamp }}",
      "footer": {"text": "Dispatcharr Event System"}
    }
  ]
}

Slack Webhook

{
  "text": "Channel Update",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*{{ event_type|replace('_', ' ')|title }}*\n{{ channel_name }} (Channel {{ channel_number }})"
      }
    },
    {
      "type": "context",
      "elements": [
        {"type": "mrkdwn", "text": "Time: {{ timestamp }}"}
      ]
    }
  ]
}

Home Assistant

{
  "state": "{{ event_type }}",
  "attributes": {
    "channel_name": "{{ channel_name }}",
    "channel_number": "{{ channel_number }}",
    "timestamp": "{{ timestamp }}",
    "friendly_name": "Dispatcharr Channel Status"
  }
}
If the rendered template is valid JSON, Dispatcharr automatically sets Content-Type: application/json. Otherwise, it sends as plain text.

Custom Script Integrations

Execute shell scripts or binaries with event data passed as environment variables.

Creating Script Integration

1

Create new integration

  • Name: “Recording Processor”
  • Type: Custom Script
  • Script Path: /data/scripts/process_recording.sh
  • Working Directory: /data/scripts (optional)
2

Write your script

Event data is available via environment variables prefixed with DISPATCHARR_:
process_recording.sh
#!/bin/bash

# Event variables
EVENT_TYPE="$DISPATCHARR_EVENT_TYPE"
CHANNEL_NAME="$DISPATCHARR_CHANNEL_NAME"
FILE_PATH="$DISPATCHARR_FILE_PATH"

echo "Processing recording: $CHANNEL_NAME"
echo "File: $FILE_PATH"

# Your processing logic
ffmpeg -i "$FILE_PATH" -c:v libx265 -crf 28 "${FILE_PATH%.mkv}_compressed.mkv"
3

Make script executable

chmod +x /data/scripts/process_recording.sh
4

Subscribe to events

Enable recording_end event in the Event Triggers tab.

Available Environment Variables

All event payload keys are available as uppercase environment variables:
Event KeyEnvironment Variable
event_typeDISPATCHARR_EVENT_TYPE
channel_idDISPATCHARR_CHANNEL_ID
channel_nameDISPATCHARR_CHANNEL_NAME
timestampDISPATCHARR_TIMESTAMP
file_pathDISPATCHARR_FILE_PATH
client_ipDISPATCHARR_CLIENT_IP
Security: Script integrations run with the same permissions as Dispatcharr. Validate inputs and sanitize paths.

Plugin Event Subscriptions

Plugins can subscribe to events by specifying an events array in action definitions:
actions = [
    {
        "id": "on_recording_end",
        "label": "Process Recording",
        "events": ["recording_end"],  # Subscribe to recording_end
    },
]

def run(self, action: str, params: dict, context: dict):
    if action == "on_recording_end":
        payload = params.get("payload", {})
        file_path = payload.get("file_path")
        channel_name = payload.get("channel_name")
        
        # Custom processing
        logger = context.get("logger")
        logger.info(f"Recording finished: {channel_name} at {file_path}")
        
        return {"status": "processed"}
See the Plugin System guide for complete plugin documentation.

Testing Integrations

Before going live, test integrations with dummy payloads:
1

Navigate to integration

Open the integration settings page.
2

Click Test

The Test button sends a sample payload for each enabled event.
3

Check delivery logs

View recent delivery attempts in the Logs section:
  • Status: Success or Failed
  • Request: Payload sent
  • Response: Server response (webhooks only)
  • Error: Error message if failed

Delivery Logs

Dispatcharr records all integration executions:
{
  "subscription_id": 42,
  "status": "success",
  "timestamp": "2026-03-03T12:34:56.789Z",
  "request_payload": { ... },
  "response_payload": {
    "status_code": 200,
    "body": "OK"
  },
  "error_message": null
}
Logs are stored in the database. Configure retention policies via the Integrations settings.

Use Cases

Post-Processing Recordings

Trigger scripts to compress, transcode, or upload recordings:
#!/bin/bash
# Convert to H.265 and upload
ffmpeg -i "$DISPATCHARR_FILE_PATH" -c:v libx265 -crf 28 compressed.mkv
rclone copy compressed.mkv remote:recordings/

Channel Status Monitoring

Send alerts to Discord when channels fail:
{
  "content": "⚠️ Channel Error",
  "embeds": [{
    "title": "{{ channel_name }}",
    "description": "Channel {{ channel_number }} encountered an error",
    "color": 15158332,
    "fields": [
      {"name": "Error", "value": "{{ error_message }}"},
      {"name": "Time", "value": "{{ timestamp }}"}
    ]
  }]
}

Home Automation

Update smart home systems when recordings finish:
#!/bin/bash
# Turn off living room lights when recording ends
curl -X POST http://homeassistant.local:8123/api/services/light/turn_off \
  -H "Authorization: Bearer $HA_TOKEN" \
  -d '{"entity_id": "light.living_room"}'

Multi-Service Notifications

Chain webhooks to notify multiple platforms:
  • Discord for admin alerts
  • Slack for team notifications
  • SMS via Twilio for critical errors
  • Email for recording summaries

Troubleshooting

Check authentication headers. Some services require Authorization headers or API keys.
Verify:
  • Script has executable permissions (chmod +x)
  • Script path is absolute
  • Script shebang is correct (#!/bin/bash)
  • Check Docker logs for error messages
Jinja2 templates must be valid syntax. Check:
  • Quotes are properly escaped
  • Variables exist in payload
  • JSON structure is valid
Ensure:
  • Integration is enabled
  • Event subscriptions are checked
  • Event is actually occurring (check System Events log)

Reference Implementation

See the integrations source code:
  • Models: apps/connect/models.py:1
  • Event Handler: apps/connect/utils.py:17
  • Webhook Handler: apps/connect/handlers/webhook.py
  • Script Handler: apps/connect/handlers/script.py