Webhooks

Beta: Webhooks are functional but still in beta. The design of this feature may change in the future.

A webhook lets Songfish notify your own server the moment a setlist is saved. Instead of polling the API on a timer, you register a URL and Songfish sends it a small message whenever setlist data changes, so you can react right away, for example to post a now-playing update to social media.

When a webhook fires

Songfish sends a webhook every time an editor saves a setlist in the admin. That is the only action that triggers a webhook today. Adding a show, editing a venue, or other changes do not send one. Note that saving an older setlist fires a webhook too, so your consumer should decide for itself whether a given show is one it cares about (see the example below).

What Songfish sends

The webhook is an HTTP POST to the URL you registered. The body is a small JSON object that contains only the show's ID:

POST <your registered URL>
Content-Type: application/json

{"show_id": 1726619443}

That is the entire payload, a single show_id field. The message intentionally carries no setlist details. Its job is to tell you which show changed; you then fetch the details you need from the public API (next section). This keeps the notification tiny and always current.

Getting the setlist details

When you receive a webhook, call the public API with the show_id to get the full setlist as JSON:

GET https://kglw.net/api/v2/setlists/show_id/1726619443.json

The public API needs no key or token. It is rate limited to 60 requests per minute per IP address; requests beyond that receive an HTTP 429 response. See the API documentation for the full response format and other lookups (for example /api/v2/shows/show_id/1726619443.json for show details, or /api/v2/links/show_id/1726619443.json for media links).

Delivery behavior you should plan for

  • Fire and forget. Songfish sends the POST once and does not retry. If your endpoint is down or slow when a setlist is saved, that notification is missed, so keep your endpoint highly available and return a response quickly.
  • Respond fast. Do the real work (calling the API, posting to your service) after you have accepted the request, not while Songfish is waiting on the connection.
  • No signature. The request is sent with only a Content-Type: application/json header. It does not include a shared secret or signature, so you cannot cryptographically prove the request came from Songfish. Two practical safeguards: register a long, hard to guess URL, and treat the show_id only as a hint, confirming everything you act on against the public API. The payload itself contains no private data, only a numeric ID.
  • All active endpoints receive every webhook. There is no per event or per show subscription; each registered, active URL gets the same show_id notification.

Registering a webhook

Webhooks are managed in the admin under Settings → Webhooks (/site/webhooks.php). Requirements and steps:

  • Your install must be on the Platinum plan, and you must be a superuser to manage webhook endpoints.
  • Add an endpoint with its URL (must be a full URL with a path) and an optional note describing what it is for, then set it to enabled.
  • Turn on the global Enable/Disable Webhooks switch. Webhooks stay disabled until at least one active endpoint exists, and the switch turns itself back off if you remove your last active endpoint.

End to end example

A minimal consumer that posts a message when the most recent show is updated. It accepts the webhook, fetches the setlist from the API, and decides whether to act:

# Your server receives:  POST /songfish-hook   {"show_id": 1726619443}

import requests

def handle_webhook(request):
    show_id = request.json["show_id"]

    # Fetch the full setlist from the public API
    url = "https://kglw.net/api/v2/setlists/show_id/%s.json" % show_id
    setlist = requests.get(url, timeout=10).json()

    # Only act on the most recent show, so edits to older
    # setlists do not trigger a post
    if is_most_recent(setlist):
        post_to_mastodon(setlist)

    return "ok", 200

This is exactly the pattern behind community bots such as a Mastodon "now playing" account: the webhook wakes the bot, the API provides the songs, and the bot decides what to publish.