Skip to main content

MagicWeave SDK: Player Store (apps/client/client_store)

This guide is for game developers integrating the MagicWeave player store into their game.

The client_store module lets players:

  • browse currently redeemable store items
  • redeem items using gems
  • receive fulfillment output (for example voucher code/pin)

Base URL and Route Prefix

Use one of these deployment styles:

  • Split client API deployment: http://localhost:8001
  • Combined deployment: http://localhost:8000/client

Store routes are under:

  • /store

Examples:

  • GET http://localhost:8001/store
  • POST http://localhost:8001/store/redeem

Required Authentication and Headers

All store endpoints require:

  • x-client-id: <your_project_client_id>
  • x-client-secret: <your_project_client_secret>
  • Authorization: Bearer <magicweave_access_token>

The authenticated user also needs the client.store permission.

For redemption retries, send:

  • Idempotency-Key: <stable-unique-key-per-purchase-attempt>

If you do not pass Idempotency-Key, the server generates one automatically, but then retries from your client cannot be safely deduplicated.

Endpoint 1: List Store Items

GET /store

Returns active items that are currently available and in stock.

Filtering rules used by backend:

  • item must be is_active = true
  • available_from must be null or in the past
  • available_until must be null or in the future
  • item must be in stock

Response shape:

{
"items": [
{
"id": 12,
"name": "Amazon INR 100",
"description": "Gift card",
"item_type": "voucher",
"brand_name": "Amazon",
"image_url": "https://cdn.example.com/amazon-100.png",
"gem_cost": 150,
"is_featured": true,
"available_from": "2026-04-01T00:00:00Z",
"available_until": null,
"stock_remaining": 25,
"in_stock": true
}
]
}

stock_remaining semantics:

  • finite integer for limited stock
  • null when stock is effectively unlimited

Reference: List store items

Endpoint 2: Redeem Store Item

POST /store/redeem

Request body:

{
"store_item_id": 12,
"shipping_address": null
}

shipping_address is required when the item uses webhook/physical fulfillment.

Physical example:

{
"store_item_id": 99,
"shipping_address": {
"name": "Rahul Nema",
"line1": "123 MG Road",
"line2": "Near Metro",
"city": "Bengaluru",
"state": "Karnataka",
"pincode": "560001",
"phone": "+919999999999"
}
}

Response shape:

{
"id": 834,
"status": "fulfilled",
"gem_cost_at_time": 150,
"fulfillment_data": {
"code": "AMZN-XXXX-YYYY",
"pin": "1234"
}
}

Redemption Behavior

When redeeming:

  1. Server validates item existence and availability window.
  2. Server checks stock and per-player limit.
  3. Server checks wallet gems.
  4. Server deducts gems and records wallet transaction.
  5. Server creates redemption record.
  6. Fulfillment output depends on fulfillment strategy:
    • code_pool: code is claimed immediately, response often returns status = fulfilled with code/pin
    • other strategies (for example webhook/provider): response is usually status = pending until downstream fulfillment

Reference: Redeem store item

Idempotency (Critical for Production)

Use a unique Idempotency-Key per user purchase attempt and reuse the same key for retries of the same attempt.

Behavior:

  • same key + same user returns existing redemption (safe retry)
  • same key reused by different user returns 409

Recommended key format:

  • <user-id>:<store-item-id>:<client-order-id>

Common Error Codes

  • 400:
    • store item not found
    • item unavailable (inactive/not yet available/expired)
    • sold out
    • per-player limit reached
    • shipping address missing for webhook item
  • 401: missing/invalid project headers or bearer token
  • 402: insufficient gems
  • 403: user lacks client.store permission
  • 409:
    • idempotency key conflict
    • concurrent sellout race (This item just sold out; please try again)

cURL Examples

List Items

curl -X GET "http://localhost:8001/store" \
-H "x-client-id: <client-id>" \
-H "x-client-secret: <client-secret>" \
-H "Authorization: Bearer <access-token>"

Redeem Voucher

curl -X POST "http://localhost:8001/store/redeem" \
-H "x-client-id: <client-id>" \
-H "x-client-secret: <client-secret>" \
-H "Authorization: Bearer <access-token>" \
-H "Idempotency-Key: user-42:item-12:order-1001" \
-H "Content-Type: application/json" \
-d '{"store_item_id":12}'

Redeem Physical Item

curl -X POST "http://localhost:8001/store/redeem" \
-H "x-client-id: <client-id>" \
-H "x-client-secret: <client-secret>" \
-H "Authorization: Bearer <access-token>" \
-H "Idempotency-Key: user-42:item-99:order-1002" \
-H "Content-Type: application/json" \
-d '{"store_item_id":99,"shipping_address":{"name":"Rahul Nema","line1":"123 MG Road","city":"Bengaluru","state":"Karnataka","pincode":"560001","phone":"+919999999999"}}'

Integration Notes for Game Teams

  • Fetch /store on store screen open and periodically refresh for stock/time changes.
  • Always send Idempotency-Key for redeem requests.
  • Deduct gems in UI only after server confirmation; server is source of truth.
  • Handle 402 with an upsell flow (earn gems / buy gems / engage in game loops).
  • For pending redemptions, show "processing" state and poll your redemption history endpoint when available.