Webhooks

Receive signed HTTP POST requests for every change event and pipe them into any system.

Org Webhooks (Business plan) let you receive a signed HTTP POST to your own endpoint every time a change is confirmed in your organization. Configure them in Dashboard → Webhooks.


Setup

Go to Dashboard → Webhooks and click New Webhook. Requires a Business plan.

Field Required Notes
Name Yes Label shown in the dashboard
Endpoint URL Yes Publicly reachable HTTPS URL
Active Toggle delivery on/off without deleting
Filter event types Leave empty to receive all events

localhost won't work in production. Use ngrok or a similar tunnel for local testing.

The payload

ArtistGuard POSTs application/json:

{
  "id": "chg_abc123",
  "organization_id": "org_xyz",
  "monitored_artist_id": "art_...",
  "artist_name": "Sophie",
  "change_type": "TRACKS_WENT_OFFLINE",
  "severity": "critical",
  "summary": "2 track(s) on \"Album Name\" went offline",
  "confirmed": true,
  "detected_at": "2026-03-07T10:32:00Z",
  "confirmed_at": "2026-03-07T10:37:00Z",
  "payload": { }
}

severity is always "critical", "warning", or "info".

Request headers

Header Value
Content-Type application/json
X-ArtistGuard-Signature sha256=<hmac>
X-ArtistGuard-Event change

Signature verification

The signature is HMAC-SHA256 of the raw JSON body keyed with your signing secret. Always verify it before processing.

Node.js

import { createHmac } from 'crypto'

app.post('/webhook', express.json(), (req, res) => {
  const sig = req.headers['x-artistguard-signature']
  const expected = 'sha256=' + createHmac('sha256', process.env.SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex')

  if (sig !== expected) return res.status(401).end()

  const { artist_name, change_type, summary } = req.body
  console.log(`[${change_type}] ${artist_name}: ${summary}`)
  res.sendStatus(200)
})

Python

import hmac, hashlib, json

def verify(body: bytes, secret: str, header: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)

Rotating the secret

Click Rotate on a webhook card in the dashboard. The new secret is shown once, so copy it before closing the modal. The old secret is invalidated immediately.

Responding

Return any 2xx within 10 seconds. There are no automatic retries. Queue events on receipt and process asynchronously if your handler might be slow.


All change_type values

Availability

Value Severity What happened
RELEASE_WENT_OFFLINE critical Entire release is no longer playable
RELEASE_CAME_ONLINE info Release is playable again
TRACKS_WENT_OFFLINE critical Multiple tracks on a release went offline (grouped)
TRACKS_CAME_ONLINE info Multiple tracks came back online (grouped)
TRACK_WENT_OFFLINE critical A single track became unplayable
TRACK_CAME_ONLINE info A single track is playable again

Releases & Tracks

Value Severity What happened
NEW_RELEASE_DETECTED warning New album, EP, or single appeared
NEW_TRACKS_DETECTED warning Multiple tracks added to a release (grouped)
NEW_TRACK_DETECTED info A single track added to an existing release
RELEASE_LABEL_CHANGED warning Label name changed on a release
RELEASE_ARTISTS_CHANGED warning Artist credits on a release changed
RELEASE_IMAGE_CHANGED info Cover art updated

Track metadata (grouped)

Grouped changes are emitted when the same change affects multiple tracks in one monitoring cycle, one event per release instead of one per track.

Value Severity What happened
TRACKS_ARTISTS_CHANGED warning Artist credits changed on multiple tracks
TRACKS_ISRC_CHANGED warning ISRC replaced on multiple tracks
TRACKS_EXPLICIT_CHANGED info Explicit flag changed on multiple tracks

Track metadata (per-track)

Value Severity What happened
TRACK_ARTISTS_CHANGED warning Artist credits changed on a single track
TRACK_ISRC_CHANGED warning ISRC replaced on a single track
TRACK_EXPLICIT_CHANGED info Explicit flag toggled on a single track

Artist stats

Value Severity What happened
FOLLOWERS_CHANGED info Follower count shifted
MONTHLY_LISTENERS_CHANGED info Monthly listeners shifted
WORLD_RANK_CHANGED info World rank moved
ARTIST_IMAGE_CHANGED info Artist profile picture updated
ARTIST_VERIFIED_CHANGED info Verified badge added or removed
ARTIST_BIOGRAPHY_CHANGED info Biography edited
TOP_CITIES_CHANGED info Top listener cities shifted
TOP_TRACKS_CHANGED info Top tracks ranking changed

Testing locally

Your endpoint must be publicly reachable. Two easy options for local development:

ngrok

ngrok http 3000

Cloudflare Tunnel (free, no account required for quick tunnels)

cloudflared tunnel --url http://localhost:3000

Both give you a public HTTPS URL to paste as the endpoint. Use the Test button on a webhook card to send a signed delivery immediately. Pick an event type to preview the sample payload before firing.

Replace with a real URL before going to production.