Guía de integración de webhooks¶
Gift Card Hero envía solicitudes HTTP POST a tu servidor cuando ocurren eventos concretos de tarjetas de regalo. Usa los webhooks para mantener sincronizados los sistemas externos con la actividad de las tarjetas de regalo en tiempo real.
Configuración¶
- Ve a For developers en la navegación de la izquierda
- Marca Enable REST API y guarda. La configuración de webhooks solo aparece mientras la REST API está activada
- Haz clic en Generate Secret para crear el secreto de firma de webhooks

El secreto solo se muestra una vez
Copia el secreto y guárdalo de forma segura. Si lo pierdes, haz clic en Regenerate Secret para crear uno nuevo. El secreto anterior deja de funcionar de inmediato, así que actualiza también tu servidor.
- Introduce las URL de tus endpoints para cada tipo de webhook que quieras recibir y haz clic en Save en la barra de guardado

Una URL de endpoint nueva o modificada debe empezar por https:// y apuntar a un servidor accesible desde internet. Las direcciones de una red privada (localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x y similares) se rechazan al guardar. Una URL guardada antes de esta regla seguirá funcionando hasta que la cambies, pero solo se llamará si apunta a una dirección pública. Para probar con un servidor local, exponlo mediante un túnel como ngrok y usa la URL https pública que te dé.
Tipos de evento¶
Gift Card Hero tiene tres campos de URL de webhook:
| Evento | Valor del encabezado de tópico | Cuándo se envía |
|---|---|---|
| Gift card order | gift_card_order |
Gift Card Hero procesa las tarjetas de regalo de un pedido. El payload lista las tarjetas que pertenecen al pedido |
| Gift card payment | gift_card_payment |
Se crea un pedido pagado total o parcialmente con una tarjeta de regalo |
| Gift card balance change | gift_card_balance |
Por ahora no se envía |
Webhook de cambio de saldo
El campo Gift card balance webhook URL aparece en la página, pero Gift Card Hero todavía no envía este evento. Para seguir los cambios de saldo hoy, consulta GET /gift-cards/transactions de forma periódica o usa el evento gift_card_payment para los pagos.
Los webhooks solo se envían mientras Enable REST API esté activado y la URL de ese evento esté rellenada.
Entrega¶
- Método: POST
- Tiempo de espera: 6 segundos
- Intentos: hasta 5 intentos de entrega en total (el primero y hasta 4 reintentos), con retrasos crecientes exponencialmente que empiezan en unos 30 a 60 segundos
- Redirecciones: no se siguen. Una respuesta
3xxcuenta como entrega fallida, así que usa la URL final de tu endpoint.
Si tu endpoint no devuelve una respuesta 2xx en 6 segundos, la entrega se considera fallida y se reintentará.
Encabezados¶
Cada solicitud de webhook incluye los siguientes encabezados:
| Encabezado | Valor |
|---|---|
Content-Type |
application/json |
User-Agent |
GiftHero-Webhooks/1.0 |
X-GiftHero-Topic |
El tipo de evento (por ejemplo, gift_card_order) |
X-GiftHero-Signature |
Firma HMAC-SHA256 para la verificación. Solo se envía cuando has generado un secreto de webhook |
Verificación de firma¶
El encabezado X-GiftHero-Signature contiene una firma HMAC-SHA256, codificada en hexadecimal y con el prefijo sha256=.
Importante: la firma se calcula sobre un objeto JSON que contiene solo
{ type, timestamp }del cuerpo del payload, NO sobre el cuerpo completo de la solicitud.
Pasos de verificación¶
- Analiza el cuerpo de la solicitud y extrae los campos
typeytimestamp - Construye el payload de firma:
JSON.stringify({ type, timestamp }) - Calcula el HMAC-SHA256 usando tu secreto de webhook como clave
- Codifica el resultado en hexadecimal y añade el prefijo
sha256= - Compara con el encabezado
X-GiftHero-Signatureusando una comparación de tiempo constante
Ejemplo (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)
);
}
Esquemas del payload¶
Todos los cuerpos de solicitud tienen el mismo envoltorio. Los detalles del evento están dentro de 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)¶
Cada entrada de giftCards también incluye la transaction que pagó el pedido.
{
"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"
}
}
]
}
}
Notas sobre los campos¶
data.orderydata.giftCardsson los campos en los que debes basarte.datatambién repite algunos campos del pedido en su nivel superior (orderId,orderName,orderEmail,createdAt,lineItems) y contiene campos internos (storeId,shop,jobType). No dependas de ellos.balancees el saldo de la tarjeta en el momento en que se construye el webhook, no cuando se hizo el pedido.codees el código completo de la tarjeta de regalo. Solo se incluye cuando Gift Card Hero tiene el código registrado, y se omite en caso contrario. Trátalo como una contraseña y asegúrate de que tu endpoint esté protegido.lineItemIdyskuse incluyen cuando la tarjeta se puede asociar a una línea del pedido.- Las entradas de
lineItemscontienenid,title,quantity,skuyvariantId(sin precio). - Si no se pueden cargar los detalles de una tarjeta, su entrada se reduce a
id, importes en cero y unlastCharactersvacío. Vuelve a leer la tarjeta con la REST API cuando veas esto.
Buenas prácticas¶
- Responde 2xx rápido: confirma el webhook de inmediato y procesa el payload de forma asíncrona. Las respuestas que tarden más de 6 segundos se consideran fallidas.
- Gestiona los duplicados: el mismo evento puede llegar más de una vez por los reintentos. Usa los IDs del pedido y de la tarjeta de regalo de los datos del evento para deduplicar. El
timestampes la hora de cada intento, así que no es una clave estable. - Verifica las firmas HMAC: verifica siempre el encabezado
X-GiftHero-Signatureantes de procesar cualquier payload de webhook. Rechaza las solicitudes con firmas no válidas. - Usa claves de idempotencia: diseña tu gestor de webhooks para que sea idempotente, de modo que procesar dos veces el mismo evento dé el mismo resultado.
- Supervisa los fallos: si tu endpoint falla de forma constante, Gift Card Hero deja de reintentar tras 5 intentos en total. Revisa con regularidad los registros de tu servidor y el estado de tu endpoint.