Skip to main content

Gift Card Webhook Events

Overview

The gateway emits eight gift-card lifecycle events. All events fire asynchronously through the standard webhook delivery pipeline (signed HMAC body with delivery retries). Subscribe via the Webhooks page in the merchant dashboard or via WebhookSubscriptionsApi in either SDK.

All payloads are JSON. All currency amounts are integer cents in the gift card's own currency (USD today; the gateway is currency-aware). All identifiers are the gateway-assigned IDs (string for giftCardId, UUID string for transaction IDs).

Event types

gift_card.issued

Fires once when a new gift card is issued (single-issue or each row of a bulk-issue stream). The card's plaintext number is never included — only last4 for display.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "giftCardTransactionId": "8f2c...-uuid",
  "initialBalanceCents": 5000,
  "currency": "USD",
  "expiresAt": "2027-04-19T00:00:00Z",
  "issuedAtLocationId": "loc_01HX...",
  "issuedToCustomerId": null,
  "last4": "3452",
  "actorType": "STAFF",
  "actorId": "user_01HX..."
}

gift_card.redeemed

Fires when a card is debited at the point of sale or via online checkout. amountCents is the positive redemption amount; the underlying ledger row stores it as a negative delta but we publish the absolute value to keep downstream accounting code symmetrical with gift_card.refunded.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "giftCardTransactionId": "8f2c...-uuid",
  "amountCents": 1500,
  "balanceAfterCents": 3500,
  "locationId": "loc_01HX...",
  "transactionId": "txn-uuid",
  "actorType": "SYSTEM",
  "actorId": "processing@gateway"
}

gift_card.balance_low

Fires once per crossing of lowBalanceThresholdCents (configurable in the GiftCardConfig). Edge-triggered: the previous balance must be above the threshold and the current balance at or below it. Reloads do not re-arm the trigger until the balance climbs back above the threshold.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "giftCardTransactionId": "8f2c...-uuid",
  "currentBalanceCents": 250,
  "thresholdCents": 500,
  "actorType": "SYSTEM",
  "actorId": "processing@gateway"
}

gift_card.reloaded

Fires when a card balance is topped up via the reload endpoint, requires a funding transaction in CAPTURED or SETTLED status with matching currency.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "giftCardTransactionId": "8f2c...-uuid",
  "amountCents": 2500,
  "previousBalanceCents": 500,
  "balanceAfterCents": 3000,
  "locationId": "loc_01HX...",
  "fundingTransactionId": "txn-uuid",
  "actorType": "STAFF",
  "actorId": "user_01HX..."
}

gift_card.refunded

Fires when a refund of the original sale routes value back to a gift card (direct path — see "Refund reroutes" below for the alternate path). amountCents is the positive credit applied to the card.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "giftCardTransactionId": "8f2c...-uuid",
  "amountCents": 1500,
  "balanceAfterCents": 5000,
  "transactionId": "refund-txn-uuid",
  "actorType": "SYSTEM",
  "actorId": "anonymous"
}

gift_card.expired

Fires when expiry processing reaches a card whose expiresAt has passed and whose status is ACTIVE or REDEEMED at sweep time. The card's status moves to EXPIRED and the balance is zeroed in a single atomic write.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "balanceAtExpiryCents": 1500,
  "expiredAt": "2026-04-19T03:01:42Z"
}

gift_card.revoked

Fires when an Org admin or platform admin revokes a card (lost, fraud, customer return). The card's status moves to REVOKED and the balance is zeroed; the balanceAtRevocationCents field captures what was forfeited so accounting can post a breakage entry.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "balanceAtRevocationCents": 1500,
  "reason": "customer reported lost",
  "actorType": "STAFF",
  "actorId": "user_01HX..."
}

gift_card.adjusted

Fires when an Org admin or platform admin adjusts a card balance manually (promo bump, dispute resolution, write-off). amountCents is signed: positive for credits, negative for debits. The card's status follows: a card driven to zero with reload disabled flips to REDEEMED; a positive adjustment from REDEEMED flips back to ACTIVE.

{
  "organizationId": "org_abc",
  "giftCardId": "gc_01HX...",
  "amountCents": 500,
  "balanceAfterCents": 2500,
  "reason": "promo bump",
  "actorType": "STAFF",
  "actorId": "user_01HX..."
}

Refund reroutes

A refund of the original sale normally routes the gift-card portion back to the gift card (gift_card.refunded fires). When the gift card is REVOKED or EXPIRED at refund time, the gift-card allocation is rerouted to the primary tender instead. In that case:

  • gift_card.refunded does not fire for the rerouted allocation.
  • The refund transaction's metadata gains a gift_card_refund_reroutes array describing the rerouted allocations (giftCardId, originalGiftCardTransactionId, amountCents).

Delivery semantics

PropertyValue
Delivery guaranteeAt-least-once
OrderingNot guaranteed across cards; per-card events arrive in source order on the writer side, but webhook delivery is concurrent
RetriesStandard webhook retry policy (exponential backoff, max 24h)
SignatureHMAC-SHA256 over the raw body, header X-Gateway-Signature
Idempotency keygiftCardTransactionId is unique per ledger row — use it to de-duplicate issued/redeemed/reloaded/refunded

For events without a giftCardTransactionId, deduplicate by the delivery's event identity, not a balance alone. Arrival order is not an accounting guarantee.

See Event log and replay.