ContentsWebhooks
  1. Getting started

    1. What Kryspal Media is
    2. System requirements
    3. Install with Docker
    4. First-time setup
    5. Upgrade and back up
  2. Libraries

    1. Create and manage libraries
    2. File and folder naming
    3. Flexible file layout
    4. Metadata and NFO
    5. Tags
    6. Images
    7. Network storage
    8. strm and cloud drives
    9. StrmTool settings
    10. Subtitles
    11. Intro and outro
    12. Search tips
    13. Actors and people
    14. Duplicate videos
  3. Playback

    1. Web player
    2. Third-party players
    3. Remote access
    4. Webhooks
  4. Members and devices

    1. Members
    2. Parental controls
    3. Account sync
    4. Devices and simultaneous streams
  5. Plugins

    1. Plugin center
    2. Plugins
    3. Third-party plugins
  6. Move from another server

    1. Move from Emby
    2. Move from Jellyfin
  7. Licenses and plans

    1. Compare plans
    2. PRO features in detail
    3. MAX features in detail
    4. Buy, activate and move a license
    5. Offline grace and expiry
  8. Troubleshooting

    1. Logs and reporting a problem

Webhooks

A webhook sends a message to another tool the moment something happens: playback starts, a title is marked watched, a new movie arrives. Home Assistant, Trakt and Simkl bridges, and Discord and Telegram bridges can all read it. The format is the same as Emby's webhooks, so tools made for Emby work without changes. Webhooks are free on every plan.

On this page
  1. Add a webhook
  2. Events
  3. What is sent
  4. Delivery
  5. Check the sender
  6. Example: Home Assistant

Add a webhook#

  1. Open System → Integrations → Webhook in the admin console and choose Add webhook.
  2. Give it a name and the address of the receiving tool. The address can be on your local network.
  3. Tick the events to send, and choose Send test on the list to check that the other side receives it.

You can add several webhooks. Each one has its own events, and can be limited to some members or some libraries (leave them empty for all). Example payload in the form shows what an event looks like.

Events#

The code is what the receiving tool sees in the Event field.

Code When it is sent
library.new A new title has finished scraping, so its IDs are there. The first scan of a new library sends nothing.
playback.start Playback begins, once per viewing.
playback.pause, playback.unpause Playback is paused, and continued after a pause.
playback.stop Playback ends. PlayedToCompletion says whether it was watched to the end.
item.markplayed, item.markunplayed A member marks a title watched or unwatched. Changes from account sync and from an import are not sent.
item.rate A member adds a title to the favorites or removes it. Both use this one code.

The Test button sends system.notificationtest. It ignores the switches and the event ticks.

What is sent#

Every message has Title, Date (UTC), Event and Server (Name, Id, Version, ProductName, ProductVersion). Server.Version is the Emby-compatible version number; to show Kryspal's own version, use Server.ProductVersion. Events about a member add User (Name, Id) and Item, the title in the same shape the Emby API uses. Item.ProviderIds holds the TMDB, IMDb and TVDB IDs, and is {} when there are none. Playback events also carry Session (device and address) and PlaybackInfo (PositionTicks, PlayedToCompletion).

Choose the format per webhook:

  • JSON (default): the payload is the request body, with Content-Type: application/json.
  • Form (multipart): the same payload is in a form field named data. Some older tools only accept this.

Delivery#

  • A reply with a 2xx status counts as received. The server waits up to 15 seconds.
  • A failure is tried again three times, after about 10 seconds, 1 minute and 5 minutes. A redirect counts as a failure and is not followed.
  • A reply of 410 turns the webhook off at once. A webhook that keeps failing for 24 hours is turned off too. Both show a Webhooks paused card on the overview and the reason on the webhook; switch it on again to resume.
  • Events are sent in the background and never slow playback or scanning. If the server restarts, events that were waiting are not sent.
  • The last 50 attempts of each webhook are listed under Recent deliveries, with the status and a short error code. The message itself is not stored.
  • Addresses on your local network are allowed. Link-local and cloud metadata addresses are blocked. Only http and https work.
  • An address with a key in it (?token=…) is shown with the value hidden in lists and in logs. When you edit a webhook, leave the address empty to keep it.

Check the sender#

Set a Secret if the other side should be sure a message is yours. Messages then carry three headers in the Standard Webhooks format:

Header Content
webhook-id A message ID, the same on every retry.
webhook-timestamp Unix time in seconds.
webhook-signature v1, and the base64 of HMAC-SHA256 over id.timestamp.body, using the secret as typed.

Without a secret nothing is added, as in Emby. The secret can be replaced or removed, never read back.

Example: Home Assistant#

Create an automation with a webhook trigger, then paste its address, http://<home-assistant>:8123/api/webhook/kryspal-playback, into a new webhook with the format JSON.

automation:
  - alias: Lights down when a movie starts
    triggers:
      - trigger: webhook
        webhook_id: kryspal-playback
        allowed_methods: [POST]
        local_only: true
    conditions:
      - condition: template
        value_template: "{{ trigger.json.Event == 'playback.start' and trigger.json.Item.Type == 'Movie' }}"
    actions:
      - action: light.turn_off
        target:
          entity_id: light.living_room