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.distributedUtlöses när en release distribueras
payment.statement_readyUtlö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.


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,
"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
release_catstring | nullDin katalogreferens för releasen
outlet_idintegerID 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,
"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,
"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,
"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,
"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

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)

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 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.

  • 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 →