Webhooks-integratiegids¶
Gift Card Hero stuurt HTTP POST-verzoeken naar je server wanneer specifieke cadeaubongebeurtenissen plaatsvinden. Gebruik webhooks om externe systemen in realtime synchroon te houden met de activiteit van cadeaubonnen.
Instellen¶
- Ga naar For developers in het linkermenu
- Vink Enable REST API aan en sla op. Webhook-instellingen verschijnen alleen terwijl de REST API aan staat
- Klik op Generate Secret om een webhook-ondertekeningsgeheim aan te maken

Het geheim wordt maar één keer getoond
Kopieer het geheim en bewaar het veilig. Als je het kwijtraakt, klik je op Regenerate Secret om een nieuwe te maken. Het oude geheim werkt meteen niet meer, dus werk ook je server bij.
- Voer je endpoint-URL's in voor elk webhooktype dat je wilt ontvangen, en klik daarna op Save in de opslagbalk

Een nieuwe of gewijzigde endpoint-URL moet beginnen met https:// en naar een server verwijzen die vanaf het internet bereikbaar is. Adressen binnen een privénetwerk — localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x en vergelijkbare — worden bij het opslaan geweigerd. Een URL die van vóór deze regel is opgeslagen blijft werken tot je hem wijzigt, maar er wordt alleen naar gebeld als hij naar een openbaar adres verwijst. Om tegen een lokale server te testen, stel je hem beschikbaar via een tunnel zoals ngrok en gebruik je de openbare https-URL die die geeft.
Gebeurtenistypen¶
Gift Card Hero heeft drie webhook-URL-velden:
| Gebeurtenis | Waarde van de topic-header | Wanneer het wordt verstuurd |
|---|---|---|
| Gift card order | gift_card_order |
Gift Card Hero verwerkt de cadeaubonnen van een bestelling. De payload somt de kaarten op die bij de bestelling horen |
| Gift card payment | gift_card_payment |
Er wordt een bestelling aangemaakt die geheel of gedeeltelijk met een cadeaubon is betaald |
| Gift card balance change | gift_card_balance |
Momenteel niet verzonden |
Webhook voor saldowijzigingen
Het veld Gift card balance webhook URL staat op de pagina, maar Gift Card Hero verstuurt deze gebeurtenis nog niet. Om saldowijzigingen nu te volgen, kun je GET /gift-cards/transactions periodiek opvragen, of gebruik je de gift_card_payment-gebeurtenis voor betalingen.
Webhooks worden alleen verstuurd terwijl Enable REST API aan staat en de URL voor die gebeurtenis is ingevuld.
Levering¶
- Methode: POST
- Timeout: 6 seconden
- Pogingen: Maximaal 5 verzendpogingen in totaal (de eerste en maximaal 4 herhalingen), met exponentieel groeiende wachttijden die starten bij ongeveer 30 tot 60 seconden
- Redirects: Worden niet gevolgd. Een
3xx-antwoord telt als mislukte verzending, dus gebruik de definitieve URL van je endpoint.
Als je endpoint binnen 6 seconden geen 2xx-antwoord geeft, geldt de verzending als mislukt en wordt ze opnieuw geprobeerd.
Headers¶
Elk webhookverzoek bevat de volgende headers:
| Header | Waarde |
|---|---|
Content-Type |
application/json |
User-Agent |
GiftHero-Webhooks/1.0 |
X-GiftHero-Topic |
Het gebeurtenistype (bijv. gift_card_order) |
X-GiftHero-Signature |
HMAC-SHA256-handtekening voor verificatie. Wordt alleen meegestuurd als je een webhook-geheim hebt gegenereerd |
Handtekeningverificatie¶
De header X-GiftHero-Signature bevat een HMAC-SHA256-handtekening, hexadecimaal gecodeerd en voorafgegaan door sha256=.
Belangrijk: De handtekening wordt berekend over een JSON-object dat alleen
{ type, timestamp }uit de payload-body bevat — NIET de volledige request-body.
Verificatiestappen¶
- Parse de request-body en haal de velden
typeentimestamperuit - Stel de ondertekeningspayload samen:
JSON.stringify({ type, timestamp }) - Bereken de HMAC-SHA256 met je webhook-geheim als sleutel
- Codeer het resultaat hexadecimaal en zet
sha256=ervoor - Vergelijk het met de header
X-GiftHero-Signaturemet een constant-time vergelijking
Voorbeeld (Node.js)¶
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const signingPayload = JSON.stringify({
type: body.type,
timestamp: body.timestamp
});
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(signingPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Payloadschema's¶
Elke request-body heeft dezelfde envelop. De gebeurtenisdetails staan in data:
{
"type": "gift_card_order",
"timestamp": "2026-03-15T10:30:00.000Z",
"data": { }
}
Gift card order (gift_card_order)¶
{
"type": "gift_card_order",
"timestamp": "2026-03-15T10:30:00.000Z",
"data": {
"order": {
"id": 5551234567890,
"name": "#1042",
"email": "buyer@example.com",
"createdAt": "2026-03-15T10:30:00.000Z",
"lineItems": [
{
"id": 11198765432100,
"title": "Gift Card",
"quantity": 1,
"sku": "GC-50",
"variantId": 44556677
}
]
},
"giftCards": [
{
"id": 987654321,
"balance": "50.00",
"currency": "USD",
"lastCharacters": "ab12",
"initialValue": "50.00",
"customer": { "id": 123, "email": "buyer@example.com", "name": "Alex Buyer" },
"recipient": { "id": 456, "email": "friend@example.com", "name": "Sam Friend" },
"code": "abcd1234efgh5678",
"lineItemId": 11198765432100,
"sku": "GC-50"
}
]
}
}
Gift card payment (gift_card_payment)¶
Elk item in giftCards bevat ook de transaction die de bestelling heeft betaald.
{
"type": "gift_card_payment",
"timestamp": "2026-03-16T14:22:00.000Z",
"data": {
"order": {
"id": 5551234567891,
"name": "#1043",
"email": "shopper@example.com",
"createdAt": "2026-03-16T14:22:00.000Z",
"lineItems": [
{ "id": 11198765432200, "title": "Running Shoes", "quantity": 1, "sku": "SHOE-9" }
]
},
"giftCards": [
{
"id": 987654321,
"balance": "0.00",
"currency": "USD",
"lastCharacters": "ab12",
"initialValue": "50.00",
"customer": null,
"recipient": null,
"transaction": {
"id": "gid://shopify/OrderTransaction/123456789",
"amount": "50.00",
"currency": "USD",
"type": "debit",
"createdAt": "2026-03-16T14:22:00.000Z"
}
}
]
}
}
Veldtoelichting¶
data.orderendata.giftCardszijn de velden om op voort te bouwen.dataherhaalt ook enkele bestelvelden op het hoogste niveau (orderId,orderName,orderEmail,createdAt,lineItems) en bevat interne velden (storeId,shop,jobType). Vertrouw daar niet op.balanceis het saldo van de kaart op het moment dat de webhook is opgebouwd, niet op het moment dat de bestelling is geplaatst.codeis de volledige cadeaubooncode. Die is alleen opgenomen wanneer Gift Card Hero de code in de administratie heeft, en anders weggelaten. Behandel hem als een wachtwoord en zorg dat je endpoint beveiligd is.lineItemIdenskuzijn opgenomen wanneer de kaart aan een bestelregel gekoppeld kan worden.- Items in
lineItemsbevattenid,title,quantity,skuenvariantId(geen prijs). - Als de gegevens van een kaart niet kunnen worden geladen, wordt het item teruggebracht tot
id, nulbedragen en een legelastCharacters. Lees de kaart opnieuw met de REST API wanneer je dat ziet.
Best practices¶
- Stuur snel een 2xx terug — bevestig de webhook direct en verwerk de payload asynchroon. Antwoorden die langer dan 6 seconden duren, worden als mislukt beschouwd.
- Verwerk duplicaten — dezelfde gebeurtenis kan door herhalingen meer dan één keer worden afgeleverd. Gebruik de order- en cadeaubon-ID's in de gebeurtenisdata om te ontdubbelen. De
timestampis het tijdstip van elke poging, dus het is geen stabiele sleutel. - Verifieer HMAC-handtekeningen — controleer altijd de header
X-GiftHero-Signaturevoordat je een webhook-payload verwerkt. Wijs verzoeken met ongeldige handtekeningen af. - Gebruik idempotentiesleutels — ontwerp je webhook-handler idempotent, zodat het twee keer verwerken van dezelfde gebeurtenis hetzelfde resultaat oplevert.
- Houd fouten in de gaten — als je endpoint consequent faalt, stopt Gift Card Hero na 5 pogingen in totaal met opnieuw proberen. Controleer regelmatig je serverlogs en de gezondheid van je endpoint.