Hoppa till innehåll
Support

Webhooks

Med webhooks får du aviseringar i realtid när något händer på ditt LabelGrid-konto. Använd webhooks för att automatisera arbetsflöden och integrera med externa system.

För utvecklare: du kan även hantera webhooks programmatiskt via API:et. Se LabelGrids API-dokumentation för endpoints och exempel.

  1. Du konfigurerar en webhook – ange en URL och vilka händelser den ska lyssna på
  2. En händelse inträffar – till exempel att en release levereras till en butik
  3. LabelGrid skickar en POST-förfrågan – din server tar emot händelsedatan
  4. Ditt system bearbetar den – automatisera arbetsflöden utifrån händelsen

  1. Klicka på din profilikon längst upp till höger
  2. Välj Webhooks i rullgardinsmenyn

  1. Klicka på Create Webhook
  2. Ange ett namn som identifierar webhooken
  3. Ange den URL där du vill ta emot aviseringar
  4. Välj vilka händelser som ska utlösa webhooken
  5. Klicka på Create

När du skapar en webhook får du en hemlig nyckel. Använd den för att verifiera att inkommande förfrågningar verkligen kommer från LabelGrid:

  • Förvara hemligheten säkert
  • Verifiera signaturen på inkommande förfrågningar
  • Generera en ny hemlighet om den röjs

Konfigurera din webhook att lyssna på de här händelserna. Händelseidentifieraren är värdet du ser i event-egenskapen i nyttolasten och i headern X-Webhook-Event:

HändelseidentifierareBeskrivning
delivery.completedUtlöses när en release har levererats till en kanal
delivery.failedUtlöses när en leverans till en kanal misslyckas
takedown.completedUtlöses när en takedown-begäran slutförs
release.review.status_changedUtlöses när granskningsstatusen för en release ändras
release.preflight.report_readyUtlöses när Preflight QC-rapporten för en release i väntläge är klar att hämta
stream_radar.flag_createdUtlöses när en Stream Radar-flagga reses, eller en löst flagga återöppnas vid en ny detektion
stream_radar.flag_resolvedUtlöses när en Stream Radar-flagga löses för att detektionerna upphörde
release.distributedUtlöses när en release distribueras
payment.statement_readyUtlöses när en avräkning är klar att visas
transcode.completedUtlöses när transkodningen av ett spårs ljud slutförs korrekt
transcode.failedUtlöses när transkodningen av ett spår misslyckas eller avslutas ofullständigt
distribution.outlet.status_changedUtlöses vid varje statusövergång i distributionen per kanal

Du kan välja flera händelser för en enda webhook, eller skapa separata webhooks för olika händelsetyper.

Du kan även läsa den här listan programmatiskt: GET /api/public/webhooks/event-types returnerar varje händelse tillsammans med ett data-schema som beskriver dess nyttolastnycklar och -typer, så att konsumenter med strikt schema kan vidga sin inkommande validering i förväg.


Webhook-listan visar:

KolumnBeskrivning
NameNamnet du gav webhooken
URLDit aviseringarna skickas
EventsAntal konfigurerade händelser
StatusAktiv eller inaktiv
Success / FailAntal lyckade och misslyckade leveranser
Last TriggeredNär webhooken senast anropades
  1. Klicka på Edit på webhookens rad
  2. Ändra namnet, URL:en eller händelserna
  3. Klicka på Save

Slå av eller på en webhooks aktiva status utan att ta bort den:

  • Aktiv – webhooken tar emot aviseringar
  • Inaktiv – webhooken är pausad, inga aviseringar skickas
  1. Klicka på Delete på webhookens rad
  2. Bekräfta borttagningen

Innan du förlitar dig på en webhook i produktion bör du testa den:

  1. Klicka på Test på din webhook
  2. LabelGrid skickar en testnyttolast till din URL
  3. Kontrollera att din endpoint tog emot och bearbetade den korrekt

Övervaka webhook-aktivitet och felsök problem:

  1. Klicka på View Logs på en webhook
  2. Se en historik över alla webhook-leveranser

Varje loggpost visar:

