Webhook payload reference

Every field Wrapped sends in a gift card webhook delivery, with a full example payload, the five topics, and how to verify the HMAC-Signature-SHA256 header. Deliveries are attempted once and are never retried.

Updated September 21, 2026

A Wrapped webhook is a POST of a single JSON object to the HTTPS URL you registered. This article documents every field in that object. To create and list webhooks, see The Wrapped API; for the endpoints themselves, see the API reference.

Topics

Every delivery carries a webhookTopic. There is no filtering — a webhook receives all five.

TopicSent when
giftcard/updatedA gift card is issued, or its balance changes, and Wrapped sends its gift card notifications
giftcard/giftedA gift card is delivered to a recipient as a gift
giftcard/reminderA balance reminder is sent for a gift card
giftcard/voidedA gift card is voided
giftcard/expiredA gift card expires

Adjustments added through the API don't send a giftcard/updated delivery.

Example payload

Property names are PascalCase, as shown. RequestId is new for every delivery — use it to discard duplicates.

{
  "RequestId": "6f1e8b6a-2c9d-4f3a-9d41-0b7c2f5ae913",
  "GiftCardId": "66f0a1b2c3d4e5f60718293a",
  "Code": "WRAP-XY7Q-4KLM",
  "CreatedAt": "2026-09-14T03:21:55.412Z",
  "InitialValue": 50.0,
  "FormattedInitialValue": "$50.00",
  "Balance": 42.5,
  "FormattedBalance": "$42.50",
  "Currency": "AUD",
  "TotalIssuedAmount": 50.0,
  "FormattedTotalIssuedAmount": "$50.00",
  "ExpiresAtUtc": "2027-09-14T00:00:00Z",
  "RecipientName": "Alex Fraser",
  "RecipientEmailAddress": "alex@example.com",
  "BuyerName": "Sam Rivers",
  "BuyerEmail": "sam@example.com",
  "GiftCardMessage": "Happy birthday!",
  "Status": "Active",
  "IsPromotional": false,
  "IsStoreCredit": false,
  "AppleWalletUrl": "https://manage.wrappedgiftcards.com/applewallet/generate/<accountId>/<giftCardId>",
  "GoogleWalletUrl": "https://manage.wrappedgiftcards.com/googlewallet/generate/<accountId>/<giftCardId>",
  "PdfUrl": "https://manage.wrappedgiftcards.com/Giftcard/Pdf/<giftCardId>",
  "ViewBalanceUrl": "https://manage.wrappedgiftcards.com/pc/check-balance/<accountId>?code=WRAP-XY7Q-4KLM",
  "GiftToFriendUrl": "https://manage.wrappedgiftcards.com/public/gift-to-friend/<giftCardId>",
  "GiftCardBatchId": null,
  "AutomationId": null,
  "CampaignId": null,
  "ApiEventName": null,
  "ApiEventProperties": null,
  "WebhookTopic": "giftcard/updated"
}

Fields

FieldTypeNotes
RequestIdstringA new GUID per delivery. Not stable across retries of your own processing — it identifies the delivery, not the gift card.
GiftCardIdstringWrapped's ID for the card. Use this with GET /api/GiftCard/GetById/{id}.
CodestringThe gift card code.
CreatedAtdatetimeWhen the card was created.
InitialValue / FormattedInitialValuenumber / stringThe value the card started with; formatted in the account's currency.
Balance / FormattedBalancenumber / stringThe balance after whatever triggered this delivery.
TotalIssuedAmount / FormattedTotalIssuedAmountnumber / stringEverything ever loaded onto the card, including top-ups.
CurrencystringThe card's currency.
ExpiresAtUtcdatetime, nullableNull when the card doesn't expire.
RecipientName, RecipientEmailAddressstring, nullableWho the card is for.
BuyerName, BuyerEmailstringWho it's from. Falls back to the recipient when the card wasn't gifted.
GiftCardMessagestring, nullableThe gift message.
StatusstringThe card's display status, for example Active, Redeemed, Voided, Expired.
IsPromotionalboolTrue for cards issued as promotional credit rather than sold.
IsStoreCreditboolTrue when this is a store credit account rather than a gift card.
AppleWalletUrl, GoogleWalletUrlstringWallet pass links for the recipient.
PdfUrlstringThe printable gift card.
ViewBalanceUrlstringThe public balance page for this card.
GiftToFriendUrlstring, nullableNull on store credit accounts, which can't be gifted on.
GiftCardBatchIdstring, nullableSet when the card came from a batch.
AutomationIdstring, nullableSet when an automation issued the card.
CampaignIdstring, nullableSet when a campaign sent the card.
ApiEventName, ApiEventPropertiesstring / object, nullableThe event that triggered the automation that issued this card, when it came from POST /api/AutomationTriggerEvents. ApiEventProperties is omitted entirely when empty.
WebhookTopicstringOne of the five topics above.

Verifying a delivery

If you set requestHeaderVerificationToken when creating the webhook, every delivery carries an HMAC-Signature-SHA256 header. Its value is the Base64-encoded HMAC-SHA256 of the raw request body, keyed with your token. The token itself is never sent.

Compute the signature over the bytes you received, before any JSON parsing or re-serialising — re-serialising changes whitespace and key order, and the signature won't match.

const crypto = require("crypto");

function isFromWrapped(rawBody, signatureHeader, token) {
  const expected = crypto.createHmac("sha256", token).update(rawBody, "utf8").digest("base64");
  const received = signatureHeader || "";
  return expected.length === received.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}

Without a token, deliveries are unsigned and anyone who learns your URL can post to it. Set one.

Delivery behaviour

  • Each delivery is attempted once. A failure is never retried, so don't rely on Wrapped to redeliver — return 2xx quickly and do your work afterwards.
  • A webhook that has failed six times over its lifetime is disabled and stops appearing in GET /api/Webhook/List. The count doesn't reset after a success, so those six failures can be spread over months. Create the webhook again once your endpoint is healthy.
  • Deliveries only go out while your Wrapped subscription is active.

Common questions

Can I subscribe to only one topic?

No. A webhook receives all five topics; filter on WebhookTopic at your end.

Why did I get two deliveries for the same change?

Each registered webhook receives its own delivery, so two webhooks on the same URL means two POSTs. Check GET /api/Webhook/List, and use RequestId to tell genuine duplicates apart.

My webhook stopped receiving anything. What happened?

Most likely it hit six lifetime failures and was disabled — it will no longer be in GET /api/Webhook/List. Fix your endpoint, then create the webhook again.

What does IsStoreCredit mean?

It marks the record as a balance account rather than a gift card. The payload is otherwise the same, except GiftToFriendUrl is null because those balances can't be gifted on.

Did this answer your question?