Guide d'intégration des webhooks¶
Gift Card Hero envoie des requêtes HTTP POST à votre serveur lorsque certains événements de cartes-cadeaux se produisent. Utilisez les webhooks pour garder vos systèmes externes synchronisés avec l'activité des cartes-cadeaux en temps réel.
Configuration¶
- Allez dans For developers dans la navigation de gauche
- Cochez Enable REST API et enregistrez. Les réglages des webhooks n'apparaissent que lorsque l'API REST est activée
- Cliquez sur Generate Secret pour créer un secret de signature des webhooks

Le secret n'est affiché qu'une seule fois
Copiez le secret et conservez-le en lieu sûr. Si vous le perdez, cliquez sur Regenerate Secret pour en créer un nouveau. L'ancien secret cesse de fonctionner immédiatement : mettez donc aussi votre serveur à jour.
- Saisissez les URL de vos points de terminaison pour chaque type de webhook que vous souhaitez recevoir, puis cliquez sur Save dans la barre d'enregistrement

Une URL de point de terminaison nouvelle ou modifiée doit commencer par https:// et pointer vers un serveur accessible depuis Internet. Les adresses d'un réseau privé (localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x et similaires) sont refusées à l'enregistrement. Une URL enregistrée avant cette règle continue de fonctionner jusqu'à ce que vous la modifiiez, mais elle n'est appelée que si elle pointe vers une adresse publique. Pour tester avec un serveur local, exposez-le via un tunnel comme ngrok et utilisez l'URL https publique qu'il vous fournit.
Types d'événements¶
Gift Card Hero propose trois champs d'URL de webhook :
| Événement | Valeur de l'en-tête Topic | Moment du déclenchement |
|---|---|---|
| Gift card order | gift_card_order |
Gift Card Hero traite les cartes-cadeaux d'une commande. La charge utile liste les cartes qui appartiennent à la commande |
| Gift card payment | gift_card_payment |
Une commande payée en totalité ou en partie avec une carte-cadeau est créée |
| Gift card balance change | gift_card_balance |
Pas envoyé pour le moment |
Webhook de changement de solde
Le champ Gift card balance webhook URL figure sur la page, mais Gift Card Hero n'envoie pas encore cet événement. Pour suivre les changements de solde dès maintenant, interrogez GET /gift-cards/transactions ou utilisez l'événement gift_card_payment pour les paiements.
Les webhooks ne sont envoyés que lorsque Enable REST API est activé et que l'URL de cet événement est renseignée.
Envoi¶
- Méthode : POST
- Délai d'attente : 6 secondes
- Tentatives : jusqu'à 5 tentatives d'envoi au total (la première et jusqu'à 4 nouvelles tentatives), avec des délais croissants de façon exponentielle, à partir d'environ 30 à 60 secondes
- Redirections : non suivies. Une réponse
3xxcompte comme un échec d'envoi : utilisez donc l'URL finale de votre point de terminaison.
Si votre point de terminaison ne renvoie pas une réponse 2xx dans les 6 secondes, l'envoi est considéré comme échoué et sera retenté.
En-têtes¶
Chaque requête de webhook comprend les en-têtes suivants :
| En-tête | Valeur |
|---|---|
Content-Type |
application/json |
User-Agent |
GiftHero-Webhooks/1.0 |
X-GiftHero-Topic |
Le type d'événement (par ex. gift_card_order) |
X-GiftHero-Signature |
Signature HMAC-SHA256 pour la vérification. Envoyée uniquement lorsque vous avez généré un secret de webhook |
Vérification de la signature¶
L'en-tête X-GiftHero-Signature contient une signature HMAC-SHA256, encodée en hexadécimal et préfixée par sha256=.
Important : la signature est calculée sur un objet JSON ne contenant que
{ type, timestamp }extraits de la charge utile, et NON sur le corps complet de la requête.
Étapes de vérification¶
- Analysez le corps de la requête et extrayez les champs
typeettimestamp - Construisez la charge utile de signature :
JSON.stringify({ type, timestamp }) - Calculez le HMAC-SHA256 en utilisant votre secret de webhook comme clé
- Encodez le résultat en hexadécimal et préfixez-le par
sha256= - Utilisez une comparaison à temps constant pour le comparer à l'en-tête
X-GiftHero-Signature
Exemple (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)
);
}
Schémas des charges utiles¶
Chaque corps de requête a la même enveloppe. Les détails de l'événement se trouvent dans data :
{
"type": "gift_card_order",
"timestamp": "2026-03-15T10:30:00.000Z",
"data": { }
}
Commande de carte-cadeau (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"
}
]
}
}
Paiement par carte-cadeau (gift_card_payment)¶
Chaque entrée de giftCards transporte aussi la transaction qui a payé la commande.
{
"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"
}
}
]
}
}
Remarques sur les champs¶
data.orderetdata.giftCardssont les champs sur lesquels vous devez vous appuyer.datarépète aussi certains champs de commande à son niveau supérieur (orderId,orderName,orderEmail,createdAt,lineItems) et contient des champs internes (storeId,shop,jobType). Ne vous y fiez pas.balanceest le solde de la carte au moment où le webhook est construit, et non au moment où la commande a été passée.codeest le code complet de la carte-cadeau. Il n'est inclus que lorsque Gift Card Hero a ce code en mémoire, et omis sinon. Traitez-le comme un mot de passe et assurez-vous que votre point de terminaison est sécurisé.lineItemIdetskusont inclus lorsque la carte peut être associée à une ligne de commande.- Les entrées de
lineItemscontiennentid,title,quantity,skuetvariantId(sans prix). - Si les détails d'une carte ne peuvent pas être chargés, son entrée se réduit à
id, des montants à zéro et unlastCharactersvide. Relisez la carte avec l'API REST lorsque vous constatez ce cas.
Bonnes pratiques¶
- Répondez 2xx rapidement : accusez réception du webhook immédiatement et traitez la charge utile de manière asynchrone. Les réponses qui prennent plus de 6 secondes sont considérées comme des échecs.
- Gérez les doublons : le même événement peut être livré plus d'une fois à cause des nouvelles tentatives. Utilisez les identifiants de commande et de carte-cadeau des données de l'événement pour dédoublonner. Le
timestampcorrespond à l'heure de chaque tentative : ce n'est donc pas une clé stable. - Vérifiez les signatures HMAC : vérifiez toujours l'en-tête
X-GiftHero-Signatureavant de traiter une charge utile de webhook. Rejetez les requêtes dont la signature est invalide. - Utilisez des clés d'idempotence : concevez votre gestionnaire de webhook pour qu'il soit idempotent, afin que le traitement du même événement deux fois produise le même résultat.
- Surveillez les échecs : si votre point de terminaison échoue de façon répétée, Gift Card Hero cesse de réessayer après 5 tentatives au total. Consultez régulièrement les journaux de votre serveur et l'état de votre point de terminaison.