Skip to main content

POS Gift Cards

This page documents the gateway-side shape POS must mirror for gift-card redemption and refund flows.

Runtime boundary

POS redeems gift cards through the normal merchant OAuth surface on the pay host:

  • GatewayPayClient.giftCards.redeem(...)
  • GatewayPayClient.giftCards.redeemForLocation(...)
  • GatewayPayClient.giftCards.refundForLocation(...)
  • GatewayPayClient.locations.redeemGiftCard(...)
  • GatewayPayClient.locations.refundGiftCard(...)

Those SDK methods call pay-host routes under /api/v1/gift-cards/... or /api/v1/locations/{locationId}/gift-cards/... with the caller's Gateway OAuth token. The online-txn service authorizes the token against gift_cards:write and the requested location/organization, then relays to processing over Gateway service-to-service auth. Processing remains internal-only.

Current behavior

TopicCurrent behavior
Scope modelGift cards are organization-scoped
Redemption across locationsAllowed within the same organization
Location restriction enforcementEnforced through the per-organization location deny list
FX / mixed-currency redemptionNot supported
Number-prefix / number-length configEffectively platform-admin-only today
Refund fallback when card credit cannot be restoredImplemented via reroute to the primary tender

Auth requirements

The required auth shape is:

  1. POS uses a Gateway OAuth access token that includes gift_cards:write.
  2. The token must be location-scoped to the requested location or organization-scoped to that location's organization.
  3. online-txn relays to processing's internal gift-card endpoint with its Gateway service account.

External POS runtimes should not call Gateway's internal gift-card routes or present Google IAM caller identity to redeem cards. Those internal routes are a service-to-service boundary only.

Expected redemption flow

  1. POS identifies the current location and transaction.
  2. POS calls GatewayPayClient.giftCards.redeemForLocation(...) or GatewayPayClient.locations.redeemGiftCard(...) with:
    • locationId
    • amountCents
    • transactionId
    • idempotency key derived from the POS ticket
  3. Gateway validates that the gift card’s organization matches the transaction location’s organization.
  4. Gateway writes the ledger mutation and returns the resulting balance.

Refunds use a location-scoped route through GatewayPayClient.giftCards.refundForLocation(...) or GatewayPayClient.locations.refundGiftCard(...).

Location restrictions

Gift-card location restrictions are enforced at redemption time.

In practice that means:

  • a card can still be redeemed across locations in the same organization by default
  • once a location is marked restricted for that organization, redemption from that location is rejected by the gateway with a gift-card validation error

Integration implication:

  • POS can rely on the gateway to block redemption from restricted same-org locations
  • a different allowlist model is a policy change, not a missing enforcement gap

Currency behavior

Gift-card redemption and reload flows are same-currency only. There is no gateway-side FX conversion path during redemption, reload, or refund-to-card.

Integration implication:

  • POS should not offer a cross-currency gift-card redemption path and expect the gateway to convert values
  • if a tender mix spans currencies, resolve that in product design before assuming the gateway can settle it

Numbering and config ownership

Gift-card configuration supports number-prefix and number-length fields, but the management proxy strips those fields from ordinary merchant-managed updates. As shipped today, custom numbering should be treated as a platform-admin-managed operation, not a self-serve merchant or POS capability.

Refund reroute behavior

If a refund cannot restore value to the original gift card because the card is REVOKED or EXPIRED, the gateway reroutes that allocation back to the primary tender instead of silently dropping value.

See Gift Card Webhook Events for the related eventing and observability behavior.

Unsupported current behavior

The following should still be treated as unavailable unless and until runtime behavior changes:

  • a separate gift-card transfer endpoint
  • Apple Wallet or Google Wallet gift-card passes

Current support claims

Support, solutions, and integrators can safely describe the current gift-card lane like this:

  • gift cards are organization-scoped
  • redemption works across locations in the same organization
  • custom numbering is not a normal merchant self-serve feature
  • FX conversion is not part of redemption or refund
  • refund value reroutes to the primary tender if the original card cannot take it

They should not describe the current lane as:

  • same-location-only redemption enforced by the gateway
  • transfer-capable between cards
  • wallet-pass enabled for Apple Wallet or Google Wallet

Validation coverage

Gateway keeps a dedicated smoke test for this path:

  • //services/processing:pos_gift_card_smoke_integration_test

Run it manually with:

  • bazel test //services/processing:pos_gift_card_smoke_integration_test

That test exercises:

  • gift-card issuance setup on the gateway side
  • cross-location redemption inside one organization
  • idempotent retry
  • refund back onto the card
  • webhook emission for redeem/refund
  • the online-txn OAuth route and internal InternalServiceClient -> processing GiftCardService hop

The target is tagged manual because POS release validation invokes it on demand rather than in the default suite.