跳至內容

瀏覽文件

用 AI 建置
行銷活動免費商品

免費道具

讓玩家無需輸入兌換碼或付款即可領取活動獎勵。您的伺服器查詢活動狀態、為玩家提交領取請求,再處理 redemption.completed Webhook,在遊戲中發放獎勵。

完整的請求與回應結構請參閱免費道具 API 參考

身份驗證與玩家識別碼

從伺服器使用金鑰呼叫 API。查詢狀態需要 FreeItemStatus 許可權,領取需要 FreeItemClaim 許可權。金鑰只儲存在後端,playerId 應來自遊戲中已登入並通過身份驗證的玩家。

playerId 是您自己的玩家識別碼。Tokenz 不會查詢遊戲帳號,只根據這個字串識別玩家。

  • 會去除首尾空白,不允許空白值。
  • 最多 100 個字元。超長值會返回 request.decoding-failed,不會被截斷。
  • 區分大小寫。Player_123player_123 是不同玩家,各有獨立額度。
  • 所有呼叫都應使用同一個穩定識別碼,不要轉為小寫或通過其他方式合併不同識別碼。
  • 相同識別碼在不同裝置、會話或店面中共享領取額度。

活動設定與狀態

在 Tokenz Dashboard 中配置活動時間、獎勵、活動總額度、每位玩家的額度以及重複週期,並管理暫停、恢復和結束操作。如果看不到免費道具設定,請聯絡 Tokenz 支援,確認您的帳號是否已開放此功能。

  • draft:草稿,不能領取,所有欄位可編輯。
  • scheduled:已釋出,等待開始;到達 startAt 即可領取。
  • active:活動進行中,可以領取。
  • paused:已暫停,不能領取,可恢復為 active
  • ended:已結束,不能領取,此狀態不可撤銷。

查詢與領取要求活動類型為免費道具,狀態為 active,或為 scheduled 且已到達 startAt,並且尚未到達 endAt。即使儲存的狀態尚未更新,已到開始時間的 scheduled 活動也可使用。時間按絕對時刻比較,玩家所在地不會改變活動結束時刻。

額度與重複週期

每次領取都會檢查兩個獨立的額度:

  • 活動總額度:所有玩家的領取次數總和。達到上限後返回 campaign.limit-reached
  • 每位玩家的額度:同一 playerId 的領取次數。一次性活動達到上限返回 campaign.player-limit-reached;重複活動返回 campaign.player-period-limit-reached。其他玩家不受影響。

一次性活動的兩個額度均適用於活動整個生命週期,不會重置。重複活動的兩個額度都會在每個週期開始時重置。被拒絕的領取不會消耗任一額度。

可視需要左右捲動
頻率週期開始時間
一次性不重置
每日當地時間午夜
每週週一當地時間午夜
每月每月第一天當地時間午夜

使用活動的時區,而非玩家時區。API 不返回該時區,因此不要自行計算週期邊界。使用 nextResetAt 顯示倒計時,到達該時刻後重新查詢狀態。該時刻及之後的領取屬於新週期。重置不會延長 endAt

例如,每日活動總額度為 100 次、每位玩家限 1 次,則每天最多 100 位玩家各領取一次。次日重置後,總額度恢復到 100 次,前一天已領取的玩家也可再次領取。

領取流程

  1. 在自己的系統中儲存 campaignId
  2. 伺服器呼叫 GET /v1/free-items/{campaignId}?playerId=...,顯示獎勵與剩餘額度。
  3. 玩家點選領取後,伺服器呼叫 POST /v1/free-items/claim
  4. Tokenz 建立領取記錄,返回 201,並發送 redemption.completed Webhook。
  5. 後端驗證簽名,使用 redemptionId 防止重複發放,再發放獎勵。

查詢狀態

campaignId 是必需的路徑引數,playerId 是可選的查詢引數。狀態查詢不會預留額度,提交領取時可用額度可能已改變。額度耗盡時,狀態介面返回剩餘次數 0,而不是額度錯誤。

bash
curl --request GET \
  --url 'https://api.tokenz.one/v1/free-items/campaign_1p4LPTRKB5Z_t?playerId=player_98765' \
  --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'

成功回應(200)

json
{
  "campaign": {
    "id": "campaign_1p4LPTRKB5Z_t",
    "name": "Weekly Free Pack"
  },
  "rewardPreview": {
    "name": "Marathon Energy Gift",
    "imageUrl": "https://images.example.com/rewards/energy.png",
    "quantity": 1
  },
  "campaignRemaining": 842,
  "remainingForPlayer": 1,
  "nextResetAt": "2026-09-14T00:00:00Z"
}
  • campaignRemaining:所有玩家可用的剩餘次數。重複活動為當前週期,一次性活動為整個生命週期。未設定活動總額度時省略。
  • remainingForPlayer:此玩家的剩餘次數。未提供 playerId 或未設定玩家額度時省略。
  • nextResetAt:兩個額度下次重置的絕對時刻。一次性活動省略。

領取免費道具

請求主體中的 campaignIdplayerId 均為必填項。活動必須可領取,且兩個額度都未耗盡。API 建立記錄;實際獎勵由您的後端處理 Webhook 時發放。

bash
curl --request POST \
  --url https://api.tokenz.one/v1/free-items/claim \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
  --data '{
    "campaignId": "campaign_1p4LPTRKB5Z_t",
    "playerId": "player_98765"
  }'

成功回應(201)

