Under Inställningar → Webhooks lägger du till den URL som händelserna ska skickas till. Du får en hemlighet tillbaka. Den används för att verifiera signaturen och ska förvaras som ett lösenord.
Ett system kan också anmäla sig själv med en API-nyckel, utan att någon öppnar kontrollpanelen. Det är en sådan integration som du inte själv skrev som ansluter sig: den får din nyckel och registrerar sin egen adress.
Lista slutpunkter
/ v1/ api/ webhooksFöretagets slutpunkter, även de som har skapats i kontrollpanelen, var och en med sin hemlighet och utfallet av den senaste leveransen.
curl https://api.kuvert.dk/v1/api/webhooks \
-H "Authorization: Bearer $KUVERT_API_KEY"200 OKJSON{
"endpoints": [
{
"id": "weh_5e8a1c3f7b9d42e6a0c4f8b2d6e1a3c9",
"url": "https://dit-system.dk/kuvert",
"events": [
"giftcard.issued",
"giftcard.redeemed"
],
"status": "active",
"secret": "whsec_docs-example-not-a-real-secret",
"lastDeliveryAt": "2026-09-29T09:12:44.000Z",
"lastDeliveryOk": true,
"lastDeliveryDetail": null,
"consecutiveFailures": 0,
"createdAt": "2026-09-01T07:30:00.000Z"
}
]
}Svarsfält
Slutpunkterna ligger under endpoints. Var och en har de här fälten:
idstring- Slutpunktens id (
weh_…). urlstring- Adressen som händelserna skickas till.
eventsstring[]- Händelserna som slutpunkten prenumererar på. En tom lista betyder alla.
status"active" | "disabled"- Bara
activefår leveranser. secretstring- Hemligheten (
whsec_…) som signaturen beräknas med. lastDeliveryAtstring | null- När en leverans senast försöktes.
nullom inget någonsin skickats. lastDeliveryOkboolean | null- Om den senaste leveransen fick 2xx.
nullbetyder aldrig försökt och inte misslyckad. lastDeliveryDetailstring | null- Varför den senaste misslyckades: en HTTP-status eller ett transportfel.
nullnär den lyckades. consecutiveFailuresinteger- Misslyckade leveranser i rad. Den första som lyckas nollställer talet.
createdAtstring- När slutpunkten skapades.
Statuskoder
200
Listan, eventuellt tom.
Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.
Används ofta tillsammans med
Lägg till en slutpunkt
/ v1/ api/ webhooksRegistrerar en adress och svarar med slutpunkten och dess hemlighet. Den får leveranser direkt.
curl -X POST https://api.kuvert.dk/v1/api/webhooks \
-H "Authorization: Bearer $KUVERT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://dit-system.dk/kuvert",
"events": [
"giftcard.issued",
"giftcard.redeemed"
]
}'201 CreatedJSON{
"endpoint": {
"id": "weh_5e8a1c3f7b9d42e6a0c4f8b2d6e1a3c9",
"url": "https://dit-system.dk/kuvert",
"events": [
"giftcard.issued",
"giftcard.redeemed"
],
"status": "active",
"secret": "whsec_docs-example-not-a-real-secret",
"lastDeliveryAt": null,
"lastDeliveryOk": null,
"lastDeliveryDetail": null,
"consecutiveFailures": 0,
"createdAt": "2026-09-29T09:00:00.000Z"
}
}Body
urlstringObligatorisk- En publik https-adress, högst 2048 tecken. Interna och lokala adresser avvisas.
eventsstring[]Obligatorisk- Händelserna som ska skickas. En tom lista betyder alla, även de som tillkommer senare.
Svarsfält
Slutpunkten ligger under endpoint, med samma fält som vid Lista slutpunkter.
Statuskoder
201
Slutpunkten är skapad.
400
invalid_webhook_endpointBodyn stämmer inte: adressen är inte en publik https-adress, eller en händelse finns inte.
Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.
Används ofta tillsammans med
Ändra en slutpunkt
/ v1/ api/ webhooksÄndrar adress, händelser eller status. Slutpunktens id står i bodyn, inte i sökvägen. Skicka bara de fält du vill ändra.
curl -X PATCH https://api.kuvert.dk/v1/api/webhooks \
-H "Authorization: Bearer $KUVERT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "weh_5e8a1c3f7b9d42e6a0c4f8b2d6e1a3c9",
"status": "disabled"
}'200 OKJSON{
"endpoint": {
"id": "weh_5e8a1c3f7b9d42e6a0c4f8b2d6e1a3c9",
"url": "https://dit-system.dk/kuvert",
"events": [
"giftcard.issued",
"giftcard.redeemed"
],
"status": "disabled",
"secret": "whsec_docs-example-not-a-real-secret",
"lastDeliveryAt": "2026-09-29T09:12:44.000Z",
"lastDeliveryOk": true,
"lastDeliveryDetail": null,
"consecutiveFailures": 0,
"createdAt": "2026-09-01T07:30:00.000Z"
}
}Body
idstringObligatorisk- Slutpunktens id (
weh_…). urlstringValfri- En ny adress, med samma krav som när den skapas.
eventsstring[]Valfri- En ny lista med händelser. Den ersätter den gamla helt.
status"active" | "disabled"Valfridisabledstoppar leveranserna utan att radera slutpunkten.
Svarsfält
Den ändrade slutpunkten ligger under endpoint.
Statuskoder
200
Slutpunkten är ändrad.
400
invalid_requestBodyn stämmer inte, oftast för att
idsaknas.404
webhook_endpoint_not_foundSlutpunkten finns inte hos ditt företag.
Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.
Används ofta tillsammans med
Radera en slutpunkt
/ v1/ api/ webhooks/ {id}Tar bort slutpunkten för gott. Vill du bara pausa, sätt status till disabled i stället.
curl -X DELETE https://api.kuvert.dk/v1/api/webhooks/weh_5e8a1c3f7b9d42e6a0c4f8b2d6e1a3c9 \
-H "Authorization: Bearer $KUVERT_API_KEY"200 OKJSON{
"deleted": true
}Sökvägsparametrar
idstringObligatorisk- Slutpunktens id (
weh_…).
Svarsfält
deletedboolean- Alltid
true.
Statuskoder
200
Slutpunkten är raderad.
404
webhook_endpoint_not_foundSlutpunkten finns inte hos ditt företag.
Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.
Används ofta tillsammans med
Varje händelse skickas som en POST med en JSON-body i fyra fält: id är leveransens eget id (whevt_…), type är händelsen, createdAt är tidpunkten, och data är det händelsen handlar om. Tre headers följer med: content-type, kuvert-event-type och kuvert-signature.
POST /kuvert HTTP/1.1
Host: dit-system.dk
content-type: application/json
kuvert-event-type: giftcard.redeemed
kuvert-signature: t=1790673164,v1=067aae7b381a2e42b518ef5781e9747638aa4c987e4f68396bef9a06a78d71a8
{"id":"whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7","type":"giftcard.redeemed","createdAt":"2026-09-29T09:12:44.118Z","data":{"code":"KUV-7K9F-2XQD","amountOre":6400,"remainingBalanceOre":43600}}Signaturen i exemplet är äkta. Med hemligheten whsec_docs-example-not-a-real-secret ger receptet under Signaturen exakt den v1. Kör din egen verifiering på den, med tidstoleransen avstängd, eftersom tidpunkten ligger bakåt i tiden.
giftcard.issued
Ett presentkort är utgivet.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "giftcard.issued",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"code": "KUV-M4TQ-8WZR",
"initialOre": 50000,
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c"
}
}giftcard.redeemed
Ett belopp dras från ett kort.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "giftcard.redeemed",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"code": "KUV-7K9F-2XQD",
"amountOre": 6400,
"remainingBalanceOre": 43600
}
}order.paid
En order är betald. På en biljettorder följer köparens svar på kvällens frågor med i answers, t.ex. ett lagnamn, vart och ett med frågan så som den löd när den besvarades.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "order.paid",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
"totalOre": 50000,
"cardCodes": [
"KUV-M4TQ-8WZR"
],
"answers": []
}
}order.refunded
En order är återbetald.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "order.refunded",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
"refundedOre": 50500
}
}ticket.issued
En biljett är utgiven från en betald order. Orderns svar på kvällens frågor följer med i answers på varje biljett.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "ticket.issued",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"code": "TKT-H3NW-7PKC",
"eventId": "evt_1a9c4e7b2d5f48a3b6c9e0d2f4a7b1c8",
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
"answers": [
{
"questionId": "eqs_5c1e9a7d3b2f48a6",
"label": "Holdnavn",
"answer": "Ølnørderne"
}
],
"seller": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"host": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"cohosts": []
}
}order.disputed
Köparens kortutgivare har bestridit betalningen. Orderns presentkort och biljetter är pausade och kan inte användas.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "order.disputed",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
"frozenCards": 1,
"frozenTickets": 0
}
}order.dispute_closed
Ärendet är löst. won: true betyder att pausen är hävd och korten fungerar igen; false att de är annullerade.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "order.dispute_closed",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
"won": true,
"disputedOre": 50500
}
}booking.created
Ett bord har bokats av gästen på bokningssidan, per telefon eller vid dörren.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "booking.created",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"bookingId": "bkg_6c0e3a9f5b1d47e2a8c4f0b6d2e9a5c1",
"date": "2026-10-02",
"startsAt": "2026-10-02T17:30:00.000Z",
"endsAt": "2026-10-02T19:30:00.000Z",
"guests": 4,
"status": "confirmed",
"source": "storefront",
"guestName": "Mette Hansen",
"guestEmail": "mette@dit-domaene.dk",
"guestPhone": "+45 12 34 56 78",
"tableIds": [
"btb_0d4a8e2c6f1b43a9b7e5c3d1f9a2e6b8"
]
}
}booking.changed
En bordsbokning har fått ny tid, nytt datum, nytt antal, nya bord eller en ny status. Hela bokningen följer med, och status säger var den står.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "booking.changed",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"bookingId": "bkg_6c0e3a9f5b1d47e2a8c4f0b6d2e9a5c1",
"date": "2026-10-02",
"startsAt": "2026-10-02T17:30:00.000Z",
"endsAt": "2026-10-02T19:30:00.000Z",
"guests": 6,
"status": "confirmed",
"source": "storefront",
"guestName": "Mette Hansen",
"guestEmail": "mette@dit-domaene.dk",
"guestPhone": "+45 12 34 56 78",
"tableIds": [
"btb_0d4a8e2c6f1b43a9b7e5c3d1f9a2e6b8"
]
}
}booking.cancelled
En bordsbokning är avbokad, av gästen eller av restaurangen. Bokningar som flyttas in från ett annat system skickar inga händelser.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "booking.cancelled",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"bookingId": "bkg_6c0e3a9f5b1d47e2a8c4f0b6d2e9a5c1",
"date": "2026-10-02",
"startsAt": "2026-10-02T17:30:00.000Z",
"endsAt": "2026-10-02T19:30:00.000Z",
"guests": 4,
"status": "cancelled",
"source": "storefront",
"guestName": "Mette Hansen",
"guestEmail": "mette@dit-domaene.dk",
"guestPhone": "+45 12 34 56 78",
"tableIds": [
"btb_0d4a8e2c6f1b43a9b7e5c3d1f9a2e6b8"
]
}
}event.published
Ett arrangemang har lagts ut till försäljning. Hela kvällen följer med (namn, tider, plats, serie, line-up och genrer) i samma form som listan på GET /v1/merchants/{slug}, med eventId i stället för id.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "event.published",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"eventId": "evt_1a9c4e7b2d5f48a3b6c9e0d2f4a7b1c8",
"slug": "vortex-dimension-2026-10-03",
"name": "Vortex Dimension",
"startsAt": "2026-10-03T21:00:00.000Z",
"endsAt": "2026-10-04T03:00:00.000Z",
"venue": "Club Vortex",
"bannerUrl": "https://api.kuvert.dk/v1/media/med_2b7e4c9a1f3d48e6b0a5c8d2f1e7a4b9",
"bannerWidth": 1080,
"bannerHeight": 1350,
"salesCloseAt": "2026-10-03T21:00:00.000Z",
"status": "published",
"cancelNote": null,
"series": null,
"seriesDate": null,
"subtitle": "No Boyz On Deck",
"lineup": [
{
"name": "Faustix",
"role": "DJ",
"time": "2026-10-03T23:00:00.000Z"
}
],
"genres": [
"House",
"Techno"
],
"doorsAt": "2026-10-03T21:00:00.000Z",
"lastEntryAt": "2026-10-04T01:30:00.000Z",
"dressCode": null,
"ticketsUrl": null,
"host": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"cohosts": []
}
}event.updated
Något offentligt på ett publicerat arrangemang har ändrats. changedFields anger vad, t.ex. lineup, eller tiers när ett pris har ändrats.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "event.updated",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"eventId": "evt_1a9c4e7b2d5f48a3b6c9e0d2f4a7b1c8",
"slug": "vortex-dimension-2026-10-03",
"name": "Vortex Dimension",
"startsAt": "2026-10-03T21:00:00.000Z",
"endsAt": "2026-10-04T03:00:00.000Z",
"venue": "Club Vortex",
"bannerUrl": "https://api.kuvert.dk/v1/media/med_2b7e4c9a1f3d48e6b0a5c8d2f1e7a4b9",
"bannerWidth": 1080,
"bannerHeight": 1350,
"salesCloseAt": "2026-10-03T21:00:00.000Z",
"status": "published",
"cancelNote": null,
"series": null,
"seriesDate": null,
"subtitle": "No Boyz On Deck",
"lineup": [
{
"name": "Faustix",
"role": "DJ",
"time": "2026-10-03T23:00:00.000Z"
}
],
"genres": [
"House",
"Techno"
],
"doorsAt": "2026-10-03T21:00:00.000Z",
"lastEntryAt": "2026-10-04T01:30:00.000Z",
"dressCode": null,
"ticketsUrl": null,
"host": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"cohosts": [],
"changedFields": [
"lineup"
]
}
}event.canceled
Ett publicerat evenemang har ställts in. cancelNote är meddelandet ni skrev till gästerna.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "event.canceled",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"eventId": "evt_1a9c4e7b2d5f48a3b6c9e0d2f4a7b1c8",
"slug": "vortex-dimension-2026-10-03",
"name": "Vortex Dimension",
"startsAt": "2026-10-03T21:00:00.000Z",
"endsAt": "2026-10-04T03:00:00.000Z",
"venue": "Club Vortex",
"bannerUrl": "https://api.kuvert.dk/v1/media/med_2b7e4c9a1f3d48e6b0a5c8d2f1e7a4b9",
"bannerWidth": 1080,
"bannerHeight": 1350,
"salesCloseAt": "2026-10-03T21:00:00.000Z",
"status": "canceled",
"cancelNote": "Aftenen er aflyst. Alle billetter refunderes automatisk.",
"series": null,
"seriesDate": null,
"subtitle": "No Boyz On Deck",
"lineup": [
{
"name": "Faustix",
"role": "DJ",
"time": "2026-10-03T23:00:00.000Z"
}
],
"genres": [
"House",
"Techno"
],
"doorsAt": "2026-10-03T21:00:00.000Z",
"lastEntryAt": "2026-10-04T01:30:00.000Z",
"dressCode": null,
"ticketsUrl": null,
"host": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"cohosts": []
}
}event.unpublished
Ett publicerat evenemang har satts tillbaka till utkast. Ett utkast skickar aldrig händelser.
{
"id": "whevt_c81f5a2d9e3b47c6a0d4e8f1b5c9a2d7",
"type": "event.unpublished",
"createdAt": "2026-09-29T09:12:44.118Z",
"data": {
"eventId": "evt_1a9c4e7b2d5f48a3b6c9e0d2f4a7b1c8",
"slug": "vortex-dimension-2026-10-03",
"name": "Vortex Dimension",
"startsAt": "2026-10-03T21:00:00.000Z",
"endsAt": "2026-10-04T03:00:00.000Z",
"venue": "Club Vortex",
"bannerUrl": "https://api.kuvert.dk/v1/media/med_2b7e4c9a1f3d48e6b0a5c8d2f1e7a4b9",
"bannerWidth": 1080,
"bannerHeight": 1350,
"salesCloseAt": "2026-10-03T21:00:00.000Z",
"status": "draft",
"cancelNote": null,
"series": null,
"seriesDate": null,
"subtitle": "No Boyz On Deck",
"lineup": [
{
"name": "Faustix",
"role": "DJ",
"time": "2026-10-03T23:00:00.000Z"
}
],
"genres": [
"House",
"Techno"
],
"doorsAt": "2026-10-03T21:00:00.000Z",
"lastEntryAt": "2026-10-04T01:30:00.000Z",
"dressCode": null,
"ticketsUrl": null,
"host": {
"slug": "club-vortex",
"name": "Club Vortex"
},
"cohosts": []
}
}Varje leverans bär en kuvert-signature-header med en tidsstämpel och en HMAC:
kuvert-signature: t=1753440000,v1=6f3a…Signaturen är HMAC-SHA256 i hex över strängen tidsstämpel, punkt, den råa bodyn, beräknad med din slutpunkts hemlighet:
HMAC_SHA256(secret, "{t}.{raw body}")# t og v1 fra kuvert-signature, body.json er den rå krop, præcis som den kom ind
printf '%s.%s' "$t" "$(cat body.json)" \
| openssl dgst -sha256 -hmac "$KUVERT_WEBHOOK_SECRET" -hex
# Sammenlign resultatet med v1- Bekräfta med 2xx så snart du har mottagit. Lägg det tunga arbetet i en kö.
- Leverans sker efter bästa förmåga. En slutpunkt som ligger nere håller aldrig tillbaka ett köp hos företaget.
- Vi väntar högst 5 sekunder på svaret. Allt annat än 2xx inom den tiden räknas som en misslyckad leverans, även en omdirigering, som vi inte följer.
Misslyckas en leverans skickar vi den igen med allt längre pauser (1 minut, 5 minuter, 30 minuter, 2 timmar, 6 timmar, 12 timmar och 24 timmar), totalt 8 försök under knappt två dygn. Det är samma body med samma id varje gång, men med en ny signatur, så att tidsstämpeln är färsk. Använd id:t för att känna igen en händelse som ni redan har tagit emot: når ert svar inte fram skickar vi den igen.
Hur den senaste leveransen gick står på slutpunkten: Lista slutpunkter svarar med lastDeliveryAt, lastDeliveryOk, lastDeliveryDetail och consecutiveFailures, och detsamma står under Inställningar → Webhooks. Vi stänger aldrig av en slutpunkt på eget initiativ. Bara du kan sätta den till disabled, och en avstängd slutpunkt får inte heller några nya försök.
Slutpunkten måste vara en offentligt tillgänglig HTTPS-adress. Interna adresser avvisas med avsikt, så att en slutpunkt inte kan användas för att nå in i vårt eget nätverk.
Var sidan till hjälp?