기프트 코드
이전 이름은 Redemption Codes입니다. API 엔드포인트와 이벤트 이름은 변경되지 않습니다.
Tokenz Redemption Codes API를 사용하여 캠페인 코드를 검증하고 사용 처리하는 방법을 알아봅니다.
Redemption Codes API를 사용하면 플레이어가 코드를 입력하고 보상을 받는 캠페인을 운영할 수 있습니다. 서버에서 코드를 검증하고 사용 자격을 확인한 후 코드를 사용 처리합니다. 이후 redemption.completed 웹훅을 받아 보상을 지급합니다.
개요
코드 사용 흐름은 다음과 같습니다.
- 검증: 코드를 사용할 수 있는지 확인하고 보상 미리 보기를 반환합니다.
- 사용 처리: 특정 플레이어가 코드를 사용하도록 처리하고 사용 기록을 생성합니다.
- 웹훅을 통한 지급:
redemption.completed를 수신하고 게임 백엔드에서 보상을 지급합니다.
캠페인 설정 및 관리
캠페인과 코드는 Tokenz 대시보드에서 생성하고 관리합니다. 판매자는 대시보드에서 다음 작업을 수행할 수 있습니다.
- 운영 기간과 보상을 설정하여 캠페인 생성
- 코드 생성 및 관리
- 캠페인 일시 중지, 재개 또는 종료
캠페인 상태
캠페인은 다음 상태 중 하나를 가집니다.
draft: 작성 중입니다. 코드를 사용할 수 없습니다. 모든 필드를 수정할 수 있습니다.scheduled: 게시 후 대기 중입니다. 설정한start_at시각에 자동으로active상태로 전환됩니다.active: 캠페인이 진행 중이며 코드를 사용할 수 있습니다.paused: 수동으로 일시 중지되었습니다. 코드 사용 요청이 거부됩니다.active상태로 재개할 수 있습니다.ended: 캠페인이 종료되었습니다. 코드 사용 요청이 거부됩니다. 이 상태는 되돌릴 수 없습니다.
캠페인이 active이거나 scheduled이면서 startAt에 도달한 경우 validate와 redeem이 성공합니다. endAt부터는 요청이 거부됩니다. 예약된 캠페인은 startAt에 자동으로 active로 전환되므로 이 차이는 전환 전후의 짧은 시간에만 영향을 줍니다.
코드 상태
코드 상태는 캠페인 상태와 코드 자체의 상태에 따라 결정됩니다.
pending: 유효한 코드이지만 캠페인이 현재 활성 상태가 아닙니다(예: 초안, 예약, 일시 중지). 코드를 사용할 수 없습니다. 단,scheduled캠페인이startAt에 도달하면 사용할 수 있습니다.active: 사용할 준비가 된 코드입니다. 캠페인이 활성 상태여야 합니다. 사용 가능한 상태가 이것뿐인 것은 아닙니다.scheduled캠페인이startAt에 도달하면pending코드도 사용할 수 있습니다.deactivated: 비활성화된 코드입니다. 판매자가 수동으로 코드를 비활성화하거나 캠페인이 종료되면 이 상태가 됩니다.
표시되는 코드 상태는 캠페인 상태에 따라 달라집니다.
| 캠페인 상태 | 코드 상태 |
|---|---|
active | active |
draft, scheduled, paused | pending |
ended | deactivated |
캠페인의 endAt이 지나면 코드 상태가 여전히 active로 표시되더라도 코드를 사용할 수 없습니다. 이때 API는 redemptionCode.campaign-invalid 오류를 반환합니다. 아직 시작되지 않은 캠페인에도 같은 오류가 반환됩니다.
판매자가 코드를 수동으로 비활성화하면 캠페인 상태와 관계없이 항상 deactivated로 표시됩니다.
또한 currentRedemptions >= maxRedemptions이면 API 상태가 active여도 Tokenz 대시보드에는 코드가 사용 완료(Redeemed)로 표시됩니다. 이는 대시보드 표시 전용 상태이며 API에서는 반환되지 않습니다.
코드 사용 수명 주기
- 플레이어가 프로모션 캠페인 UI에 코드를 입력합니다.
- 서버가
POST /v1/redemption-codes/validate를 호출합니다. - 서버가 플레이어에게 보상 미리 보기를 표시합니다.
- 플레이어가 코드 사용을 확인합니다.
- 서버가
POST /v1/redemption-codes/redeem을 호출합니다. - Tokenz가 코드 사용 성공 응답을 반환합니다.
- Tokenz가
redemption.completed웹훅을 전송합니다. - 백엔드에서 보상을 지급합니다.
redemptionId를 사용하여 중복 지급을 방지해야 합니다.
코드 검증
검증 API는 캠페인과 코드의 사용 자격을 확인하고 캠페인 및 보상 미리 보기를 반환합니다. 검증이 성공하려면 캠페인이 활성 상태이거나 예약 상태에서 startAt에 도달해야 하며, 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"
}'
요청 필드
redemptionCode(필수): 플레이어가 입력한 코드playerId(선택): 판매자 측 플레이어 식별자입니다. 지정하면 플레이어별 한도도 확인합니다. 생략하면 코드와 캠페인의 전체 한도만 검증합니다.
성공 응답 (200)
{
"campaign": {
"id": "campaign_1AbCdEfGh12",
"name": "Spring Campaign 2026"
},
"rewardPreview": {
"name": "SSR Reimu Card",
"imageUrl": "https://images.example.com/rewards/reimu.png",
"quantity": 1
}
}
코드 사용 처리
사용 처리 API는 플레이어가 코드를 사용하도록 처리하고 사용 기록을 생성합니다. 성공하려면 캠페인이 활성 상태이거나 예약 상태에서 startAt에 도달해야 하며, 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"
}'
요청 필드
redemptionCode(필수): 플레이어가 입력한 코드playerId(필수): 판매자 측 플레이어 식별자
성공 응답 (201)
{
"redemptionId": "redemption_1XyZaBcDe34",
"kind": "CODE_REDEMPTION",
"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"
}
코드 사용 웹훅
코드 사용이 완료되면 Tokenz는 이 이벤트를 구독하는 웹훅 엔드포인트로 redemption.completed를 전송합니다.
보상을 지급하기 전에 반드시 서명을 검증하세요. 모든 전송에는 Tokenz-Signature 헤더가 포함됩니다. 서명 검증을 생략하면 URL을 알아내거나 추측한 사람이라면 누구나 보상을 받을 수 있습니다. 원본 요청 본문으로 서명을 검증한 후 파싱하세요. 절차는 웹훅 엔드포인트 보안 설정을 참고하세요. 아래 필드는 서명 검증에 성공한 후에만 신뢰할 수 있습니다.
{
"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"
},
"kind": "CODE_REDEMPTION",
"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"
}
}
}
}
최상위 이벤트 id는 웹훅 전송 추적에 사용하고, redemptionId는 백엔드의 중복 지급 방지에 사용하세요.
같은 redemption.completed 이벤트가 무료 아이템 수령에도 전송됩니다. kind로 CODE_REDEMPTION과 FREE_ITEM_CLAIM을 구분하세요. 무료 아이템 수령에서는 code 필드가 생략됩니다. source는 더 이상 권장되지 않으며 하위 호환성을 위해 유지됩니다. 신규 연동에서는 kind를 사용하세요. 이전에 대기열에 들어간 이벤트에는 kind가 없을 수 있습니다.
오류 처리
코드 사용 엔드포인트는 구조화된 오류 객체와 함께 표준 HTTP 상태 코드를 반환합니다.
일반적인 오류
401 Unauthorized: API 키가 없거나 유효하지 않습니다.403 Forbidden: API 키에 필요한 권한 범위가 없습니다.404 Not Found(entity.not-found): 코드를 찾을 수 없습니다.422 Unprocessable Entity(campaign.limit-reached): 캠페인의 전체 사용 한도에 도달했습니다.422 Unprocessable Entity(campaign.player-limit-reached): 플레이어가 캠페인별 사용 한도에 도달했습니다.422 Unprocessable Entity(redemptionCode.campaign-invalid): 캠페인이 비활성 상태이거나 유효 기간 밖이거나 코드가 비활성화되었습니다. 오류의message필드로 원인을 구분할 수 있습니다.422 Unprocessable Entity(redemptionCode.limit-reached): 코드 자체의 사용 한도에 도달했습니다.422 Unprocessable Entity(redemptionCode.player-limit-reached): 플레이어가 이 코드의 플레이어별 사용 한도에 도달했습니다.429 Too Many Requests: 요청 빈도 제한을 초과했습니다.500 Server Error: 예기치 않은 서버 오류입니다.
테스트
테스트 모드에서 코드 사용 연동을 개발하고 테스트하세요.
- 테스트 API 키(
secret_test_접두사)를 사용하여 테스트 캠페인과 코드에 접근합니다. - Tokenz 대시보드의 테스트 모드에서 테스트 캠페인을 생성합니다.
- 테스트 코드 사용은 실제 데이터와 완전히 분리됩니다. 테스트 API 키로는 테스트 코드만, 라이브 API 키로는 라이브 코드만 사용할 수 있습니다.
- 테스트 엔티티 ID에는
_t접미사가 포함됩니다(예:redemption_1XyZaBcDe34_t). - 테스트 웹훅은 테스트 웹훅 엔드포인트로만 전송되며, 페이로드에
"test": true가 포함됩니다.