本文へ移動

ドキュメント一覧

AI で構築
キャンペーン無料アイテム

無料アイテム

コードの入力や支払いなしで、プレイヤーがキャンペーン報酬を受け取れるようにします。サーバーが利用状況を確認して受け取りを申請し、redemption.completed Webhook を処理してゲーム内で報酬を付与します。

リクエストとレスポンスの詳細は無料アイテム API リファレンスを参照してください。

認証とプレイヤー識別子

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、または scheduledstartAt に達しており、かつ endAt より前の場合に成功します。保存済みステータスの更新前でも、開始時刻に達した scheduled キャンペーンは利用可能です。時刻は絶対時刻で比較され、プレイヤーの所在地によって終了時刻は変わりません。

上限と繰り返し

各受け取りで、独立した 2 つの上限を確認します。

  • キャンペーン全体の上限:全プレイヤーの合計です。上限に達すると campaign.limit-reached で拒否されます。
  • プレイヤーごとの上限:同じ playerId の受け取り回数です。単発では campaign.player-limit-reached、繰り返しでは campaign.player-period-limit-reached で拒否されます。他のプレイヤーには影響しません。

単発キャンペーンでは、両方の上限がキャンペーン全期間に適用され、リセットされません。繰り返しキャンペーンでは、両方の上限が各期間の開始時にリセットされます。拒否された受け取りは、どちらの残り回数も消費しません。

必要に応じて横にスクロール
頻度期間の開始
単発リセットなし
日次現地時刻の午前 0 時
週次月曜日の現地時刻の午前 0 時
月次毎月 1 日の現地時刻の午前 0 時

使用するのはプレイヤーではなくキャンペーンのタイムゾーンです。このタイムゾーンは API で返されないため、境界を自前で計算せず nextResetAt をカウントダウンに使用し、その時刻を過ぎたら状況を再取得してください。その時刻以降の受け取りは次の期間に属します。リセットしても endAt は延長されません。

例えば日次で全体 100 回、1 人 1 回なら、毎日最大 100 人が 1 回ずつ受け取れます。翌日のリセットで全体の残り回数が 100 に戻り、前日に受け取った人も再び受け取れます。

受け取りフロー

  1. 自社システムに campaignId を保存します。
  2. サーバーから GET /v1/free-items/{campaignId}?playerId=... を呼び出し、報酬と残り回数を表示します。
  3. プレイヤーの操作に応じて POST /v1/free-items/claim を呼び出します。
  4. Tokenz が受け取り記録を作成し、201redemption.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 は今回の受け取り後の残り回数で、プレイヤー上限がなければ省略されます。nextResetAt は単発では省略されます。redemption 内のフィールドは次の Webhook と共通です。

Webhook と報酬付与

このイベントを購読しているエンドポイントに 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 時点の繰り返し設定から計算した次の期間の開始時刻です。単発とコード引き換えでは省略されます。

通常は redemptionIdplayerIdreward を使う共通の付与処理で十分です。kind が欠けている、または未知の値でも種類を推測せず、この 3 項目で付与し、照合対象として記録してください。イベントのトップレベル id は配信追跡、redemptionId は重複付与の防止に使います。

再試行と応答の喪失

受け取り API に冪等性キーはありません。同じリクエストを繰り返すと、上限に余裕があれば別の受け取りになります。応答を失っても、無条件に再試行しないでください。

Webhook で成功を確認できますが、キャンペーンとプレイヤーを識別するだけなので、特定のタイムアウトしたリクエストと一意に対応しない場合があります。自社のリクエストログと照合してください。応答も Webhook もない場合、公開 API では受け取り記録を再取得できません。再試行前に Tokenz サポートへ連絡してください。Webhook の重複排除だけでは、受け取りリクエストの重複を防げません。

Webhook 配信が受け付けられない場合、間隔を広げ、ランダムな変動を加えて再試行します。初回試行から最大 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 ごとの付与が 1 回だけであることを検証します。