Opprett et endepunkt
Under Innstillinger → Webhooks legger du til den URL-en hendelsene skal sendes til. Du får en hemmelighet tilbake — den brukes til å verifisere signaturen og skal lagres som et passord.
Et system kan også abonnere på seg selv med en API-nøkkel, uten at noen åpner dashbordet. Det er slik en integrasjon du ikke selv har skrevet kobler seg på: den får din nøkkel og registrerer sin egen adresse.
| Metode | Sti | Gjør |
|---|---|---|
| GET | /v1/api/webhooks | Lister dine endepunkter |
| POST | /v1/api/webhooks | Oppretter ett og returnerer hemmeligheten |
| PATCH | /v1/api/webhooks | Retter adresse, hendelser eller status |
| DELETE | /v1/api/webhooks/{id} | Fjerner det igjen |
curl -X POST https://api.kuvert.dk/v1/api/webhooks \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"url":"https://dit-system.dk/kuvert","events":["giftcard.redeemed"]}'Hendelser
| Hendelse | Sendes når |
|---|---|
| giftcard.issued | Et gavekort er utstedt. |
| giftcard.redeemed | Et beløp er trukket fra et kort. |
| order.paid | En ordre er betalt. |
| order.refunded | En ordre er refundert. |
| ticket.issued | En billett er utstedt av en betalt ordre. |
| order.disputed | Kjøperens kortutssteder har bestridt betalingen. Ordren sine gavekort og billetter er satt på pause og kan ikke brukes. |
| order.dispute_closed | Saken er avgjort. `won: true` betyr at pauseringen er hevet og kortene virker igjen; `false` at de er annullert. |
| booking.created | Et bord er booket — av gjesten på bookingsiden, på telefon eller ved døren. |
| booking.changed | En bordreservasjon har fått nytt tidspunkt, ny dato, nytt antall, nye bord eller en ny status. Hele bookingen følger med, og `status` sier hvor den står. |
| booking.cancelled | En bordreservasjon er avbestilt, av gjesten eller av restauranten. Bookinger som flyttes inn fra et annet system, sender ingen hendelser. |
Signaturen
Hver levering bærer en kuvert-signature-header med et tidsstempel og en HMAC:
kuvert-signature: t=1753440000,v1=6f3a…Signaturen er HMAC-SHA256 i heks over strengen tidsstempel, punktum, den rå kroppen — beregnet med ditt endepunkts-hemmelighet:
HMAC_SHA256(secret, "{t}.{raw body}")Verifiser i Node
import { createHmac, timingSafeEqual } from 'node:crypto'
function verify(header, rawBody, secret, toleranceSec = 300) {
const parts = Object.fromEntries(
header.split(',').map((kv) => kv.split('=')),
)
const t = Number(parts.t)
if (!t || !parts.v1) return false
// Afvis for gamle leverancer — det stopper genafspilning.
if (Math.abs(Date.now() / 1000 - t) > toleranceSec) return false
const expected = createHmac('sha256', secret)
.update(`${t}.${rawBody}`)
.digest('hex')
const a = Buffer.from(expected, 'hex')
const b = Buffer.from(parts.v1, 'hex')
return a.length === b.length && timingSafeEqual(a, b)
}Svar raskt
- Kvitter med 2xx så snart du har mottatt. Legg det tunge arbeidet i en kø.
- Levering er beste forsøk — et endepunkt som er nede, holder aldri et kjøp tilbake hos bedriften.
- Regn med å kunne motta den samme hendelsen to ganger, og gjør håndteringen idempotent.
Krav til URL
Endepunktet skal være en offentlig tilgjengelig HTTPS-adresse. Interne adresser avvises — det er en bevisst sperre mot at et endepunkt brukes til å nå inn i vårt eget nettverk.