json
{
  "redemption": {
    "redemptionId": "redemption_1p4LPTRKB5Z_t",
    "playerId": "player_98765",
    "campaign": {
      "id": "campaign_1p4LPTRKB5Z_t",
      "name": "Weekly Free Pack"
    },
    "reward": {
      "skuRedemptionReward": {
        "type": "EXTERNAL_SKU",
        "sku": "ITEM_ENERGY_GIFT",
        "name": "Marathon Energy Gift",
        "quantity": 1
      }
    },
    "redeemedAt": "2026-09-10T08:10:00Z",
    "kind": "FREE_ITEM_CLAIM",
    "source": "FREE_ITEM_CLAIM",
    "nextPeriodStart": "2026-09-14T00:00:00Z"
  },
  "remainingForPlayer": 0,
  "nextResetAt": "2026-09-14T00:00:00Z"
}

remainingForPlayer 是本次領取後的剩餘次數,未設定玩家額度時省略。一次性活動省略 nextResetAtredemption 物件欄位與下方 Webhook 相同。

Webhook 與獎勵發放

Tokenz 向訂閱此事件的端點發送 redemption.completed,與兌換碼兌換使用同一事件。

發放獎勵前先驗證 Tokenz-Signature 針對原始請求主體驗證,再解析內容。跳過驗證會使偽造請求獲得獎勵。請參閱保護你的 webhook 端點

json
{
  "id": "f75ff6f0-bdf9-4b25-bb96-968f8733a7e3",
  "object": "redemption.completed",
  "createdAt": "2026-09-10T08:10:00Z",
  "test": true,
  "eventData": {
    "type": "redemption",
    "version": "v1",
    "data": {
      "redemption": {
        "redemptionId": "redemption_1p4LPTRKB5Z_t",
        "campaign": {
          "id": "campaign_1p4LPTRKB5Z_t",
          "name": "Weekly Free Pack"
        },
        "playerId": "player_98765",
        "reward": {
          "skuRedemptionReward": {
            "type": "EXTERNAL_SKU",
            "sku": "ITEM_ENERGY_GIFT",
            "name": "Marathon Energy Gift",
            "quantity": 1
          }
        },
        "redeemedAt": "2026-09-10T08:10:00Z",
        "kind": "FREE_ITEM_CLAIM",
        "source": "FREE_ITEM_CLAIM",
        "nextPeriodStart": "2026-09-14T00:00:00Z"
      }
    }
  }
}
  • kind:免費道具為 FREE_ITEM_CLAIM,兌換碼為 CODE_REDEMPTION。新事件都會設定此欄位,但較早進入佇列的事件可能省略。
  • source:已棄用,僅為相容現有整合保留。新整合使用 kind
  • code:僅兌換碼兌換包含此欄位,免費道具領取會省略。請檢查現有處理程序是否錯誤地要求其存在。
  • nextPeriodStart:僅重複免費道具活動包含。它根據 redeemedAt 時的活動週期計算下一週期開始時刻,而非根據 Webhook 投遞時間計算。一次性領取和兌換碼兌換均省略。

通常只需根據 redemptionIdplayerIdreward 共用一套發放邏輯。kind 缺失或未知時不要猜測類型,仍使用這三個欄位發放,並標記事件以供核對。頂層事件 id 用於追蹤投遞,redemptionId 用於防止重複發放。

重試與回應丟失

領取請求沒有冪等性鍵。額度允許時,重複請求會建立另一條領取記錄。回應丟失後不要盲目重試。

Webhook 可確認領取成功,但只標識活動和玩家,未必能唯一對應某次超時請求。請結合自己的請求日誌核對。如果既無回應也無 Webhook,公開 API 目前無法重新查詢領取記錄,請在重試前聯絡 Tokenz 支援。Webhook 去重不能防止重複的領取請求。

端點未接受 Webhook 時,Tokenz 會逐漸增加間隔並加入隨機變化進行重試。重試安排在首次嘗試後的最長 72 小時視窗內;這不是保證在視窗內送達,實際執行可能延後。不要依賴固定次數或準確時間。投遞可能晚到數天,因此應將已發放的 redemptionId 持久儲存,而非放入短期快取,並保證同一 ID 的獎勵只發放一次。

錯誤處理

  • 400 / request.decoding-failed:無效 ID、空白或超長的 playerId,或格式錯誤的請求。
  • 401:缺少或無效的 API 金鑰。
  • 403:缺少所需許可權。
  • 404 / entity.not-found:活動不存在、屬於其他商戶,或測試模式與金鑰不匹配。
  • 422 / campaign.kind-invalid:不是免費道具活動。
  • 422 / campaign.status-invalid:草稿、暫停、結束,或尚未開始的預定活動。
  • 422 / campaign.expired:已到結束時刻;結束狀態也可能返回 campaign.status-invalid
  • 422 / campaign.limit-reached:總額度耗盡;重複活動為當前週期,一次性活動為整個生命週期。
  • 422 / campaign.player-limit-reached:玩家額度耗盡。
  • 422 / campaign.player-period-limit-reached:當前週期的玩家額度耗盡,可在 nextResetAt 後重試。
  • 429:超過速率限制。兩個介面均按 API 金鑰限制;提供玩家識別碼時,也按玩家限制。
  • 500:意外的伺服器錯誤。

測試

使用以 secret_test_ 開頭的金鑰,在 Dashboard 測試模式下建立活動。測試與正式資料隔離,金鑰只能操作模式匹配的活動。測試 ID 以 _t 結尾;測試 Webhook 僅傳送到測試端點,承載內容包含 "test": true

測試成功領取與獎勵發放、兩個額度耗盡、週期重置、暫停與過期、重複投遞。也應驗證空白和超長 playerId、速率限制以及測試與正式模式隔離,並確認每個 redemptionId 只發放一次獎勵。