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.
Så fungerar webhooks
Section titled “Så fungerar webhooks”- Du konfigurerar en webhook – ange en URL och vilka händelser den ska lyssna på
- En händelse inträffar – till exempel att en release levereras till en butik
- LabelGrid skickar en POST-förfrågan – din server tar emot händelsedatan
- Ditt system bearbetar den – automatisera arbetsflöden utifrån händelsen
Hitta webhooks
Section titled “Hitta webhooks”- Klicka på din profilikon längst upp till höger
- Välj Webhooks i rullgardinsmenyn
Skapa en webhook
Section titled “Skapa en webhook”- Klicka på Create Webhook
- Ange ett namn som identifierar webhooken
- Ange den URL där du vill ta emot aviseringar
- Välj vilka händelser som ska utlösa webhooken
- Klicka på Create
Webhook-hemlighet
Section titled “Webhook-hemlighet”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
Tillgängliga händelser
Section titled “Tillgängliga händelser”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ändelseidentifierare | Beskrivning |
|---|---|
delivery.completed | Utlöses när en release har levererats till en kanal |
delivery.failed | Utlöses när en leverans till en kanal misslyckas |
takedown.completed | Utlöses när en takedown-begäran slutförs |
release.review.status_changed | Utlöses när granskningsstatusen för en release ändras |
release.distributed | Utlöses när en release distribueras |
payment.statement_ready | Utlöses när en avräkning är klar att visas |
Du kan välja flera händelser för en enda webhook, eller skapa separata webhooks för olika händelsetyper.
Hantera webhooks
Section titled “Hantera webhooks”Visa dina webhooks
Section titled “Visa dina webhooks”Webhook-listan visar:
| Kolumn | Beskrivning |
|---|---|
| Name | Namnet du gav webhooken |
| URL | Dit aviseringarna skickas |
| Events | Antal konfigurerade händelser |
| Status | Aktiv eller inaktiv |
| Success / Fail | Antal lyckade och misslyckade leveranser |
| Last Triggered | När webhooken senast anropades |
Redigera en webhook
Section titled “Redigera en webhook”- Klicka på Edit på webhookens rad
- Ändra namnet, URL:en eller händelserna
- Klicka på Save
Aktivera och inaktivera
Section titled “Aktivera och inaktivera”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
Ta bort en webhook
Section titled “Ta bort en webhook”- Klicka på Delete på webhookens rad
- Bekräfta borttagningen
Testa webhooks
Section titled “Testa webhooks”Innan du förlitar dig på en webhook i produktion bör du testa den:
- Klicka på Test på din webhook
- LabelGrid skickar en testnyttolast till din URL
- Kontrollera att din endpoint tog emot och bearbetade den korrekt
Visa webhook-loggar
Section titled “Visa webhook-loggar”Övervaka webhook-aktivitet och felsök problem:
- Klicka på View Logs på en webhook
- Se en historik över alla webhook-leveranser
Loggdetaljer
Section titled “Loggdetaljer”Varje loggpost visar:
| Fält | Beskrivning |
|---|---|
| Event Type | Vilken händelse som utlöste leveransen |
| Response Status | HTTP-statuskoden från din server |
| Duration | Hur lång tid förfrågan tog |
| Attempt | Försöksnummer för omförsöket |
| Timestamp | När leveransen skedde |
Format på webhook-nyttolasten
Section titled “Format på webhook-nyttolasten”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).
Händelsenyttolaster
Section titled “Händelsenyttolaster”Strukturen på data-objektet beror på event-typen. Alla fälttyper nedan är JSON-typer så som de serialiseras i nyttolasten.
delivery.completed
Section titled “delivery.completed”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, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "complete" }}| Fält | Typ | Beskrivning |
|---|---|---|
distro_queue_id | integer | Internt kö-ID för det här leveransförsöket |
release_id | integer | Den release som levererades |
release_cat | string | null | Din katalogreferens för releasen |
outlet_id | integer | ID för målkanalen |
outlet_name | string | null | Läsbart namn på kanalen (t.ex. "Spotify") |
status | string | Alltid "complete" för den här händelsen |
delivery.failed
Section titled “delivery.failed”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, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "error", "message": "Outlet rejected the delivery: missing ISRC." }}| Fält | Typ | Beskrivning |
|---|---|---|
status | string | Ett av error, fault, rejected, batch_exception |
message | string | null | Orsak till felet, från kanalen eller distributionspipelinen |
takedown.completed
Section titled “takedown.completed”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, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "complete", "takedown": true }}release.distributed
Section titled “release.distributed”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, "release_cat": "ABC123", "release_title": "Summer EP", "delivery_status": "distributed" }}release.review.status_changed
Section titled “release.review.status_changed”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, "release_cat": "ABC123", "release_title": "Summer EP", "previous_status": "to_review", "new_status": "approved" }}| Fält | Typ | Beskrivning |
|---|---|---|
previous_status | string | Föregående status. Ett av draft, to_review, approved, rejected, require_changes, audit |
new_status | string | Ny status. Samma uppsättning värden |
payment.statement_ready
Section titled “payment.statement_ready”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ält | Typ | Beskrivning |
|---|---|---|
payment_request_id | integer | Internt ID för betalningsbegäran |
invoice_number | string | Fakturareferens för avräkningen |
period | string | null | Slutdatum för perioden (ISO 8601-datum, YYYY-MM-DD) |
amount | number | Avräkningsbelopp i currency |
total_due_usd | number | Avräkningens totalsumma omräknad till USD |
currency | string | Valutakod enligt ISO 4217 (USD som standard) |
Verifiera webhook-signaturer
Section titled “Verifiera webhook-signaturer”Varje webhook-leverans signeras så att du kan verifiera att den verkligen kom från LabelGrid. Verifiera alltid signaturen innan du bearbetar händelsen.
Request-headers
Section titled “Request-headers”Varje POST-förfrågan från en webhook innehåller de här headrarna:
| Header | Beskrivning |
|---|---|
X-Webhook-Signature | HMAC-SHA256 av den råa förfrågningskroppen, gemener i hex, utan algoritmprefix |
X-Webhook-Timestamp | ISO 8601-tidsstämpel för leveransen (samma värde som timestamp-egenskapen i kroppen) |
X-Webhook-Event | Händelseidentifierare (t.ex. delivery.completed) |
X-Webhook-Id | ID för den webhook som tar emot leveransen |
User-Agent | LabelGrid-Webhooks/1.0 |
Content-Type | application/json |
Algoritm
Section titled “Algoritm”- 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)
Så verifierar du signaturen
Section titled “Så verifierar du signaturen”- 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.
- Beräkna
HMAC-SHA256(raw_body, your_webhook_secret)och ta hex-sammandraget i gemener. - Jämför mot
X-Webhook-Signaturemed en jämförelse i konstant tid. - (Rekommenderas) Avvisa förfrågan om
X-Webhook-Timestampär äldre än din toleranstid för replay-attacker – vi föreslår 5 minuter.
PHP-exempel
Section titled “PHP-exempel”$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 minutesif (abs(time() - strtotime($timestamp)) > 300) { http_response_code(401); exit('Stale delivery');}
$payload = json_decode($rawBody, true);// ... process the eventhttp_response_code(200);Node.js-exempel
Section titled “Node.js-exempel”const crypto = require('crypto');
// Express: capture raw body BEFORE any JSON middlewareapp.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);});Python-exempel
Section titled “Python-exempel”import hmac, hashlibfrom datetime import datetime, timezone
raw_body = request.get_data() # Flask: bytes, before any JSON parsingsignature = 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 ackVanliga fallgropar
Section titled “Vanliga fallgropar”- 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 alltidhash_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änsningar och tillförlitlighet
Section titled “Begränsningar och tillförlitlighet”Begränsningar för förfrågningar
Section titled “Begränsningar för förfrågningar”| Begränsning | Värde |
|---|---|
| Timeout för förfrågan | 10 sekunder |
| Maximal storlek på nyttolast | 64 KB |
| Maximalt antal webhooks per användare | 10 |
Om din endpoint inte svarar inom 10 sekunder betraktas leveransen som misslyckad och görs om.
Schema för omförsök
Section titled “Schema för omförsök”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ök | Väntan före omförsök |
|---|---|
| 1 → 2 | 30 sekunder |
| 2 → 3 | 1 minut |
| 3 → 4 | 2 minuter |
| 4 → 5 | 4 minuter |
| 5 → 6 | 8 minuter |
| 6 → 7 | 16 minuter |
| 7 → 8 | 32 minuter |
| 8 → 9 | 64 minuter |
| 9 → 10 | 128 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.
Automatisk inaktivering
Section titled “Automatisk inaktivering”Om en webhook samlar på sig 100 misslyckade leveranser totalt inaktiveras den automatiskt. Aktivera den manuellt igen i webhook-listan när du har åtgärdat din endpoint. När du återaktiverar en inaktiverad webhook nollställs dess felräknare.
Bästa praxis för tillförlitlighet
Section titled “Bästa praxis för tillförlitlighet”- 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
Användningsfall
Section titled “Användningsfall”Automatiserade aviseringar
Section titled “Automatiserade aviseringar”- Skicka Slack-meddelanden när releaser går live
- Mejla ditt team när leveranser misslyckas
- Uppdatera interna dashboards
Automatisering av arbetsflöden
Section titled “Automatisering av arbetsflöden”- Utlös marknadsföringskampanjer när releaser distribueras
- Uppdatera din webbplats när nytt innehåll finns tillgängligt
- Synka status till externa projektledningsverktyg
Övervakning och larm
Section titled “Övervakning och larm”- Få larm direkt vid leveransfel
- Följ distributionens framsteg i realtid
- Bevaka ändringar i granskningsstatus
Felsökning
Section titled “Felsökning”Webhooken tar inte emot några händelser
Section titled “Webhooken tar inte emot några händelser”- Kontrollera statusen – är webhooken aktiv?
- Verifiera URL:en – går endpointen att nå från internet?
- Kontrollera händelserna – är rätt händelser valda?
- Granska loggarna – finns det några fel registrerade?
Hög felräknare
Section titled “Hög felräknare”- Kontrollera din endpoint – returnerar den 200 OK?
- Kontrollera svarstiden – svarar den inom timeouten?
- Granska felmeddelandena – vad är det som misslyckas?
- Testa manuellt – skicka en testwebhook
Generera en ny hemlighet
Section titled “Generera en ny hemlighet”Om din webhook-hemlighet har röjts:
- Klicka på Regenerate Secret i webhook-inställningarna
- Uppdatera din applikation med den nya hemligheten
- Den gamla hemligheten slutar gälla omedelbart
Behöver du hjälp?
Section titled “Behöver du hjälp?”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 →