I can provide detailed guidance on implementing idempotency for reward redemptions in zs-2022. This involves three critical aspects:
1. Idempotency Key Usage
The reward redemption endpoint requires an idempotency key to prevent duplicate processing. Include this header with every redemption request:
Idempotency-Key: {unique_key_value}
POST /api/v2/loyalty/rewards/redeem
Key Generation Strategy:
Generate keys that are:
- Unique per redemption intent: Different redemptions must have different keys
- Consistent for retries: Same redemption retried should use same key
- Cryptographically random: Use UUID v4 or secure random generation
Recommended approach:
// Pseudocode - Key generation:
1. Generate UUID when user initiates redemption
2. Store UUID with redemption intent (database/cache)
3. Use same UUID for all retry attempts of that redemption
4. Generate new UUID only for new redemption intents
5. Include: redemption_id + customer_id + timestamp_hash
Example implementation:
- User clicks ‘Redeem’ → Generate UUID: `a1b2c3d4-e5f6-7890-abcd-ef1234567890
- Store in session/database with redemption details
- Send request with header: `Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890
- If request fails → Retry with SAME key
- New redemption → Generate NEW UUID
2. Reward Redemption Endpoint Requirements
The redemption endpoint has specific requirements:
Required Headers:
Content-Type: application/json
Authorization: Bearer {token}
Idempotency-Key: {uuid}
Request Payload:
{
"customer_id": "cust_12345",
"reward_id": "reward_67890",
"points_amount": 500,
"redemption_type": "discount"
}
Endpoint Behavior:
- Without idempotency key → 409 Duplicate Request error (as you’re seeing)
- With valid key (first attempt) → 200 Success, processes redemption
- With same key (retry) → 200 Success, returns original redemption result (doesn’t reprocess)
- With same key after 24 hours → 409 Conflict, key expired
3. Duplicate Request Handling
Client-Side Prevention:
- Disable UI controls after redemption initiated
- Show loading state during API call
- Generate idempotency key before request
- Store key with redemption intent for retry scenarios
Server-Side Handling:
Implement proper retry logic:
// Pseudocode - Retry with idempotency:
1. Generate and store idempotency key
2. Attempt redemption request with key
3. If network error or 5xx response:
- Retry with SAME idempotency key
- Use exponential backoff (1s, 2s, 4s)
- Max 3 retry attempts
4. If 409 Duplicate Request:
- Check if key matches stored key
- If yes: Likely race condition, fetch redemption status
- If no: Generate new key and retry
5. If 200 Success: Mark redemption complete
Race Condition Handling:
If you receive 409 even with proper idempotency key:
- Query redemption status: `GET /api/v2/loyalty/redemptions/{customer_id}
- Check if redemption already completed
- Verify points balance to confirm processing
Idempotency Key Management:
Storage Strategy:
- Store keys in database with redemption records
- Include: key, customer_id, reward_id, timestamp, status
- TTL: 24 hours (matches API idempotency window)
- Index by key for fast duplicate detection
Key Lifecycle:
- Generation: When user initiates redemption
- Active: During API call and retries (same key)
- Completed: After successful redemption (mark as processed)
- Expired: After 24 hours (can be reused)
Debugging Your Current Issue:
Since you’re getting false duplicates without idempotency keys, the API is likely using fallback duplicate detection based on:
- Customer ID + Reward ID + Timestamp proximity
- Request payload hash
- Session identifiers
This can trigger false positives if:
- Multiple requests sent within seconds
- Network retries without proper idempotency
- Load balancer duplicating requests
Immediate Fix:
- Add idempotency key header to all redemption requests
- Generate UUID v4 for each new redemption intent
- Store key with redemption record for retry consistency
- Implement client-side duplicate prevention (disable button)
- Add retry logic with exponential backoff using same key
Example Implementation:
POST /api/v2/loyalty/rewards/redeem
Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479
{
"customer_id": "cust_12345",
"reward_id": "reward_67890",
"points_amount": 500
}
With proper idempotency implementation, the API will correctly distinguish between:
- New redemptions (different keys) → Process normally
- Retries (same key) → Return original result without reprocessing
- Duplicates (different keys, same redemption) → Detect and prevent
This ensures customers can redeem rewards reliably even with network issues or UI race conditions.