Guia de Integração de Webhooks¶
O Gift Card Hero envia requisições HTTP POST para o seu servidor quando eventos específicos de cartão-presente acontecem. Use webhooks para manter sistemas externos sincronizados com a atividade dos cartões-presente em tempo real.
Configuração¶
- Acesse For developers no menu de navegação à esquerda
- Marque Enable REST API e salve. As configurações de webhook só aparecem enquanto a REST API estiver ativada
- Clique em Generate Secret para criar um segredo de assinatura do webhook

O segredo é exibido apenas uma vez
Copie o segredo e guarde-o em local seguro. Se você perdê-lo, clique em Regenerate Secret para criar um novo. O segredo antigo deixa de funcionar imediatamente, então atualize também o seu servidor.
- Informe as URLs de endpoint para cada tipo de webhook que deseja receber e clique em Save na barra de salvamento

Uma URL de endpoint nova ou alterada precisa começar com https:// e apontar para um servidor acessível pela internet. Endereços de uma rede privada — localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x e similares — são recusados ao salvar. Uma URL salva antes dessa regra continua funcionando até que você a altere, mas só é chamada se apontar para um endereço público. Para testar com um servidor local, exponha-o por um túnel como o ngrok e use a URL https pública que ele fornecer.
Tipos de evento¶
O Gift Card Hero tem três campos de URL de webhook:
| Evento | Valor do cabeçalho de tópico | Quando é disparado |
|---|---|---|
| Gift card order | gift_card_order |
O Gift Card Hero processa os cartões-presente de um pedido. O payload lista os cartões que pertencem ao pedido |
| Gift card payment | gift_card_payment |
Um pedido é criado e foi pago, total ou parcialmente, com um cartão-presente |
| Gift card balance change | gift_card_balance |
Não é enviado no momento |
Webhook de alteração de saldo
O campo Gift card balance webhook URL está na página, mas o Gift Card Hero ainda não envia este evento. Para acompanhar alterações de saldo hoje, faça polling de GET /gift-cards/transactions ou use o evento gift_card_payment para pagamentos.
Os webhooks só são enviados enquanto Enable REST API estiver ativado e a URL desse evento estiver preenchida.
Entrega¶
- Método: POST
- Timeout: 6 segundos
- Tentativas: até 5 tentativas de entrega no total (a primeira e até 4 novas tentativas), com intervalos crescentes exponencialmente, começando em cerca de 30 a 60 segundos
- Redirecionamentos: não são seguidos. Uma resposta
3xxconta como entrega com falha, então use a URL final do seu endpoint.
Se o seu endpoint não devolver uma resposta 2xx em 6 segundos, a entrega é considerada falha e será tentada de novo.
Cabeçalhos¶
Toda requisição de webhook inclui os seguintes cabeçalhos:
| Cabeçalho | Valor |
|---|---|
Content-Type |
application/json |
User-Agent |
GiftHero-Webhooks/1.0 |
X-GiftHero-Topic |
O tipo de evento (por exemplo, gift_card_order) |
X-GiftHero-Signature |
Assinatura HMAC-SHA256 para verificação. Enviado somente quando você gerou um segredo de webhook |
Verificação de assinatura¶
O cabeçalho X-GiftHero-Signature contém uma assinatura HMAC-SHA256, codificada em hexadecimal e com o prefixo sha256=.
Importante: A assinatura é calculada sobre um objeto JSON que contém apenas
{ type, timestamp }do corpo do payload — NÃO o corpo inteiro da requisição.
Passos de verificação¶
- Faça o parse do corpo da requisição e extraia os campos
typeetimestamp - Monte o payload de assinatura:
JSON.stringify({ type, timestamp }) - Calcule o HMAC-SHA256 usando o seu segredo de webhook como chave
- Codifique o resultado em hexadecimal e acrescente o prefixo
sha256= - Compare com o cabeçalho
X-GiftHero-Signatureusando uma comparação de tempo constante
Exemplo (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 de payload¶
Todo corpo de requisição tem o mesmo envelope. Os detalhes do evento ficam dentro de data:
{
"type": "gift_card_order",
"timestamp": "2026-03-15T10:30:00.000Z",
"data": { }
}
Pedido com cartão-presente (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"
}
]
}
}
Pagamento com cartão-presente (gift_card_payment)¶
Cada entrada em giftCards também traz a transaction que pagou o 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 os campos¶
data.orderedata.giftCardssão os campos em que você deve se basear.datatambém repete alguns campos do pedido no nível superior (orderId,orderName,orderEmail,createdAt,lineItems) e traz campos internos (storeId,shop,jobType). Não dependa deles.balanceé o saldo do cartão no momento em que o webhook foi montado, não no momento em que o pedido foi feito.codeé o código completo do cartão-presente. É incluído somente quando o Gift Card Hero tem o código registrado, e omitido caso contrário. Trate-o como uma senha e garanta que o seu endpoint esteja protegido.lineItemIdeskusão incluídos quando o cartão pode ser associado a uma linha do pedido.- As entradas de
lineItemstrazemid,title,quantity,skuevariantId(sem preço). - Se os detalhes de um cartão não puderem ser carregados, a entrada dele é reduzida a
id, valores zerados e umlastCharactersvazio. Releia o cartão pela REST API quando isso acontecer.
Boas práticas¶
- Responda 2xx rapidamente — confirme o recebimento do webhook imediatamente e processe o payload de forma assíncrona. Respostas que demorem mais de 6 segundos são tratadas como falhas.
- Trate duplicatas — o mesmo evento pode ser entregue mais de uma vez por causa das novas tentativas. Use os IDs do pedido e do cartão-presente nos dados do evento para deduplicar. O
timestampé o momento de cada tentativa, então não serve como chave estável. - Verifique as assinaturas HMAC — sempre verifique o cabeçalho
X-GiftHero-Signatureantes de processar qualquer payload de webhook. Rejeite requisições com assinaturas inválidas. - Use chaves de idempotência — projete o seu handler de webhook para ser idempotente, de modo que processar o mesmo evento duas vezes produza o mesmo resultado.
- Monitore falhas — se o seu endpoint estiver falhando de forma consistente, o Gift Card Hero para de tentar novamente após 5 tentativas no total. Verifique os logs do servidor e a saúde do endpoint regularmente.