FältBeskrivning
Event TypeVilken händelse som utlöste leveransen
Response StatusHTTP-statuskoden från din server
DurationHur lång tid förfrågan tog
AttemptFörsöksnummer för omförsöket
TimestampNär leveransen skedde

När en händelse inträffar skickar LabelGrid en POST-förfrågan till din URL med en JSON-nyttolast:

{
"event": "delivery.completed",
"timestamp": "2026-05-05T10:00:00+00:00",
"webhook_id": "123",
"data": {
// Event-specific data
}
}

Fältet timestamp använder formatet ISO 8601. webhook_id är ID:t för din konfigurerade webhook (det matchar headern X-Webhook-Id).


Strukturen på data-objektet beror på event-typen. Alla fälttyper nedan är JSON-typer så som de serialiseras i nyttolasten.

Utlöses en gång per kanal när en releaseleverans når ett slutligt lyckat tillstånd.

{
"event": "delivery.completed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete"
}
}
FältTypBeskrivning
distro_queue_idintegerInternt kö-ID för det här leveransförsöket
release_idintegerDen release som levererades
label_idintegerSkivbolaget som äger releasen, så att du kan dirigera händelsen utan en extra uppslagning
release_catstring | nullDin katalogreferens för releasen
outlet_idinteger | nullID för målkanalen
outlet_namestring | nullLäsbart namn på kanalen (t.ex. "Spotify")
statusstringAlltid "complete" för den här händelsen

Utlöses en gång per kanal när en releaseleverans når ett slutligt misslyckat tillstånd. Samma nyttolast som delivery.completed plus ett message-fält.

{
"event": "delivery.failed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "error",
"message": "Outlet rejected the delivery: missing ISRC."
}
}
FältTypBeskrivning
statusstringEtt av error, fault, rejected, batch_exception
messagestring | nullOrsak till felet, från kanalen eller distributionspipelinen

Utlöses en gång per kanal när en takedown-begäran lyckas. Samma form som delivery.completed plus en takedown: true-flagga.

{
"event": "takedown.completed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete",
"takedown": true
}
}

Utlöses en gång per release när releasen övergår till leveranstillståndet distributed. Utlöses bara vid övergången in i distributed, inte vid efterföljande sparningar medan releasen redan är distribuerad.

{
"event": "release.distributed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"delivery_status": "distributed"
}
}

Utlöses varje gång en release byter granskningstillstånd.

{
"event": "release.review.status_changed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"previous_status": "to_review",
"new_status": "approved"
}
}
FältTypBeskrivning
previous_statusstringFöregående status. Ett av draft, to_review, approved, rejected, require_changes, audit
new_statusstringNy status. Samma uppsättning värden
review_issuesarray (valfritt)Finns bara vid övergångar till require_changes och rejected: de problem som kräver din uppmärksamhet. Vid alla andra övergångar utelämnas nyckeln, så utgå inte från att den alltid finns

Utlöses när kvalitetsrapporten från Preflight QC för en release i väntläge före granskningen är klar att hämta. Kräver tillägget Preflight QC på ditt konto.

{
"event": "release.preflight.report_ready",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"generated_at": "2026-07-07T09:58:12+00:00",
"profile": { "name": "quality_report", "version": 2 },
"counts": { "blocking": 1, "informational": 2, "requires_feedback": 1 }
}
}
FältTypBeskrivning
release_idintegerReleasen som rapporten hör till
label_idintegerSkivbolaget som äger releasen
release_catstring | nullDin katalogreferens för releasen
release_titlestring | nullReleasetiteln
generated_atstringNär kontrollerna slutfördes (ISO 8601). Matchar kvalitetsrapport-endpointens report.generated_at
profileobjectKvalitetsprofilen som antalen beräknades genom: {name, version}
countsobjectEndast aggregerade antal: {blocking, informational, requires_feedback}. Antalet requires_feedback överlappar de andra två

Utlöses när en Stream Radar-flagga reses – antingen en helt ny flagga eller en tidigare löst flagga som återöppnas vid en ny detektion. Kräver tillägget Stream Radar på ditt konto. Fältet transition skiljer de två fallen åt: published för en ny flagga, reopened för en som blev aktiv igen.

