Webhooks.
Welcome to the Gifty webhooks documentation. This documentation covers all information relevant to our event-driven webhooks.
If you have any questions, don't hesitate to reach out. You can contact us via our contact page.
Introduction
The following section describes generic usage information about webhooks.
Getting started
To start receiving webhooks from us, you'll need to register a webhook on the developer's page in your dashboard
When setting up your new webhook, you'll be asked to fill in several fields. These are explained below:
Attribute | Description |
---|---|
Name | Used to help you identify different webhooks. This field is only visible to you. |
URL | This is the endpoint that we forward the events to. This must use HTTPS and accept POST requests. |
Events | The events you want to subscribe to. |
Secret | A private key used to verify webhook authenticity. For details on using this security feature, see "Verifying the authenticity". |
Active | Specifies whether the webhook is active. When paused, it will not send or store events. |
Example flow
In this flow, we'll show you how to verify the authenticity of a webhook request. After following these
steps correctly, you can be sure that the request is authentic and originates from Gifty.
- We send a webhook to your endpoint
- You receive the webhook request
- Verify the authenticity of the request (HMAC and timestamp)
- Process the request
Verifying the authenticity
Every webhook includes the X-Gifty-Webhook-Signature
header. This header contains a hash of
the payload (body) using HMAC-SHA256,
with the secret key you provided during the registration of the webhook. By hashing the payload
of the request yourself using the same hashing algorithm and the secret key that only you and Gifty
know, you can verify if the request is originating from Gifty.
Idempotence
Duplicate webhook deliveries can never be completely ruled out, as they may also occur outside our network, for example, due to retries by intermediaries or client-side issues. Because of this, you should never assume that a webhook will be delivered only once. Always design and build your integration to handle potential duplicates safely and idempotently.
You can verify whether a webhook has already been processed by tracking the X-Gifty-Webhook-Job-Id
header. This identifier is unique to each individual event and remains the same if the same webhook is resent, such as during a retry. By keeping a record of processed job IDs, you can detect and safely ignore duplicates.
Headers
Every webhook we send comes with a set of headers, that are described as follows:
Header | Description |
---|---|
X-Gifty-Webhook-Job-Id | The unique identifier of this specific webhook request. |
X-Gifty-Webhook-Id | The unique identifier of the webhook. |
X-Gifty-Webhook-Signature | The signature used to validate the authenticity of the request. |
X-Gifty-Webhook-Event | The event that caused the webhook to be sent. |
X-Gifty-Webhook-Version | The version of our webhooks processor used to send the request. |
Status codes
When your server responds to a webhook request, the HTTP status code you return determines how our system interprets the outcome. Please ensure that your endpoints return the appropriate status code based on the result of your processing logic.
Code | Meaning |
---|---|
2XX | Successful request. |
3XX* | Redirections will not be followed, please change the endpoint URL if it changed. |
4XX* | The request cannot be processed due to client-side errors. |
429* | The endpoint is receiving too many requests. |
5XX* | The endpoint is unable to process the request at this time. |
* We will attempt to deliver this webhook again later using an exponential back-off strategy.
If a Retry-After
header is provided, we will use this instead. The maximum value for this header is 86,400 seconds (24 hours) and anything above that will be rounded down to this maximum.
Events
Event giftcard.issue
A gift card has been issued.
{
"id": "whj_XeLNZ7E9vQM0L8pvOw4BpoY3",
"object": "event",
"type": "giftcard.issue",
"created_at": "2025-04-10T14:24:53+00:00",
"data": {
"id": "tr_za5Jk8E1ovxQoDNmrpXRxADb",
"amount": 4000,
"currency": "EUR",
"status": "success",
"type": "issue",
"description": "Issue amount of '€ 40,00'",
"is_capturable": false,
"captured_at": "2025-04-10T14:24:53+00:00",
"captured_by": {},
"created_at": "2025-04-10T14:24:53+00:00",
"giftcard": ...GiftCardObject,
"object": "transaction"
}
}
Event giftcard.redeem
A gift card has been (partially) redeemed.
{
"id": "whj_VmLwJwo19xKjSAkVpyooDJvl",
"object": "event",
"type": "giftcard.redeem",
"created_at": "2025-04-10T14:25:52+00:00",
"data": {
"id": "tr_Blp3JyeqRnk2bxod9N2AZwjM",
"amount": -1000,
"currency": "EUR",
"status": "success",
"type": "redeem",
"description": "Redeem amount of '€ 10,00'",
"is_capturable": false,
"captured_at": "2025-04-10T14:25:52+00:00",
"captured_by": {},
"created_at": "2025-04-10T14:25:52+00:00",
"giftcard": ...GiftCardObject,
"object": "transaction"
}
}
Event transaction.captured
A transaction has been captured.
{
"id": "whj_GmW4O4axk7K3TQblDJ11N1d0",
"object": "event",
"type": "transaction.captured",
"created_at": "2025-04-10T14:25:52+00:00",
"data": {
"id": "tr_Blp3JyeqRnk2bxod9N2AZwjM",
"amount": -1000,
"currency": "EUR",
"status": "success",
"type": "redeem",
"description": "Redeem amount of '€ 10,00'",
"is_capturable": false,
"captured_at": "2025-04-10T14:25:52+00:00",
"captured_by": {},
"created_at": "2025-04-10T14:25:52+00:00",
"giftcard": ...GiftCardObject,
"object": "transaction"
}
}
Event location.created
A new establishment has been added to the account.
{
"id": "whj_lvqMRMONllO7T0pOB3PxEavN",
"object": "event",
"type": "location.created",
"created_at": "2025-04-10T14:24:28+00:00",
"data": {
"id": "lc_NaxRrj0MXmGPRLdp5eok8bKZ",
"street": "Floridalaan",
"house_number": "8",
"addition": null,
"postal_code": "3404WV",
"city": "IJsselstein",
"country_code": "NL",
"geometry": {},
"object": "location"
}
}
Event location.updated
An establishment has been modified.
{
"id": "whj_QmyxMxq3WNelIybjO7gB9yvP",
"object": "event",
"type": "location.updated",
"created_at": "2025-04-10T14:24:32+00:00",
"data": {
"id": "lc_NaxRrj0MXmGPRLdp5eok8bKZ",
"street": "Floridalaan",
"house_number": "8",
"addition": null,
"postal_code": "3404WV",
"city": "IJsselstein",
"country_code": "NL",
"geometry": {},
"object": "location"
}
}
Event location.deleted
An establishment has been removed from the account.
{
"id": "whj_lvgRQRqJXPZru8V4A38ALrng",
"object": "event",
"type": "location.deleted",
"created_at": "2025-04-10T14:24:35+00:00",
"data": {
"id": "lc_NaxRrj0MXmGPRLdp5eok8bKZ",
"street": "Floridalaan",
"house_number": "8",
"addition": null,
"postal_code": "3404WV",
"city": "IJsselstein",
"country_code": "NL",
"geometry": {},
"object": "location"
}
}