Creating Coupon Codes
This guide explains how to create coupon definitions and generate coupons for users via the Admin Gateway.
Authentication
Coupon admin endpoints require admin-level authentication:
Option 1: Admin JWT (Recommended)
POST /v1/tenants/{tenant_id}/coupons
Authorization: Bearer <admin_jwt_token>
Content-Type: application/jsonThe JWT must contain in its payload:
sub_type:"admin"sub_id: API key UUID (returned when creating the API key)- Signed with the API key value (the plaintext key like
pk_abc123...)
Option 2: API Key Header (Server-to-Server)
POST /v1/tenants/{tenant_id}/coupons
X-API-Key: {api_key}
Content-Type: application/jsonPrerequisites: Create a Reward Item
Before creating a coupon, you need a reward item that the coupon will grant:
POST /v1/tenants/{tenant_id}/rewards
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"name": "100 Bonus Points",
"description": "Grants 100 bonus points to the user",
"reward_type": "points",
"payload": {
"amount": 100
}
}Response:
{
"item_id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "your-tenant-id",
"name": "100 Bonus Points",
"description": "Grants 100 bonus points to the user",
"reward_type": "points",
"payload": {"amount": 100},
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}Save the item_id - you'll need it for the coupon configuration.
Creating a Coupon Definition
Basic Reward Coupon
POST /v1/tenants/{tenant_id}/coupons
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"name": "Welcome Bonus",
"description": "Welcome bonus for new users",
"config": {
"reward_item_id": "550e8400-e29b-41d4-a716-446655440000",
"code_format": "random",
"code_prefix": "WELCOME",
"code_length": 8,
"usage_limit": {
"limit_type": "per_user",
"max_uses": 1
}
}
}Response:
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"tenant_id": "your-tenant-id",
"name": "Welcome Bonus",
"description": "Welcome bonus for new users",
"config": {
"reward_item_id": "550e8400-e29b-41d4-a716-446655440000",
"code_format": "random",
"code_prefix": "WELCOME",
"code_length": 8,
"case_sensitive": false,
"usage_limit": {
"limit_type": "per_user",
"max_uses": 1
}
},
"status": "active",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}Custom Promotional Code
For marketing campaigns with a specific code:
POST /v1/tenants/{tenant_id}/coupons
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"name": "New Year 2025 Promo",
"description": "Special New Year promotion",
"config": {
"reward_item_id": "550e8400-e29b-41d4-a716-446655440000",
"code_format": "custom",
"custom_code": "NEWYEAR2025",
"starts_at": "2025-01-01T00:00:00Z",
"expires_at": "2025-01-31T23:59:59Z",
"usage_limit": {
"limit_type": "unlimited"
}
}
}Auto-Generated Streak Reward
Automatically generate coupons when users hit streak milestones:
POST /v1/tenants/{tenant_id}/coupons
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"name": "7-Day Streak Reward",
"description": "Reward for maintaining a 7-day streak",
"config": {
"reward_item_id": "550e8400-e29b-41d4-a716-446655440000",
"code_format": "random",
"code_prefix": "STREAK7",
"code_length": 8,
"usage_limit": {
"limit_type": "per_user",
"max_uses": 1
},
"auto_generate": {
"enabled": true,
"trigger": "streak_milestone",
"trigger_config": {
"streak_id": "770e8400-e29b-41d4-a716-446655440002",
"milestone_threshold": 7
}
}
}
}Generating Coupons
Bulk Generation
Generate coupons for multiple users at once:
POST /v1/tenants/{tenant_id}/coupons/{definition_id}/generate
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"user_ids": ["user_123", "user_456", "user_789"]
}Response:
{
"generated": 3,
"coupons": [
{"user_id": "user_123", "code": "WELCOME8X4F2K9P"},
{"user_id": "user_456", "code": "WELCOMEJ7K2L5M3"},
{"user_id": "user_789", "code": "WELCOMEP9Q1R8S6"}
]
}Bulk Generation with Custom Codes
For custom code format, provide matching codes:
POST /v1/tenants/{tenant_id}/coupons/{definition_id}/generate
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"user_ids": ["user_123", "user_456"],
"custom_codes": ["VIP-USER-123", "VIP-USER-456"]
}Managing Coupon Definitions
List All Definitions (Admin-Only)
List all definitions across all tenants (requires API key auth):
GET /v1/coupons
X-API-Key: {api_key}List Tenant Definitions
GET /v1/tenants/{tenant_id}/coupons
Authorization: Bearer <admin_jwt>Response:
{
"definitions": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"tenant_id": "your-tenant-id",
"name": "Welcome Bonus",
"description": "Welcome bonus for new users",
"config": {...},
"status": "active",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}
],
"total": 1
}Get Single Definition
GET /v1/tenants/{tenant_id}/coupons/{definition_id}
Authorization: Bearer <admin_jwt>Update Definition
Only name, description, and config can be updated:
PUT /v1/tenants/{tenant_id}/coupons/{definition_id}
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"name": "Updated Name",
"description": "Updated description"
}Update Status (Pause/Activate)
PUT /v1/tenants/{tenant_id}/coupons/{definition_id}/status
Authorization: Bearer <admin_jwt>
Content-Type: application/json
{
"status": "paused"
}Valid statuses: active, paused
Archive (Soft Delete)
DELETE /v1/tenants/{tenant_id}/coupons/{definition_id}
Authorization: Bearer <admin_jwt>Returns 204 No Content. The definition is marked as archived and no longer processes events.
Configuration Reference
CouponConfig Schema
interface CouponConfig {
// Required: UUID of the reward item to grant
reward_item_id: string;
// Required: How codes are generated
code_format: "random" | "custom";
// For random format: prefix added to generated codes
code_prefix?: string;
// For random format: length of random portion (4-32, default: 8)
code_length?: number;
// For custom format: the exact code to use
custom_code?: string;
// Whether codes are case-sensitive (default: false)
case_sensitive?: boolean;
// When the coupon becomes valid (optional)
starts_at?: string; // ISO 8601 datetime
// When the coupon expires (optional)
expires_at?: string; // ISO 8601 datetime
// Required: Usage limit configuration
usage_limit: {
limit_type: "per_user" | "global" | "unlimited";
max_uses?: number; // Required for per_user/global
};
// Optional: Auto-generation configuration
auto_generate?: {
enabled: boolean;
trigger?: "achievement_completed" | "streak_milestone" | "leaderboard_rank";
trigger_config?: {
// For achievement_completed:
achievement_id?: string;
// For streak_milestone:
streak_id?: string;
milestone_threshold?: number;
// For leaderboard_rank:
leaderboard_id?: string;
rank_threshold?: number;
};
};
}Validation Rules
| Rule | Description |
|---|---|
reward_item_id | Must be a valid UUID of an existing reward item |
code_length | Must be between 4 and 32 for random format |
custom_code | Alphanumeric, hyphens, underscores only; max 255 chars |
starts_at / expires_at | starts_at must be before expires_at if both provided |
max_uses | Required and must be > 0 for per_user and global limits |
auto_generate | If enabled, trigger is required |
Scopes Required
Admin API key scopes for coupon operations:
| Operation | Required Scope |
|---|---|
| List definitions | coupons:read |
| Get definition | coupons:read |
| Create definition | coupons:write |
| Update definition | coupons:write |
| Update status | coupons:write |
| Delete/archive | coupons:write |
| Bulk generate | coupons:write |
Coupon Overview
The Phoenix Gamification Coupon System allows you to create, generate, and manage reward coupons for your users. Coupons grant reward items when redeemed and can be manually generated, bulk-generated, or automatically generated based on user achievements (streak milestones, achievement completions, leaderboard rankings).
Redeeming Coupons
This guide explains how to query, validate, and redeem coupons for users via the Query Gateway.