This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.
Gift Cards API
Complete API for managing gift cards including creation, redemption, PIN security, balance transfers, eGift digital delivery, and fraud prevention.
Base Path: /api/v1/gift-cards
Overview
The Gift Cards API provides:
| Feature | Description |
|---|---|
| Card Management | Create, list, search gift cards |
| Balance Operations | Load, redeem, adjust, transfer balances |
| PIN Security | Optional 4-digit PIN for online redemption |
| eGift Delivery | Digital gift cards via email/SMS |
| Fraud Prevention | Freeze/unfreeze cards for suspicious activity |
| Transaction History | Full audit trail of all operations |
Gift Card Status
| Status | Code | Description |
|---|---|---|
| Active | active | Card is usable |
| Frozen | frozen | Card temporarily disabled |
| Expired | expired | Past expiration date |
| Redeemed | redeemed | Zero balance, fully used |
Transaction Types
| Type | Code | Description |
|---|---|---|
| Load | load | Adding funds to card |
| Redeem | redeem | Using funds for payment |
| Adjustment | adjustment | Manager balance correction |
Create Gift Card
Create a new gift card with optional auto-generated code.
POST /api/v1/gift-cards
Authorization: Bearer {access_token}
Content-Type: application/json
{
"code": null,
"initial_balance": 50.00,
"currency": "USD",
"expires_at": "2027-12-31T23:59:59Z",
"pin": "1234"
}
| Field | Type | Required | Description |
|---|---|---|---|
code | string | No | Custom code (16 chars) or auto-generated |
initial_balance | decimal | Yes | Starting balance |
currency | string | No | Currency code (default: USD) |
expires_at | datetime | No | Expiration date |
pin | string | No | 4-digit PIN for online security |
Response (201 Created)
{
"card": {
"id": "gc-abc123",
"tenant_id": "tenant-xyz",
"code_hash": "sha256:abcdef...",
"last_4": "7890",
"current_balance": 50.00,
"currency": "USD",
"status": "active",
"expires_at": "2027-12-31T23:59:59Z",
"pin_enabled": true,
"metadata": {},
"created_at": "2026-01-23T12:00:00Z",
"updated_at": "2026-01-23T12:00:00Z"
},
"code": "GIFT-1234-5678-7890"
}
The plaintext code is only returned on creation. Store it securely or give it to the customer immediately. It cannot be retrieved later.
List Gift Cards
List all gift cards for the tenant.
GET /api/v1/gift-cards?limit=50&offset=0
Authorization: Bearer {access_token}
| Parameter | Type | Description |
|---|---|---|
limit | integer | Max results (default: 50) |
offset | integer | Pagination offset |
Response
[
{
"id": "gc-abc123",
"last_4": "7890",
"current_balance": 42.50,
"currency": "USD",
"status": "active",
"pin_enabled": true,
"created_at": "2026-01-23T12:00:00Z"
}
]
Get Gift Card
Get details of a specific gift card by ID.
GET /api/v1/gift-cards/{id}
Authorization: Bearer {access_token}
Response
{
"id": "gc-abc123",
"tenant_id": "tenant-xyz",
"code_hash": "sha256:abcdef...",
"last_4": "7890",
"current_balance": 42.50,
"currency": "USD",
"status": "active",
"expires_at": "2027-12-31T23:59:59Z",
"pin_enabled": true,
"metadata": {
"purchased_by": "John Smith",
"purchase_order_id": "order-456"
},
"created_at": "2026-01-23T12:00:00Z",
"updated_at": "2026-01-23T14:30:00Z"
}
Search Gift Cards
Search for gift cards by code, last-4 digits, or transaction ID.
GET /api/v1/gift-cards/search?q=7890
Authorization: Bearer {access_token}
| Parameter | Type | Description |
|---|---|---|
q | string | Search query |
Searches match:
- Full gift card code
- Last 4 digits
- Transaction ID
Response
{
"cards": [
{
"id": "gc-abc123",
"last_4": "7890",
"current_balance": 42.50,
"status": "active"
}
]
}
Check Balance
Check the balance of a gift card by code.
POST /api/v1/gift-cards/balance
Authorization: Bearer {access_token}
Content-Type: application/json
{
"code": "GIFT-1234-5678-7890"
}
Response
{
"id": "gc-abc123",
"last_4": "7890",
"current_balance": 42.50,
"currency": "USD",
"status": "active",
"expires_at": "2027-12-31T23:59:59Z"
}
Redeem Gift Card
Use gift card balance for payment.
POST /api/v1/gift-cards/redeem
Authorization: Bearer {access_token}
Content-Type: application/json
{
"code": "GIFT-1234-5678-7890",
"amount": 25.00,
"order_id": "order-12345",
"location_id": "loc-abc",
"pin": "1234"
}
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes* | Gift card code |
code_hash | string | Yes* | Or code hash directly |
amount | decimal | Yes | Amount to redeem |
order_id | UUID | No | Associated order |
location_id | UUID | No | Redemption location |
pin | string | Conditional | Required if pin_enabled |
*Either code or code_hash is required.
Response
{
"id": "gc-abc123",
"current_balance": 17.50,
"amount_redeemed": 25.00,
"status": "active"
}
PIN Validation
If the card has pin_enabled: true, the PIN must be provided:
- Correct PIN: Transaction proceeds
- Incorrect PIN: Error returned
- Missing PIN: Error returned
Load Gift Card
Add funds to an existing gift card.
POST /api/v1/gift-cards/{id}/load
Authorization: Bearer {access_token}
Content-Type: application/json
{
"amount": 25.00,
"location_id": "loc-abc",
"reason": "Birthday bonus reload"
}
Response
{
"id": "gc-abc123",
"current_balance": 67.50,
"amount_loaded": 25.00,
"status": "active"
}
Adjust Balance
Manager-only balance adjustment for corrections.
Permissions Required: tenant_admin, commerce_manager, manager
POST /api/v1/gift-cards/adjust
Authorization: Bearer {access_token}
Content-Type: application/json
{
"code": "GIFT-1234-5678-7890",
"amount": -5.00,
"reason": "Customer service credit",
"location_id": "loc-abc"
}
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Gift card code |
amount | decimal | Yes | Adjustment amount (positive or negative) |
reason | string | Yes | Audit reason for adjustment |
location_id | UUID | No | Location where adjustment made |
Response
{
"id": "gc-abc123",
"current_balance": 62.50,
"adjustment_amount": -5.00,
"reason": "Customer service credit"
}
Transfer Balance
Transfer balance from one gift card to another (lost card replacement).
Permissions Required: tenant_admin, commerce_manager, manager
POST /api/v1/gift-cards/transfer
Authorization: Bearer {access_token}
Content-Type: application/json
{
"source_code": "GIFT-1111-2222-3333",
"destination_code": "GIFT-4444-5555-6666",
"amount": null,
"reason": "Lost card replacement"
}
| Field | Type | Required | Description |
|---|---|---|---|
source_code | string | Yes | Source gift card code |
destination_code | string | Yes | Destination gift card code |
amount | decimal | No | Amount to transfer (null = full balance) |
reason | string | Yes | Audit reason for transfer |
Response
{
"source_card": {
"id": "gc-source",
"last_4": "3333",
"current_balance": 0.00,
"status": "redeemed"
},
"destination_card": {
"id": "gc-dest",
"last_4": "6666",
"current_balance": 75.00,
"status": "active"
},
"amount_transferred": 75.00
}
Set PIN
Set or update PIN for a gift card.
POST /api/v1/gift-cards/{id}/pin
Authorization: Bearer {access_token}
Content-Type: application/json
{
"code": "GIFT-1234-5678-7890",
"pin": "4567"
}
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Gift card code (verification) |
pin | string | Yes | 4-digit PIN to set |
Response
{
"id": "gc-abc123",
"pin_enabled": true,
"updated_at": "2026-01-23T15:00:00Z"
}
- PIN is hashed before storage (never stored in plaintext)
- 4 digits only (0-9)
- Required for online/app redemptions when enabled
- In-person POS redemptions may bypass PIN
Get Transactions
Get transaction history for a gift card.
GET /api/v1/gift-cards/{id}/transactions
Authorization: Bearer {access_token}
Response
{
"transactions": [
{
"id": "txn-001",
"tenant_id": "tenant-xyz",
"card_id": "gc-abc123",
"transaction_type": "load",
"amount": 50.00,
"order_id": null,
"location_id": "loc-abc",
"reason": "Initial purchase",
"metadata": {},
"created_at": "2026-01-23T12:00:00Z"
},
{
"id": "txn-002",
"tenant_id": "tenant-xyz",
"card_id": "gc-abc123",
"transaction_type": "redeem",
"amount": -25.00,
"order_id": "order-12345",
"location_id": "loc-def",
"reason": null,
"metadata": {},
"created_at": "2026-01-23T14:30:00Z"
}
]
}
Send eGift
Send a digital gift card via email or SMS.
POST /api/v1/gift-cards/send
Authorization: Bearer {access_token}
Content-Type: application/json
{
"amount": 50.00,
"currency": "USD",
"recipient_email": "recipient@example.com",
"recipient_phone": "+15551234567",
"sender_name": "John Smith",
"recipient_name": "Jane Doe",
"message": "Happy Birthday! Enjoy dinner on me!",
"delivery_method": "email",
"scheduled_at": "2026-02-14T09:00:00Z",
"design_template_id": "birthday-01"
}
| Field | Type | Required | Description |
|---|---|---|---|
amount | decimal | Yes | Gift card amount |
currency | string | No | Currency code (default: USD) |
recipient_email | string | Conditional | Email for delivery |
recipient_phone | string | Conditional | Phone for SMS delivery |
sender_name | string | Yes | Sender's name |
recipient_name | string | Yes | Recipient's name |
message | string | No | Personal message |
delivery_method | enum | No | email, sms, both (default: email) |
scheduled_at | datetime | No | Future delivery time |
design_template_id | string | No | Email template design |
Response (201 Created)
{
"card": {
"id": "gc-egift-123",
"last_4": "4567",
"current_balance": 50.00,
"status": "active"
},
"code": "GIFT-EGFT-1234-4567",
"delivery_status": "scheduled",
"scheduled_at": "2026-02-14T09:00:00Z"
}
eGift Delivery Status
| Status | Code | Description |
|---|---|---|
| Pending | pending | Awaiting processing |
| Scheduled | scheduled | Set for future delivery |
| Sent | sent | Email/SMS sent |
| Delivered | delivered | Confirmed received |
| Failed | failed | Delivery failed |
Freeze Gift Card
Temporarily disable a gift card for fraud prevention or customer request.
Permissions Required: tenant_admin, commerce_manager, manager, fraud_analyst
POST /api/v1/gift-cards/{id}/freeze
Authorization: Bearer {access_token}
Content-Type: application/json
{
"reason": "Suspicious redemption pattern detected"
}
Response
{
"card": {
"id": "gc-abc123",
"status": "frozen",
"current_balance": 42.50
},
"frozen_at": "2026-01-23T16:00:00Z",
"reason": "Suspicious redemption pattern detected"
}
When to Freeze
- Multiple failed PIN attempts
- Unusual redemption locations
- Customer reports lost/stolen
- Fraud detection alerts
Unfreeze Gift Card
Re-enable a frozen gift card.
Permissions Required: tenant_admin, commerce_manager, manager, fraud_analyst
POST /api/v1/gift-cards/{id}/unfreeze
Authorization: Bearer {access_token}
Content-Type: application/json
{
"reason": "Customer verified identity"
}
Response
{
"card": {
"id": "gc-abc123",
"status": "active",
"current_balance": 42.50
},
"unfrozen_at": "2026-01-23T17:00:00Z",
"reason": "Customer verified identity"
}
Error Responses
Insufficient Balance (400)
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Gift card balance is insufficient for this transaction",
"available_balance": 17.50,
"requested_amount": 25.00
}
}
Invalid PIN (401)
{
"error": {
"code": "INVALID_PIN",
"message": "The PIN provided is incorrect"
}
}
Card Frozen (400)
{
"error": {
"code": "CARD_FROZEN",
"message": "This gift card is frozen and cannot be used"
}
}
Card Expired (400)
{
"error": {
"code": "CARD_EXPIRED",
"message": "This gift card has expired",
"expired_at": "2025-12-31T23:59:59Z"
}
}
Forbidden (403)
{
"error": {
"code": "FORBIDDEN",
"message": "Insufficient permissions"
}
}
Security Best Practices
Code Storage
- Gift card codes are hashed (SHA-256) before storage
- Plaintext codes are only returned on creation
last_4field allows card identification
PIN Security
- PINs are hashed before storage
- 4-digit numeric only
- Enable for online/app redemptions
- Consider bypassing for in-person POS
Fraud Prevention
- Monitor redemption patterns
- Use freeze for suspicious activity
- Require manager approval for large transfers
- Log all adjustment reasons
Related Documentation
- Payments API - Using gift cards in payments
- Staff Gift Card Guide - Staff operations
- Customer Gift Card Guide - Customer usage