Gift Codes
Formerly Redemption Codes. API endpoints and event names are unchanged.
Learn how to validate and redeem campaign codes through the Tokenz Redemption Codes API.
The Redemption Codes API helps you run campaigns where players enter a code and receive a reward. Your server validates a code, confirms eligibility, redeems it, and then handles a redemption.completed webhook for fulfillment.
Overview
The redemption flow includes:
- Validation: Check whether a code is redeemable and return a reward preview
- Redemption: Consume the code for a specific player and create a redemption record
- Webhook fulfillment: Receive
redemption.completedand grant the reward in your game backend
Campaign setup and management
Campaigns and redemption codes are created and managed in the Tokenz Dashboard. Merchants use the Tokenz Dashboard to:
- Create campaigns with active periods and reward configuration
- Generate or manage redemption codes
- Pause, resume, or end campaign operations
Campaign statuses
Campaigns can be in one of the following statuses:
draft: Work in progress. Redemption not allowed. All fields are editable.scheduled: Published and queued. Automatically transitions toactiveat the configuredstart_attime.active: Campaign is live and redemptions can succeedpaused: Manually paused. Redemptions are rejected. Can be resumed toactiveended: Campaign is finished. Redemptions are rejected. This state is irreversible
validate and redeem succeed when the campaign is active, and also when it is scheduled and its startAt has already been reached. They are rejected from endAt onwards. A scheduled campaign moves to active on its own at startAt, so this only matters in the short window around the transition.
Code statuses
Redemption code statuses are derived from the campaign status and the code's own status:
pending: Code is valid but the campaign is not currently active (e.g., draft, scheduled, or paused). Redemption is not allowed, except for ascheduledcampaign whosestartAthas been reached, which does accept redemptions.active: Code is ready for use. Requires the campaign to be active. This is not the only redeemable status, because apendingcode becomes redeemable once ascheduledcampaign reaches itsstartAt.deactivated: Code is disabled. This happens when a merchant manually deactivates a code, or when the campaign has ended.
The displayed code status depends on the campaign state:
| Campaign status | Code status |
|---|---|
active | active |
draft, scheduled, paused | pending |
ended | deactivated |
Once a campaign has passed its endAt, the code cannot be redeemed even though its status may still show as active. The API returns a redemptionCode.campaign-invalid error in this case, and the same error for a campaign that has not started yet.
If a merchant manually deactivates a code, it always shows as deactivated regardless of the campaign status.
Additionally, the Tokenz Dashboard displays a code as Redeemed when currentRedemptions >= maxRedemptions, even though the API status remains active. This is a display-only state in the Dashboard and is not returned by the API.
Redemption lifecycle
- Player enters a code in your promotional campaign UI
- Your server calls
POST /v1/redemption-codes/validate - Your server shows the reward preview to the player
- Player confirms redemption
- Your server calls
POST /v1/redemption-codes/redeem - Tokenz returns a successful redemption response
- Tokenz sends a
redemption.completedwebhook - Your backend fulfills the reward and should use
redemptionIdto guard against duplicate fulfillment
Validate a code
Validate checks campaign and code eligibility and returns the campaign preview plus reward preview. A successful validation requires the campaign to be active, or scheduled with its startAt reached, and before its endAt.
curl --request POST \
--url https://api.tokenz.one/v1/redemption-codes/validate \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"redemptionCode": "SPRING2026FREE",
"playerId": "player_98765"
}'
Request fields
redemptionCode(required): Code entered by the playerplayerId(optional): Merchant player identifier. If provided, per-player limits are also checked. If omitted, only global code and campaign limits are validated
Success response (200)
{
"campaign": {
"id": "campaign_1AbCdEfGh12",
"name": "Spring Campaign 2026"
},
"rewardPreview": {
"name": "SSR Reimu Card",
"imageUrl": "https://images.example.com/rewards/reimu.png",
"quantity": 1
}
}
Redeem a code
Redeem consumes the code for a player and creates a redemption record. A successful redemption requires the campaign to be active, or scheduled with its startAt reached, and before its endAt.
curl --request POST \
--url https://api.tokenz.one/v1/redemption-codes/redeem \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"redemptionCode": "SPRING2026FREE",
"playerId": "player_98765"
}'
Request fields
redemptionCode(required): Code entered by the playerplayerId(required): Merchant player identifier
Success response (201)
{
"redemptionId": "redemption_1XyZaBcDe34",
"source": "CODE_REDEMPTION",
"code": "SPRING2026FREE",
"playerId": "player_98765",
"campaign": {
"id": "campaign_1AbCdEfGh12",
"name": "Spring Campaign 2026"
},
"reward": {
"skuRedemptionReward": {
"type": "EXTERNAL_SKU",
"sku": "ITEM_SSR_REIMU",
"name": "SSR Reimu Card",
"quantity": 1
}
},
"redeemedAt": "2026-03-25T08:10:00Z"
}
Redemption webhook
After a successful redemption, Tokenz sends redemption.completed to webhook endpoints subscribed to this event.
Verify the signature before you grant anything. Every delivery carries a Tokenz-Signature header, and a handler that skips verification will grant rewards to anyone who finds or guesses its URL. Verify over the raw request body, then parse. See Secure your webhook endpoint for the steps. Treat the fields below as trustworthy only once the signature checks out.
{
"id": "f75ff6f0-bdf9-4b25-bb96-968f8733a7e3",
"object": "redemption.completed",
"createdAt": "2026-03-24T23:10:00Z",
"test": false,
"eventData": {
"type": "redemption",
"version": "v1",
"data": {
"redemption": {
"redemptionId": "redemption_1XyZaBcDe34",
"campaign": {
"id": "campaign_1AbCdEfGh12",
"name": "Spring Campaign 2026"
},
"source": "CODE_REDEMPTION",
"code": "SPRING2026FREE",
"playerId": "player_98765",
"reward": {
"skuRedemptionReward": {
"type": "EXTERNAL_SKU",
"sku": "ITEM_SSR_REIMU",
"name": "SSR Reimu Card",
"quantity": 1
}
},
"redeemedAt": "2026-03-25T08:10:00Z"
}
}
}
}
Use the top-level event id for webhook delivery tracing, and use redemptionId to guard against duplicate fulfillment in your backend.
The same redemption.completed event is also sent for free item claims, documented in the v2 Free Items guide. Use source to tell CODE_REDEMPTION from FREE_ITEM_CLAIM. The code field is omitted for free item claims.
Error handling
Redemption endpoints return standard HTTP status codes with structured error objects.
Common errors
401 Unauthorized: Invalid or missing API key403 Forbidden: API key does not have the required scope404 Not Found(entity.not-found): Redemption code not found422 Unprocessable Entity(campaign.limit-reached): The campaign has reached its total redemption limit422 Unprocessable Entity(campaign.player-limit-reached): The player has reached the per-campaign redemption limit422 Unprocessable Entity(redemptionCode.campaign-invalid): Campaign is not active, is outside its valid time window, or code is deactivated. The errormessagefield distinguishes between these reasons422 Unprocessable Entity(redemptionCode.limit-reached): The redemption code has reached its own usage limit422 Unprocessable Entity(redemptionCode.player-limit-reached): The player has reached the per-code redemption limit for this code429 Too Many Requests: Rate limit exceeded500 Server Error: Unexpected server error
Testing
Use test mode to develop and test your redemption integration:
- Use test API keys (prefixed with
secret_test_) to interact with test campaigns and codes - Create test campaigns in the Tokenz Dashboard using test mode
- Test redemptions are fully isolated from live data — a test API key can only redeem test codes, and a live API key can only redeem live codes
- Test entity IDs include a
_tsuffix (e.g.,redemption_1XyZaBcDe34_t) - Test webhooks are delivered only to your test webhook endpoints, with
"test": truein the payload