{
"event": "stream_radar.flag_created",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"flag_id": 4501,
"dsp": "spotify",
"isrc": "USRC12345678",
"release_id": 789,
"track_id": 654,
"severity": "high",
"status": "active",
"transition": "published",
"first_detected_at": "2026-07-06T00:00:00+00:00",
"last_detected_at": "2026-07-07T00:00:00+00:00",
"estimated_affected_streams": 12500,
"published_at": "2026-07-07T09:58:12+00:00",
"resolved_at": null
}
}
FältTypBeskrivning
flag_idintegerFlaggans stabila identifierare; matchar id på Stream Radar-endpointerna
dspstringPlattformen som mönstret sågs på (t.ex. spotify)
isrcstringISRC för den berörda inspelningen
release_idintegerReleasen som inspelningen hör till
track_idinteger | nullDet specifika spåret, när ISRC entydigt mappar till ett av dina spår
severitystringlow, medium eller high
statusstringactive för den här händelsen
transitionstringpublished för en ny flagga, reopened när en löst flagga blev aktiv igen
first_detected_atstring | nullNär mönstret först sågs för det här spåret och den här plattformen (ISO 8601)
last_detected_atstring | nullDen senaste detektionen (ISO 8601)
estimated_affected_streamsinteger | nullEn uppskattning av hur många streams som är inblandade
published_atstringNär flaggan först restes för dig (ISO 8601)
resolved_atstring | nullnull medan flaggan är aktiv

Utlöses när en Stream Radar-flagga löses för att detektionerna upphörde. Kräver tillägget Stream Radar. Samma fält som stream_radar.flag_created (utan transition), med status satt till resolved och resolved_at ifyllt.

{
"event": "stream_radar.flag_resolved",
"timestamp": "2026-07-14T10:00:00+00:00",
"webhook_id": "123",
"data": {
"flag_id": 4501,
"dsp": "spotify",
"isrc": "USRC12345678",
"release_id": 789,
"track_id": 654,
"severity": "high",
"status": "resolved",
"first_detected_at": "2026-07-06T00:00:00+00:00",
"last_detected_at": "2026-07-12T00:00:00+00:00",
"estimated_affected_streams": 18700,
"published_at": "2026-07-07T09:58:12+00:00",
"resolved_at": "2026-07-14T09:55:03+00:00"
}
}

Utlöses när en avräkning genereras och är klar att visas.

{
"event": "payment.statement_ready",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"payment_request_id": 1024,
"invoice_number": "INV-2026-001",
"period": "2026-04-30",
"amount": 1234.56,
"total_due_usd": 1234.56,
"currency": "USD"
}
}
FältTypBeskrivning
payment_request_idintegerInternt ID för betalningsbegäran
invoice_numberstringFakturareferens för avräkningen
periodstring | nullSlutdatum för perioden (ISO 8601-datum, YYYY-MM-DD)
amountnumberAvräkningsbelopp i currency
total_due_usdnumberAvräkningens totalsumma omräknad till USD
currencystringValutakod enligt ISO 4217 (USD som standard)

Utlöses när transkodningen av ett spårs ljud slutförs. transcode.completed utlöses vid framgång; transcode.failed utlöses när transkodningen misslyckas eller avslutas ofullständigt. Båda har samma nyttolastform.

{
"event": "transcode.completed",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"track_id": 654,
"transcoder_queue_id": 987,
"status": "complete",
"status_message": "transcode_complete",
"files": [
{ "asset_type_id": 2, "status": "complete" }
]
}
}
FältTypBeskrivning
release_idintegerReleasen som spåret hör till
label_idintegerSkivbolaget som äger releasen
track_idintegerSpåret som transkodades
transcoder_queue_idintegerInternt transkodnings-kö-ID
statusstringRå köstatus: complete, error eller incomplete
status_messagestringSäker, uppräknad orsakskod: transcode_complete, transcode_error eller transcode_incomplete
filesarrayDetaljer per fil för spåret: {asset_type_id, status} per transkodad fil

Utlöses vid varje statusövergång i distributionen per kanal (till exempel scheduled → transcoding → batched → complete), inte bara de slutliga som täcks av delivery.completed, delivery.failed och takedown.completed. Den här händelsen är pratsam med avsikt: prenumerera på den bara om du vill ha hela förloppet per kanal.

