Phoenix Gamification
Rewards

Creating Rewards

This guide explains how to create rewards in your catalog that users can purchase or receive as grants.

This guide explains how to create rewards in your catalog that users can purchase or receive as grants.

Overview

Rewards are created through the Admin API. Each reward needs:

  • A unique slug identifier
  • A name and optional description
  • A fulfillment method (how the reward is delivered)
  • Optional purchase configuration (if users can buy it)
  • Optional required fields (if you need user information)

Endpoint

POST /v1/rewards-catalog?tenant_id=${tenant_id}

Basic Reward Creation

Example: XP Boost (Wallet Fulfillment)

This reward automatically grants 100 XP to the user's wallet when purchased or granted.

{
  "slug": "xp-boost-100",
  "name": "100 XP Boost",
  "description": "Instant 100 XP boost for your account",
  "image_url": "https://example.com/images/xp-boost.png",
  "active": true,
  "fields": [],
  "fulfillment": {
    "type": "wallet",
    "item_type": "xp",
    "amount": 100
  },
  "requires_claim": false,
  "purchase": {
    "prices": [
      { "currency": "gold_coins", "amount": 50 }
    ]
  },
  "stock": null,
  "config": {}
}

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "tenant_id": "your_tenant",
  "slug": "xp-boost-100",
  "name": "100 XP Boost",
  "description": "Instant 100 XP boost for your account",
  "image_url": "https://example.com/images/xp-boost.png",
  "active": true,
  "fields": [],
  "fulfillment": {
    "type": "wallet",
    "item_type": "xp",
    "amount": 100
  },
  "requires_claim": false,
  "purchase": {
    "prices": [
      { "currency": "gold_coins", "amount": 50 }
    ]
  },
  "stock": null,
  "config": {},
  "created_at": "2026-01-28T10:00:00Z",
  "updated_at": "2026-01-28T10:00:00Z"
}

Fulfillment Types

Wallet Fulfillment

Automatically grants items to the user's wallet. Use this for virtual rewards like XP, badges, or currency.

For XP:

{
  "type": "wallet",
  "item_type": "xp",
  "amount": 100
}

For Badges:

{
  "type": "wallet",
  "item_type": "badge",
  "item_id": "vip_badge_2026"
}

For Currency:

{
  "type": "wallet",
  "item_type": "currency",
  "currency_id": "gems",
  "amount": 500
}

Manual Fulfillment

For physical items that require admin action (shipping, processing, etc.).

{
  "type": "manual",
  "notes": "Ship to user's address"
}

When using manual fulfillment, admins update order status through the Admin API when items are shipped or delivered.

API Fulfillment

Calls your webhook for external fulfillment. Useful for third-party integrations.

{
  "type": "api",
  "retry": {
    "max_attempts": 3,
    "backoff_seconds": [60, 300, 900]
  }
}

The system will call your webhook with order details and retry if the call fails.

Purchase Configuration

If you want users to be able to purchase the reward, include a purchase object:

{
  "purchase": {
    "prices": [
      { "currency": "gold_coins", "amount": 500 },
      { "currency": "gems", "amount": 100 }
    ]
  }
}

You can specify multiple currencies, allowing users to pay with different types of currency.

Grant-Only Rewards: If you omit the purchase field, the reward can only be granted (not purchased). This is useful for exclusive rewards from leaderboards or achievements.

Required Fields

If you need information from users (like phone number for airtime or address for shipping), define fields:

{
  "fields": [
    {
      "name": "phone_number",
      "label": "Phone Number",
      "required": true,
      "type": "text",
      "pattern": "^\\+251[0-9]{9}$",
      "placeholder": "+251912345678"
    },
    {
      "name": "address",
      "label": "Shipping Address",
      "required": true,
      "type": "text",
      "multiline": true,
      "max_length": 500
    }
  ]
}

Field Types:

  • text - Single-line or multi-line text input
  • select - Dropdown with options

When a reward has required fields, users must claim the order and provide the information before fulfillment begins.

Stock Management

Limit how many of a reward are available:

{
  "stock": 1000
}

Set to null for unlimited stock. Stock automatically decreases when orders are created.

Examples

Airtime Top-up (API Fulfillment)

{
  "slug": "airtime-topup",
  "name": "Airtime Top-up",
  "description": "Mobile airtime for any network",
  "image_url": "https://example.com/airtime.png",
  "active": true,
  "fields": [
    {
      "name": "phone_number",
      "label": "Phone Number",
      "required": true,
      "type": "text",
      "pattern": "^\\+251[0-9]{9}$"
    }
  ],
  "fulfillment": {
    "type": "api",
    "retry": {
      "max_attempts": 3,
      "backoff_seconds": [60, 300, 900]
    }
  },
  "requires_claim": false,
  "purchase": {
    "prices": [
      { "currency": "gold_coins", "amount": 500 }
    ]
  },
  "stock": 1000,
  "config": {
    "amount_etb": 10,
    "networks": ["ethio-telecom", "safaricom"]
  }
}

VIP Badge (Grant Only)

{
  "slug": "vip-badge",
  "name": "VIP Badge",
  "description": "Exclusive VIP status badge",
  "image_url": "https://example.com/vip-badge.png",
  "active": true,
  "fields": [],
  "fulfillment": {
    "type": "wallet",
    "item_type": "badge",
    "item_id": "vip_badge_2026"
  },
  "requires_claim": false,
  "purchase": null,
  "stock": null,
  "config": {}
}

Physical Prize (Manual Fulfillment)

{
  "slug": "iphone-15-pro",
  "name": "iPhone 15 Pro",
  "description": "Latest iPhone model",
  "image_url": "https://example.com/iphone.png",
  "active": true,
  "fields": [
    {
      "name": "shipping_address",
      "label": "Shipping Address",
      "required": true,
      "type": "text",
      "multiline": true
    }
  ],
  "fulfillment": {
    "type": "manual",
    "notes": "Ship via DHL"
  },
  "requires_claim": true,
  "purchase": {
    "prices": [
      { "currency": "gold_coins", "amount": 100000 }
    ]
  },
  "stock": 5,
  "config": {}
}

Updating Rewards

To update an existing reward:

PUT /v1/rewards-catalog/{reward_id}?tenant_id=${tenant_id}

Only include fields you want to update. All fields are optional.

{
  "name": "Updated Reward Name",
  "stock": 500,
  "active": true
}

Best Practices

  1. Use descriptive slugs - Make slugs easy to understand (e.g., xp-boost-100 not r1)
  2. Set appropriate stock limits - Use stock management for limited items
  3. Validate fields - Use patterns and validation to ensure correct user input
  4. Test fulfillment - Test wallet fulfillment with small amounts first
  5. Handle errors gracefully - Plan for out-of-stock and insufficient balance scenarios

Next Steps

On this page