Skip to Content

Gift card mapping

StagingGiftcard is a flat shape — code, value, expiry, optional recipient, and a debit history that’s passed through to Shopify unchanged.

Gift cards depend on the customer migration. The staging model declares requires_additional_mapping = customer so customer_id / recipient_id get rewritten from source IDs to Shopify GIDs at load time. Run the customer migration first.

Quick reference — minimum loadable gift card

{ "original_id": gift_card_id, "code": code, "initialValue": face_value }

Identity & value

codestring

The redemption code on the card. Must be unique per shop.

"code": code
initialValuenumber

The original face value at issue. Set once — Shopify computes current balance as initialValue minus the sum of debits.

"initialValue": face_value
expiresOnstring (ISO8601 date)

Expiry date. Omit for cards that never expire.

"expiresOn": expires_at
notestring

Internal admin note.

"note": "Migrated from " & source_platform

Customer & recipient

Source-platform IDs here. Graftport rewrites them to Shopify GIDs at load time.

customer_idstring

Source-platform customer ID for the cardholder. Resolved to a Shopify customer GID using the customer migration’s results.

"customer_id": customer_id
recipient_idstring

Source-platform customer ID for the gift recipient (when the card was purchased as a gift for someone else). Also resolved to a Shopify GID.

messagestring

Personal gift message.

preferredNamestring

What the recipient wants to be called in the card-delivery email.

Debit history (pass-through)

debitsobject[]

Array of past debit transactions. Each entry has Shopify’s DebitTransaction shape:

FieldNotes
processedAtISO8601 of when the debit happened.
noteOptional reason.
debitAmount{ amount, currencyCode }.
"debits": redemptions.{ "processedAt": redeemed_at, "note": "Order " & $string(order_id), "debitAmount": { "amount": $string(amount), "currencyCode": currency } }

Patterns

Source has just code + balance (no debit history)

If the source only tracks current balance, issue at the current balance and skip debits — the customer-visible amount is preserved even though the history is lost:

{ "original_id": gift_card_id, "code": code, "initialValue": current_balance, "expiresOn": expires_at, "note": "Migrated from " & source_platform & " — balance preserved, history dropped" }

Source has full debit history

{ "original_id": gift_card_id, "code": code, "initialValue": original_amount, "expiresOn": expires_at, "customer_id": customer_id, "debits": redemptions.{ "processedAt": redeemed_at, "note": "Order " & $string(order_id), "debitAmount": { "amount": $string(amount), "currencyCode": currency } } }

Gift purchased for someone else

{ "original_id": gift_card_id, "code": code, "initialValue": face_value, "customer_id": purchaser_customer_id, "recipient_id": recipient_customer_id, "preferredName": recipient_name, "message": gift_message }

Gotchas

Gift cards are real money. Always extract + dry-run transform first; spot-check a sample of staged records to confirm values and balances are right before loading.

  • initialValue is set once and can’t be changed. Decide upfront whether to issue at original face value (preserves history via debits) or current balance (drops history). Document the choice for the merchant.
  • Code uniqueness is enforced. Duplicates fail the load. Suffix in the mapping if your source allows duplicate codes.
  • customer_id / recipient_id are source IDs, not Shopify GIDs. Graftport rewrites them — but only if those customers were migrated. If the customer wasn’t migrated, the link drops to null.
  • Currency. Each Shopify shop has a single gift card currency. Multi-currency cards from the source need to be converted in the mapping.
  • Expired cards. Setting expiresOn in the past creates an already-expired card on Shopify. Usually fine — preserves the historical state — but customers can’t redeem.
  • Debits are pass-through validated. Each entry runs through Shopify’s DebitTransaction schema; malformed entries (missing debitAmount, unparseable processedAt) fail the row.
Last updated on