{
"event": "distribution.outlet.status_changed",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"previous_status": "transcoding",
"status": "batched"
}
}
FältTypBeskrivning
distro_queue_idintegerInternt kö-ID för den här leveransen
release_idintegerReleasen som distribueras
label_idintegerSkivbolaget som äger releasen
release_catstring | nullDin katalogreferens för releasen
outlet_idinteger | nullID för målkanalen
outlet_namestring | nullLäsbart namn på kanalen
previous_statusstring | nullDen föregående statusen; null när raden inte hade någon igenkänd föregående status
statusstringDen nya statusen

Varje webhook-leverans signeras så att du kan verifiera att den verkligen kom från LabelGrid. Verifiera alltid signaturen innan du bearbetar händelsen.

Varje POST-förfrågan från en webhook innehåller de här headrarna:

HeaderBeskrivning
X-Webhook-SignatureHMAC-SHA256 av den råa förfrågningskroppen, gemener i hex, utan algoritmprefix
X-Webhook-TimestampISO 8601-tidsstämpel för leveransen (samma värde som timestamp-egenskapen i kroppen)
X-Webhook-EventHändelseidentifierare (t.ex. delivery.completed)
X-Webhook-IdID för den webhook som tar emot leveransen
User-AgentLabelGrid-Webhooks/1.0
Content-Typeapplication/json
  • Algoritm: HMAC-SHA256
  • Kodning: gemener i hexadecimal
  • Prefix: inget – värdet är bara hex-sammandraget, inte sha256=...
  • Signerat innehåll: hela den råa JSON-förfrågningskroppen (kroppen innehåller själv tidsstämpeln som en egenskap, så tidsstämpeln signeras implicit)
  1. Läs in den råa förfrågningskroppen innan någon JSON-parsning eller omvandling. Om du serialiserar om den parsade JSON-datan kan byten skilja sig och signaturen sluta stämma.
  2. Beräkna HMAC-SHA256(raw_body, your_webhook_secret) och ta hex-sammandraget i gemener.
  3. Jämför mot X-Webhook-Signature med en jämförelse i konstant tid.
  4. (Rekommenderas) Avvisa förfrågan om X-Webhook-Timestamp är äldre än din toleranstid för replay-attacker – vi föreslår 5 minuter.
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$expected = hash_hmac('sha256', $rawBody, $webhookSecret);
if (! hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
// Reject deliveries older than 5 minutes
if (abs(time() - strtotime($timestamp)) > 300) {
http_response_code(401);
exit('Stale delivery');
}
$payload = json_decode($rawBody, true);
// ... process the event
http_response_code(200);
const crypto = require('crypto');
// Express: capture raw body BEFORE any JSON middleware
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const rawBody = req.body; // Buffer
const signature = req.header('X-Webhook-Signature') || '';
const timestamp = req.header('X-Webhook-Timestamp') || '';
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
const sigBuf = Buffer.from(signature, 'hex');
const expBuf = Buffer.from(expected, 'hex');
if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) {
return res.status(401).send('Invalid signature');
}
if (Math.abs(Date.now() - new Date(timestamp).getTime()) > 5 * 60 * 1000) {
return res.status(401).send('Stale delivery');
}
const payload = JSON.parse(rawBody.toString('utf8'));
// ... process the event
res.sendStatus(200);
});
import hmac, hashlib
from datetime import datetime, timezone
raw_body = request.get_data() # Flask: bytes, before any JSON parsing
signature = request.headers.get('X-Webhook-Signature', '')
timestamp = request.headers.get('X-Webhook-Timestamp', '')
expected = hmac.new(
webhook_secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
return ('Invalid signature', 401)
delivery_time = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
if abs((datetime.now(timezone.utc) - delivery_time).total_seconds()) > 300:
return ('Stale delivery', 401)
return ('', 200) # process the event, then ack
  • Att serialisera om kroppen innan du hashar. Ramverk som parsar JSON automatiskt (Express express.json(), Laravels standardhantering av förfrågningskroppen) förlorar de ursprungliga byten. Läs in den råa kroppen först.
  • Att använda en jämförelse som inte sker i konstant tid (==, ===). Den är sårbar för timing-attacker – använd alltid hash_equals (PHP), crypto.timingSafeEqual (Node), hmac.compare_digest (Python) eller motsvarande i ditt språk.
  • Att förvänta sig ett sha256=-prefix. Headervärdet är bara hex-sammandraget utan prefix.
  • Att hoppa över tidsstämpelkontrollen. Utan den kan en läckt signatur återanvändas hur länge som helst.

BegränsningVärde
Timeout för förfrågan10 sekunder
Maximal storlek på nyttolast64 KB
Maximalt antal webhooks per användare10

Om din endpoint inte svarar inom 10 sekunder betraktas leveransen som misslyckad och görs om.

Om din endpoint returnerar en status som inte är 2xx eller tar för lång tid, gör LabelGrid om leveransen med exponentiell backoff:

FörsökVäntan före omförsök
1 → 230 sekunder
2 → 31 minut
3 → 42 minuter
4 → 54 minuter
5 → 68 minuter
6 → 716 minuter
7 → 832 minuter
8 → 964 minuter
9 → 10128 minuter

Varje intervall innehåller 0–30 sekunders jitter. Efter 10 försök (cirka 4,5 timmars total tid) loggas leveransen som permanent misslyckad och görs inte om fler gånger.

Om en webhooks endpoint fortsätter att misslyckas — upprepade misslyckade leveranser utan någon lyckad leverans emellan — inaktiverar LabelGrid webhooken automatiskt för att sluta göra nya försök mot en endpoint som uppenbarligen inte kan ta emot händelser. Felräknaren nollställs vid varje lyckad leverans, så en enstaka hicka inaktiverar aldrig en webhook; bara ihållande, oavbrutna misslyckanden gör det.

När en webhook inaktiveras på det här sättet får dess ägare ett e-postmeddelande. E-postmeddelandet anger webhookens namn och dess endpoint-URL samt vilken typ av fel som utlöste inaktiveringen — till exempel en timeout för anslutningen eller upprepade HTTP-fel.

Att återaktivera gör du själv: åtgärda din endpoint och slå sedan på webhooken igen under Profil → Webhooks. När du återaktiverar en inaktiverad webhook nollställs dess felräknare. Webhook-listan visar den aktiva statusen och den aktuella felräknaren för varje webhook, så att du snabbt kan upptäcka en endpoint med problem.

  • Returnera ett 2xx-svar snabbt (inom 10 sekunder)
  • Bearbeta datan asynkront efter att du har kvitterat
  • Verifiera signaturen på varje förfrågan (se Verifiera webhook-signaturer)
  • Håll koll på din felräknare i webhook-listan
  • Granska leveransloggarna när du utreder uteblivna händelser

  • Skicka Slack-meddelanden när releaser går live
  • Mejla ditt team när leveranser misslyckas
  • Uppdatera interna dashboards
  • Utlös marknadsföringskampanjer när releaser distribueras
  • Uppdatera din webbplats när nytt innehåll finns tillgängligt
  • Synka status till externa projektledningsverktyg
  • Få larm direkt vid leveransfel
  • Följ distributionens framsteg i realtid
  • Bevaka ändringar i granskningsstatus

  1. Kontrollera statusen – är webhooken aktiv?
  2. Verifiera URL:en – går endpointen att nå från internet?
  3. Kontrollera händelserna – är rätt händelser valda?
  4. Granska loggarna – finns det några fel registrerade?
  1. Kontrollera din endpoint – returnerar den 200 OK?
  2. Kontrollera svarstiden – svarar den inom timeouten?
  3. Granska felmeddelandena – vad är det som misslyckas?
  4. Testa manuellt – skicka en testwebhook

Om din webhook-hemlighet har röjts:

  1. Klicka på Regenerate Secret i webhook-inställningarna
  2. Uppdatera din applikation med den nya hemligheten
  3. Den gamla hemligheten slutar gälla omedelbart

Om du har frågor om webhooks kan du kontakta vårt supportteam.

Använder du inte LabelGrid än?

Allt du just läste om finns på vår plattform.

Se vad LabelGrid kan göra →