API リファレンス
作者の手元・CI・エディタ拡張から、ゲームの作成と設定変更・サムネイルとビルドのアップロード・ランキングの宣言・アナリティクスの取得を行う HTTP API です。
ゲームの中から呼ぶ API(ランキングへの投稿・公開プレイヤー状態・マルチプレイ)は SDK ガイド を見てください。
1. はじめに
API はすべて https://gamerush.jp/api/ の下にあります。本文は JSON で送り、応答も JSON で返ります。成功はすべて 200 です。
認証は、Studio の API トークン で発行したトークンを Authorization: Bearer に載せるだけです。発行のしかた・権限の選び方・置き場所の注意は SDK ガイドの API トークン にあります。
export GRUSH_TOKEN="grush_pat_..."
curl "https://gamerush.jp/api/games" \
-H "Authorization: Bearer $GRUSH_TOKEN"トークンをゲームのビルドへ入れないでください。ここにある API は、作者の手元・CI・エディタ拡張から呼ぶためのものです。
- トークンで呼べるのは、このページに載っている API だけです。アカウントの操作・コメント・フォローなどは、トークンでは
401になります。 - トークンから新しいトークンは発行できません。
- 運営の管理権限はトークンには乗りません。管理者が発行したトークンでも、触れるのは本人がオーナーか共同編集者のゲームだけです。
エラーの形
失敗すると、error(英語の説明文)か code(機械で読める識別子)と params のどちらかを持つ JSON が返ります。details が付くこともあります。
{ "error": "API token is missing the games:write scope." }
{ "code": "build.tooManyFiles", "params": { "limit": 2000 } }| HTTP | よくある原因 |
|---|---|
| 400 | リクエストの形が違う(必須の項目が無い、ビルドのファイル一覧の形が違う など) |
| 401 | トークンが無い・形が違う・期限切れ・失効済み |
| 403 | トークンに必要な権限が無い。規約や素材の権利への同意が無い |
| 404 | ゲームが無い。トークンの対象ゲームに入っていない。自分がオーナーでも共同編集者でもない |
| 409 | 状態がぶつかった(審査の途中で変わった、同じ key が既にある など) |
| 422 | アップロードしたビルドの中身の検査で弾かれた |
対象ゲームを絞ったトークンを他のゲームへ向けたときは、存在を漏らさないために 403 ではなく 404 になります。
2. ゲーム
| API | 権限 | 内容 |
|---|---|---|
GET /api/games | games:read | 自分のゲームと共同編集中のゲームの一覧 |
GET /api/games/:id | games:read | ゲーム1本と最新ビルド |
POST /api/games | games:create | ゲームの新規作成 |
PATCH /api/games/:id | games:write | タイトル・説明・遊び方とそれらの言語と訳・元 URL・サムネイル・実況ポリシー・公開設定の変更 |
GET の応答は { games: [...] } / { game } です。各ゲームには id・title・visibility・review_status・requested_visibility・streaming_policy・thumb_url・thumb_wide_url・thumb_tall_url・play_count などと、最新ビルドの latestBuild が入ります。public のゲームで最新ビルドが審査待ちか差し戻しのあいだは、配信中の承認済みのビルドが publishedBuild に入ります(それ以外は null)。approved_build_id は承認済みのビルドの id です。leaderboard_manifest_build_id は、grush.json のランキングの定義を承認の時点まで繰り延べているビルドの id で、繰り延べていなければ null です。既定の文面を書いた言語は source_locale に、言語ごとの訳は localizations に入ります(訳を書く)。
ゲームを作る
curl -X POST "https://gamerush.jp/api/games" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "ねこジャンプ",
"description": "タップで跳ぶだけのショートゲーム",
"visibility": "public",
"streamingPolicy": "allowed",
"acceptTerms": true,
"confirmAssetRights": true,
"declareAllAges": true
}'| フィールド | 内容 |
|---|---|
title | 必須。120 文字まで。改行は空白になる |
description | 2000 文字まで |
howToPlay | 遊び方(操作やルール)。2000 文字まで |
sourceLocale | title・description・howToPlay を書いた言語。ja / en / ko / zh-Hans / zh-Hant / id / fil / vi / th のどれか。省略するか null なら未設定(既定の文面の言語) |
localizations | 言語ごとの訳。形と検証は PATCH と同じ(訳を書く)。空の項目と、title などの既定の文面と同じ訳は保存されない。sourceLocale を指定したときは、保存した後にその言語の訳が残る要求は 400(localizations.sourceLocale)。既定と同じ文面か空の項目だけなら、正規化で落ちて残らないので通る(既定の文面の言語) |
visibility | public / unlisted / private。unlisted と private は指定した可視性で作られる。public を指定したゲームは原則 private で始まり、最初のビルドが完了した時点で審査に積まれる(オーナー本人が認証済みクリエイターか管理者なら審査を経ずに public で作られる) |
sourceUrl | 元の配布ページなど。http / https で 500 文字まで |
streamingPolicy | 実況ポリシー。下の表を参照 |
streamingPolicyNote | conditional のときだけ保存される条件の説明。500 文字まで |
officialFeatureOptOut | GameRush 公式の特集記事や SNS での紹介を断るなら true。省略すると false(紹介してよい)。真偽値でなければ 400 |
acceptTerms | 必須。利用規約 と ゲーム掲載ポリシー に同意するなら true |
termsVersion | 任意。同意した利用規約の版(2026-10-07 のような施行日の文字列)。送ると作成の時点で施行中の版と照合し、違えばゲームを作らずに 409(terms.versionMismatch。施行中の版を details.termsVersion に入れる)を返す。文字列でなければ 400(terms.versionRequired)。省略するか null なら照合しない |
confirmAssetRights | 必須。画像・音・コードなどの素材をすべて自分で作ったか、使う権利を持っているなら true。true でなければゲームを作らずに 403(rights.confirmRequired) |
declareAllAges | visibility が public / unlisted なら必須。ゲームが全年齢向けに適した内容であることを申告するなら true。申告した時刻と申告した人をゲームに記録する(private で送っても記録する)。public / unlisted で false か省略ならゲームを作らずに 403(ageRating.declarationRequired)。private なら省略しても作れ、公開へ変えるときに求められる。真偽値でなければ 400 |
thumbnail | サムネイルを同時に上げるとき(16:9 の thumbnailWide、9:16 の thumbnailTall も同じ)。サムネイル を参照 |
応答は { game, mediaUploads } です。作成には冪等キーが無いので、失敗しても機械的に再試行しないでください。応答が失われた場合は GET /api/games で作られたかを確かめてからやり直します。
トークンでゲームを作るスクリプトや CI も、visibility に public / unlisted を指定するときは declareAllAges: true を送る必要があります。無ければ 403 になり、ゲームは作られません。private で作る要求は declareAllAges が無くても作れます(confirmAssetRights: true はどちらでも必須です)。
対象ゲームを絞ったトークンではゲームを作れません(まだ無いゲームは対象に入れられないため)。
設定を変える
PATCH は送ったフィールドだけを変えます。Studio の保存ボタンと同じ処理を通るので、審査やホールドの扱いも画面と同じです。
curl -X PATCH "https://gamerush.jp/api/games/$GAME_ID" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"streamingPolicy": "conditional",
"streamingPolicyNote": "収益化した配信ではクレジットを表示してください",
"visibility": "unlisted",
"declareAllAges": true
}'| streamingPolicy の値 | 意味 |
|---|---|
allowed | 実況・動画投稿を許可する |
conditional | 条件付きで許可する(条件は streamingPolicyNote) |
prohibited | 実況・動画投稿を許可しない |
unspecified | 未設定(既定) |
実況ポリシーの意味と、プレイヤーにどう見えるかは ゲーム実況ポリシー にあります。officialFeatureOptOut も PATCH で切り替えられ、真偽値でなければ 400 になります。sourceUrl に null か空文字を送ると消えます。
全年齢の申告(declareAllAges)の記録が無いゲームは、PATCH で declareAllAges: true を送ると申告を記録できます。公開設定とは関係なく、private のままでも送れます。記録が無いゲームを private から public / unlisted へ変えるときは必須です(公開設定と審査)。申告は一度記録したら変わらず、記録済みのゲームに送っても何も起きません。公開設定を上げない要求では、ほかのトークンや別の要求が同時に申告していても失敗せず、同じ要求のほかの変更もそのまま保存されます。private から上げる要求では、申告は公開設定の変更と一緒に保存され、別の要求が先に申告していたときは公開設定も変えずに 409 review.stateChanged になります。false を送っても記録は消えず、何も起きません。真偽値でなければ 400 になります。
streamingPolicy に表に無い値("Allowed" のような打ち間違いを含む)を送ると、エラーにはならず unspecified として保存されます。title / description / howToPlay / streamingPolicyNote は上限を超えた分が切り詰められます。description / howToPlay / streamingPolicyNote の改行は LF に揃い、制御文字(タブを含む)は空白に、行末の空白は削られます。応答の game で保存された値を確かめてください。
訳を書く
title・description・howToPlay は作品の既定の文面です。これとは別に、言語ごとの訳を POST と PATCH の localizations で書けます。プレイヤーの表示言語の訳があればそれを、無い言語と空の項目には既定の文面を出します。
curl -X PATCH "https://gamerush.jp/api/games/$GAME_ID" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"localizations": {
"en": { "title": "Cat Jump", "howToPlay": "Tap to jump." },
"ko": null
}
}'| localizations に送る値 | 内容 |
|---|---|
| キー | 言語。ja / en / ko / zh-Hans / zh-Hant / id / fil / vi / th のどれかを、この綴りのまま書く。en-US・zh-TW のような地域付きの形、zh-hans のような大文字小文字の違う形、ほかの言語は 400 |
{ "title", "description", "howToPlay" } | その言語の訳。送った項目だけを変え、送らなかった項目は今の訳を残す。上限と正規化は既定の文面と同じ |
null | その言語の訳をすべて消す |
項目に null か "" | その項目の訳を消す(既定の文面に戻る) |
応答と GET の localizations は、{ "en": { "title": "...", "description": "...", "how_to_play": "..." } } の形で、保存されている訳だけが入ります。遊び方のキーは how_to_play です。既定の文面と同じ訳は保存されないので、title と同じ文字列を en の title に送ると、en の title は消えます。
訳は今の値に重ねて保存します。読んでから保存するまでの間に、Studio やほかのトークンが同じゲームの訳か sourceLocale を変えていたときは、保存せずに 409 localizations.changed を返します。GET /api/games/:id で最新の訳を読んでからやり直してください。
既定の文面の言語
sourceLocale は、title・description・howToPlay を書いた言語です。値は localizations のキーと同じく ja / en / ko / zh-Hans / zh-Hant / id / fil / vi / th のどれかを、この綴りのまま送ります。null は未設定です。ほかの値(en-US・zh-hans など)は 400 です。POST で省略すると未設定、PATCH で省略すると今の値のまま、PATCH で null を送ると未設定に戻ります。localizations を送らない PATCH で今と同じ値を送ったときは、省略したときと同じです(毎回送っても、ほかの変更の保存には影響しません)。GET と応答の source_locale で今の値を確かめられます(未設定は null)。
指定したゲームでは、この言語の閲覧者に既定の文面を出し、ゲームの紹介ページはこの言語の版で検索に載ります。英語で書いたゲームは sourceLocale を en にしてください。未設定のゲーム(sourceLocale を送らずに作ったゲームを含む)は、既定の文面を日本語の版として扱い、ja を含むどの言語の訳も書けて、閲覧者の言語の訳があればそれを出します。
sourceLocale を指定したゲームは、その言語の訳を持てません。保存した後の localizations に sourceLocale の言語の訳が残る要求は、何も保存せずに 400 localizations.sourceLocale を返します。未設定から指定するときと、別の言語に変えるときに、その言語の訳が残っているときも同じです。既定と同じ文面か空の項目だけを送った言語は、正規化で落ちて残らないので通ります。その言語の訳を消す null は送れます。
既定の文面と訳を入れ替えるときは、1回の PATCH に新しい sourceLocale・その言語の既定の文面・新しい言語の訳を消す null・前の言語の文面を訳として送ります。既定の文面は3項目(title・description・howToPlay)をすべて送ってください。送らなかった項目は前の言語の文面のまま既定に残り、新しい言語のその項目の訳は null で消えます。前の言語の訳にも、3項目をすべて送ります。下の例は、日本語で書いて英語の訳を持つゲームを、英語の既定の文面と日本語の訳に入れ替えます。
curl -X PATCH "https://gamerush.jp/api/games/$GAME_ID" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sourceLocale": "en",
"title": "Cat Jump",
"description": "Tap to jump over the walls.",
"howToPlay": "Tap anywhere to jump.",
"localizations": {
"en": null,
"ja": {
"title": "ねこジャンプ",
"description": "タップで壁を跳び越える。",
"howToPlay": "画面のどこかをタップして跳ぶ。"
}
}
}'公開設定と審査
privateへの変更はすぐに反映され、審査待ちがあれば取り消されます。unlistedへの変更は、審査を経ずにすぐに反映されます。審査待ちがあれば取り消されます。publicへの変更は、最新ビルドが審査済みならすぐに反映されます。そうでなければrequested_visibilityに希望が入り、review_statusがpendingになります。visibilityは、unlistedのゲームならunlistedのまま、承認済みのビルドを配信しているpublicのゲームならpublicのまま、それ以外はprivateのままです。publicのゲームが配信するのは、審査で承認されたビルドです。新しいビルドが審査を待つ間と差し戻された後も、承認済みのビルドの配信が続きます。- ビルドがまだ無いゲームは
publicにもunlistedにもできません(409review.buildRequired)。 - 素材の権利をまだ確認していないゲームを公開へ変えるときは、
confirmAssetRights: trueを一緒に送ります。無ければ403rights.confirmRequiredになります。 - 全年齢の申告の記録が無いゲームを
privateからpublic/unlistedへ変えるとき(公開の審査の申請を含む)は、declareAllAges: trueを一緒に送ります。無ければ403ageRating.declarationRequiredになり、同じ要求のほかの変更も保存されません。認証済みクリエイターと管理者、トークンからの変更も同じです。publicとunlistedの間の変更と、privateへの変更では求めません。 - ホールド中のゲームは公開設定を変えられません(
403hold.locked)。 - ホールド中のゲームで
descriptionかhowToPlay(どちらかの訳を含む)の内容を変えると、一般公開の審査に積まれます。 - 審査待ち(
review_statusがpending)のゲームでtitle・description・howToPlay・それらの訳・サムネイル・sourceUrlの内容を変えると、運営は新しい内容で審査し直します。審査の順番は、変えた時点で申請したものとして後ろへ回ります。 - 変更の途中で審査の状態が変わったときは
409review.stateChangedになります。最新の状態を読んでからやり直してください。
審査を飛ばせるのは、オーナー本人が運営の認めた認証済みクリエイターか管理者のときだけです。その場合はトークンからでも Studio と同じく即時に反映されます。共同制作者の立場では審査を飛ばせません。認証済みクリエイターの場合、運営が最後に差し戻したゲームは審査に回ります。全年齢の申告の記録が無いゲームの申請も、審査を飛ばさずに審査に回ります。
3. サムネイル
サムネイルは2段で上げます。まず POST /api/games か PATCH /api/games/:id にファイルの名前と大きさだけを送り、返ってきた mediaUploads の url へ画像そのものを PUT します。確定の呼び出しはありません。
サムネイルは露出面ごとに3種類あります。正方形の thumbnail は「続きから」などに使う基本の1枚で、ホームの横長カード(オススメ・話題の新作・人気・特集棚)には 16:9 の thumbnailWide を出します。フィードではカードの形に合わせ、PC ブラウザなどでカードが横長のときは 16:9 の thumbnailWide、スマホなどで縦長のときは 9:16 の thumbnailTall を出します。16:9 と 9:16 は任意で、形に合う方が無ければその面でも正方形を使います。3種類とも GIF とアニメーション WebP を使え、その面でアニメーションします。
SIZE=$(wc -c < thumb.png)
curl -X PATCH "https://gamerush.jp/api/games/$GAME_ID" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"thumbnail\":{\"fileName\":\"thumb.png\",\"size\":$SIZE,\"contentType\":\"image/png\"}}" \
> patch.json
UPLOAD_URL=$(jq -r '.mediaUploads[] | select(.kind == "thumbnail") | .url' patch.json)
curl -X PUT "$UPLOAD_URL" --data-binary @thumb.png| フィールド | kind | 受け付ける形 |
|---|---|---|
thumbnail | thumbnail | png / jpg / webp / gif、1MB まで。これが無いと下の3つ(Small / Large / Og)も無視される |
thumbnailSmall | thumbnail-small | 長辺 512px の webp / jpg、1MB まで。GIF のときは無視 |
thumbnailLarge | thumbnail-large | 長辺 1920px の webp / jpg、1MB まで。GIF のときは無視 |
thumbnailOg | thumbnail-og | SNS の共有カード用の静止 jpg、1MB まで。GIF と WebP のときだけ使い、png / jpg では無視 |
thumbnailWide | thumbnail-wide | 横長の 16:9(ホームのカードと、横長に表示したフィード)。推奨 1280×720 の png / jpg / webp / gif、1MB まで |
thumbnailTall | thumbnail-tall | 縦長の 9:16(縦長に表示したフィード)。推奨 1080×1920 の png / jpg / webp / gif、1MB まで |
- 各フィールドは
{ fileName, size, contentType }です。形式はfileNameの拡張子で決まります。 urlの期限は 1 時間です。切れたら同じPATCHをやり直して新しいurlを取ります。- ゲームのサムネイルの URL は
PATCHの時点で新しいものへ切り替わります。PUTを終えるまでは画像が出ないので、続けて上げてください。 thumbnailWide/thumbnailTallはthumbnailと独立しています。片方だけ送っても構いませんし、正方形を差し替えても 16:9・9:16 は残ります。- アニメーション WebP の
thumbnailにthumbnailSmallを送らなければ、一覧向けの縮小版をアニメーションを保ったままサーバが後から作ります。GIF と違いthumbnailSmall/thumbnailLargeは無視されず、送った派生はそれを使う面でそのまま出ます。 - 16:9・9:16 を外して正方形へ戻すときは、
PATCHにclearThumbnailWide: true/clearThumbnailTall: trueを送ります。同じ呼び出しでファイルも送った場合はファイルが優先されます。
4. ビルドのアップロード
ビルドは3段で上げます。権限はどれも builds:write で、最上位に grush.json を含むビルドでは leaderboards:write も要ります。Unity なら Editor 拡張 が同じ手順を持っているので、自分で書く必要はありません。
| 段 | API | 内容 |
|---|---|---|
| 1 | POST /api/games/:id/builds | ファイルの一覧を送り、ファイルごとの送り先を受け取る |
| 2 | PUT <uploadUrls[].url> | 各ファイルの中身をそのまま送る |
| 3 | POST /api/builds/:buildId/complete | 中身を検査して、ゲームの最新ビルドにする |
{
"engine": "godot",
"files": [
{ "path": "index.html", "size": 5120 },
{ "path": "index.js", "size": 301224 },
{ "path": "index.wasm", "size": 35651584 },
{ "path": "index.pck", "size": 2097152 }
]
}curl -X POST "https://gamerush.jp/api/games/$GAME_ID/builds" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d @manifest.json > build.json
jq -c '.uploadUrls[]' build.json | while read -r ticket; do
path=$(echo "$ticket" | jq -r '.path')
url=$(echo "$ticket" | jq -r '.url')
curl -X PUT "$url" -H "If-None-Match: *" --data-binary @"build/$path"
done
BUILD_ID=$(jq -r '.build.id' build.json)
curl -X POST "https://gamerush.jp/api/builds/$BUILD_ID/complete" \
-H "Authorization: Bearer $GRUSH_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'ファイルの一覧で決まること
engineはunity/godot/phaser/webのどれかです。- ルートに
index.htmlが要ります。HTML は圧縮せずに送ってください。 - ファイル数は 2000 まで、合計は 50MB までです(目安は 15MB 以下で、30MB 以上は危険です)。
sizeはそのまま送るバイト数を書きます。 - 使えるファイルの種類は Studio からのアップロードと同じです。ソースマップ(
.js.map)は含めないでください。 - Unity の
Build/x.wasm.brのように、書き出した時点で.br/.gzが付いたファイルはその名前のまま送ります。自分で gzip したファイルを送るときは、元の名前のpathに"encoding": "gzip"を添え、sizeは圧縮後の大きさにします。 - 最上位の
grush.jsonはランキングの定義として読みます(書式は SDK ガイドのランキング)。トークンにleaderboards:writeが無ければ403です。grush.jsonは 64KB までで、圧縮しないか"encoding": "gzip"で送ります。"encoding": "br"と、圧縮せずに送る 64KB 超のファイルは400です。gzip で送ったものの大きさは展開してから確かめ、64KB を超えれば complete が422を返します。
Studio の画面から Unity を選んで上げたときは、GameRush がプレイヤーを組み立ててローディングバーと先読みを付けます。API から上げたビルドは、送った index.html がそのまま使われます。
ファイルを送る
uploadUrls[].headersに入っているヘッダーは、そのまま付けて送ってください(いまはIf-None-Match: *です)。- 同じファイルは1度しか書けません。2度目は
412になるので、送信済みとして扱って構いません。途中で止まったときは、残りのファイルだけ送り直せます。 urlの期限は 1 時間です。
完了させる
complete は、送ったファイルの大きさ・中身の形式・HTML の内容を検査してから、ゲームの最新ビルドに切り替えます。
| 応答 | 意味 | 次にすること |
|---|---|---|
| 200 | ビルドが ready になり、ゲームの最新ビルドになった | — |
| 403 | 最上位に grush.json を含むビルドで、トークンに leaderboards:write が無い。ビルドには触れない | leaderboards:write を持つトークンで呼ぶ |
409(details.missing 付き) | 送っていないファイルがある。アップロード中のビルドは失敗扱いになる | ビルドの作成からやり直す |
409(details なし、ゲームの状態が変わった) | アップロード中に、ほかの操作でゲームの状態が変わった | 同じ complete をもう一度呼ぶ |
409(details なし、ビルドが失敗済み・破棄済み) | 前の complete で既に失敗したか、ビルドが破棄された | ビルドの作成からやり直す |
| 422 | 中身の検査で弾かれた(params.path に原因のファイル)。アップロード中のビルドは消える | ファイルを直してから作成し直す |
422(code が build.leaderboardManifest で始まる) | grush.json を読めないか、反映できない宣言がある(下の表)。アップロード中のビルドは消える | grush.json を直してから作成し直す |
| 503 | 一時的に処理できなかった | 同じ complete をもう一度呼ぶ |
| `grush.json` の 422 の `code` | 原因 |
|---|---|
build.leaderboardManifestInvalidJson | JSON のオブジェクトとして読めない |
build.leaderboardManifestUnknownField | 知らない項目がある(params.field) |
build.leaderboardManifestInvalidField | 値が正しくない(params.field) |
build.leaderboardManifestDuplicateKey | key が重複している(params.key) |
build.leaderboardManifestTooMany | 定義が 21 個以上ある |
build.leaderboardManifestTooLarge | 64KB を超える |
build.leaderboardManifestCompressed | brotli で圧縮されている |
build.leaderboardManifestSemanticsLocked | スコアが投稿済みの枠の sort・valueType・aggregation・period を変えようとした(params.key) |
build.leaderboardManifestLimit | すでにある枠と合わせて 1 ゲーム 20 個を超える |
grush.json を含むビルドの 200 の応答には leaderboards: { applied, unchanged, failed } が付きます。applied は作成か更新をした key、unchanged は同じ内容で何も書かなかった key です。検査の後に投稿が割り込むなどで書けなかった定義は、ビルドを最新にしたまま failed: [{ key, code }] に載ります。grush.json に書かなかった key の枠は、消えも止まりもしません。public のゲームで審査を待つビルドは、grush.json の検査だけを complete で行い、定義は審査で承認されて配信される時点で反映します。このときの応答には leaderboards の代わりに leaderboardsDeferred: true が付きます。
既に ready になったビルドへ complete をもう一度呼んで 400・409・422 が返ったときは、ビルドは ready のまま残り、配信も続きます。失敗扱いにも削除にもならないので、作成からやり直す必要はありません。
public のゲームに審査前のビルドを完了させると、ゲームは public のまま、新しいビルドが審査に積まれます(review_status が pending)。審査の間は前に承認されたビルドの配信が続き、承認されると新しいビルドに差し替わります。差し戻されたときは、新しいビルドは配信されず、承認済みのビルドの配信が続きます。新しいビルドは Studio の試遊で確かめられます。オーナー本人が運営の認めた認証済みクリエイターか管理者なら、審査を経ずにすぐ差し替わります。unlisted のゲームは審査を経ずに、unlisted のままビルドが差し替わります。
ビルドの作成には冪等キーが無いので、POST /api/games/:id/builds を機械的に再試行しないでください。再試行するたびに別のビルドができます。
5. ランキングの定義
ゲームから投稿するランキングの枠を宣言します。ゲーム側からの投稿と取得は SDK の役目で、ここにあるのは作者の手元から枠を管理する API です(SDK ガイドのランキング)。
API を使わずに、ビルドの最上位に置いた grush.json で同じ定義を宣言することもできます(書式は SDK ガイドのランキング、アップロードでの扱いは 4. ビルドのアップロード)。grush.json に書いた key の枠は、grush.json を含むビルドが最新になるたびにファイルの中身で書き換わります。ここの API で title・値域・enabled を変えても、そのようなビルドを次に上げたときにファイルの値へ戻ります。投稿のある枠の sort / valueType / aggregation / period を API で変えたときは、grush.json も合わせてください。食い違ったままのビルドは 422 で失敗します。
| API | 権限 | 内容 |
|---|---|---|
GET /api/games/:id/leaderboards | leaderboards:read | 定義の一覧(停止中も含む) |
PUT /api/games/:id/leaderboards/:key | leaderboards:write | key での冪等な作成・更新。スクリプトから流すならこれ |
POST /api/games/:id/leaderboards | leaderboards:write | 作成。同じ key があれば 409 |
PATCH /api/games/:id/leaderboards/:leaderboardId | leaderboards:write | 送ったフィールドだけ更新 |
DELETE /api/games/:id/leaderboards/:leaderboardId | leaderboards:write | 削除 |
GET /api/games/:id/leaderboards/anomalies | leaderboards:read | 不審な投稿として印が付いたエントリの一覧 |
| フィールド | 値 |
|---|---|
key | 英数字と . _ : - で 64 文字まで |
title | 60 文字まで |
sort | desc(大きいほど上)/ asc |
valueType | int / float / duration_ms |
aggregation | best / last / sum |
period | all_time / daily / weekly / monthly |
minValue / maxValue | 受け付ける値域。両方そろえて指定する |
enabled | false で投稿を止める(既定 true) |
1ゲームあたり 20 枠までです。投稿が1件でもある枠では sort / valueType / aggregation / period を変えられません(409)。コマンドの例と注意は SDK ガイドの API トークン にあります。
6. アナリティクス
GET /api/analytics/games/:id で、Studio のアナリティクス画面の「概要」と「パフォーマンス」と同じ数字をゲーム1本ぶん取れます。「プレイ時間と離脱」の数字は下の GET /api/analytics/games/:id/engagement で、「ファネル」の数字は GET /api/analytics/games/:id/funnels で、「カスタムイベント」の数字は GET /api/analytics/games/:id/events で、「エコノミー」の数字は GET /api/analytics/games/:id/economy で取ります。権限はどれも analytics:read です。
curl "https://gamerush.jp/api/analytics/games/$GAME_ID?period=7d" \
-H "Authorization: Bearer $GRUSH_TOKEN"period は 24h / 7d / 28d(既定)/ 90d / all です。
| フィールド | 内容 |
|---|---|
game | validPlays(有効プレイ数)・uniquePlayers・totalSessions・avgDurationSec・opens・skips・likeCount・commentCount・retention(翌日の再訪率と 7 日以内の再訪率) |
series | bucket ごとの plays / sessions / durationSec。期間に応じて1時間・6時間・1日で区切る |
performance | 端末で測ったロード時間(平均・95%の読み込みが収まる時間・途中離脱率)とフレームレート。標本が少ないうちは null |
surfaces | 面ごとの数。feed は landings(着地数)・validPlays、home は clicks(クリック数)・validPlays・impressions(表示数。未計測で常に null)。series は bucket ごとの同じ数。source が unavailable / failed のときは数を返さない |
engagementSeries | bucket ごとの uniquePlayers / opens / likes / comments。source が unavailable / failed のときは数を返さない |
period / generatedAt | 集計の期間と、集計した時刻 |
有効プレイは、遊び始めてから 10 秒を超えたプレイだけを数えます。ロード時間の数字は ゲームの最適化ガイド の効き目を確かめるのに使えます。
GET /api/analytics/games/:id/engagement で、Studio の「プレイ時間と離脱」と同じ数字を取れます。プレイヤーがどこで遊ぶのをやめるかを、経過時間ごとの割合で返します。period は上と同じです。
curl "https://gamerush.jp/api/analytics/games/$GAME_ID/engagement?period=7d" \
-H "Authorization: Bearer $GRUSH_TOKEN"| フィールド | 内容 |
|---|---|
engagement | sessions・firstSessions・players と、sessionCurve・firstSessionCurve・playerCurve(edgesSec の各秒の時点でまだ遊んでいた割合)・p50Sec / p75Sec / p90Sec(1回のプレイ時間)・avgPlayerSec・funnel(opened → revealed → played1s → played10s)。標本が少ないうちは件数だけを返し、値は null |
series | bucket ごとの sessions / players / durationSec / medianSec。区切りは上の series と同じ |
edgesSec | 曲線の横軸の秒。60 分以上は最後の点にまとめる |
scope | 数えた範囲。作者・共同制作者・運営のプレイは含まない |
曲線・分位・平均と series が数えるのは、プレイモードでゲームの表示を待ち始め、その回のうちに読み込みが終わった回だけです。待ち始めた後で閲覧モードへ戻った回は入り、閲覧モードで通り過ぎただけの回は入りません。funnel.opened だけは、表示の前に離れた回も数えます。engagement と series は、集計に失敗すると source が failed か unavailable になり、ほかの値を持ちません。
GET /api/analytics/games/:id/funnels で、Studio の「ファネル」と同じ数字を取れます。ゲームが SDK から送ったファネルのステップを、ステップごとの到達と離脱で返します。period は上と同じです。funnel は onboarding か recurring: に続けたファネルの名前で、省くか、一覧に無い値なら一覧の先頭のファネルを返します。
curl "https://gamerush.jp/api/analytics/games/$GAME_ID/funnels?period=28d&funnel=recurring:Shop" \
-H "Authorization: Bearer $GRUSH_TOKEN"| フィールド | 内容 |
|---|---|
list | hasEvents(期間を問わず、数える範囲のイベントが届いたことがあるか)・hasAnyEvents(作者・共同制作者・運営のものも含めて届いたことがあるか)・funnels(funnel・units・players)・other(一覧に入れなかったファネルの funnels と players。無ければ null) |
report | 選んだファネルの funnel・units・players・steps・biggestDropStep(前のステップからの率がいちばん低いステップ)。期間に始めた回のあるファネルが無ければ source が none |
report.steps | step・name・reached・reachedPlayers・fromStartRate・fromPreviousRate・dropped。onboarding は playSec(届いたときの累計プレイ秒の p25 / p50 / p75 / p90)と medianDays、recurring は medianElapsedSec(回を始めてからの秒)。分位と中央値は人ごとの値の上で取る |
scope | 数えた範囲。作者・共同制作者・運営のイベントは含まない |
collecting | ゲームからの分析イベントを今保存しているか。false の間は送ったイベントが残らない |
onboarding は人で、recurring は人と funnelSessionId の組(省いたステップはプレイセッション)を1回として数えます。期間の中で始めた回だけを数え、その回のステップは今までの到達をすべて数えます。先のステップに届いた回は、飛ばした手前のステップにも届いたと数えます。ファネルの名前は人数の多い上位 10 個まで返し、3人未満のファネルは other にまとめます。3人未満しか送っていないステップ名は null に、到達した人が5人未満のステップの時間は null になります。list と report は、集計に失敗すると source が failed か unavailable になります。
GET /api/analytics/games/:id/events で、Studio の「カスタムイベント」と同じ数字を取れます。ゲームが SDK から送ったカスタムイベントを、イベント名ごとの指標・推移・custom field ごとの内訳で返します。period は上と同じです。event はイベント名で、省くか、一覧に無い値なら一覧の先頭のイベントを返します。field は内訳に使う custom field のキーで、省くか、選べないキーなら内訳を返しません。
curl "https://gamerush.jp/api/analytics/games/$GAME_ID/events?period=28d&event=level_clear&field=stage" \
-H "Authorization: Bearer $GRUSH_TOKEN"| フィールド | 内容 |
|---|---|
list | hasEvents・hasAnyEvents(funnels と同じ)・events(key・count・players)・other(一覧に入れなかったイベント名の events・count・players。無ければ null) |
report | 選んだイベントの event・totals・series(bucket ごとの指標)・fields(内訳に選べるキー)・breakdown。名前を出せるイベントが期間に無ければ source が none |
指標 | count(回数)・sum(value の合計)・players(人数)・avg・min・max(人ごとの value の平均の、平均・最小・最大)・perPlayer(合計を人数で割った値) |
report.breakdown | field・values(value と指標)・other(values に入れなかった値をまとめた指標)・otherValues(その値の種類の数)・unset(そのキーを持たないイベントの指標) |
scope | 数えた範囲。作者・共同制作者・運営のイベントは含まない |
collecting | ゲームからの分析イベントを今保存しているか。false の間は送ったイベントが残らない |
期間の中に送られたイベントを数えます。イベント名は人数の多い上位 100 個まで返し、3人未満のイベント名は other にまとめます。custom field のキーと値も3人未満のものは名前を出さず、値は上位 20 個まで返して残りを breakdown.other にまとめます。sum・avg・min・max・perPlayer は、対象の人数が5人未満なら null になります。推移の区切りと内訳の行(other を含む)も、それぞれの人数で同じです。期間の sum から見えている区切りや行の sum を引いて隠した値が戻るときは、人数のいちばん少ない区切りや行の sum と perPlayer も null にします。list と report は、集計に失敗すると source が failed か unavailable になります。
GET /api/analytics/games/:id/economy で、Studio の「エコノミー」と同じ数字を取れます。ゲームが SDK から送った通貨の入手(source)と消費(sink)を、通貨ごとの合計・日ごとの推移・所持・内訳で返します。period は上と同じです。currency は通貨の名前で、省くか、一覧に無い値なら人数のいちばん多い通貨を返します。
curl "https://gamerush.jp/api/analytics/games/$GAME_ID/economy?period=28d¤cy=Gold" \
-H "Authorization: Bearer $GRUSH_TOKEN"| フィールド | 内容 |
|---|---|
list | hasEvents・hasAnyEvents(funnels と同じ)・currencies(currency・players)・other(一覧に入れなかった通貨の currencies と players。無ければ null) |
report | 選んだ通貨の currency・players・sourcePlayers・sinkPlayers・totals(source・sink・net)・latestBalance(人ごとの期間の中の最後の所持の p50 / p90)・days・breakdown。期間に行のある通貨が無ければ source が none |
report.days | UTC の日ごとの day・source・sink・net・players・sourcePlayers・sinkPlayers・balanceAvg(人ごとのその日の最後の所持の平均)。行の無い日は players が 0 で、量は 0、balanceAvg は null。期間を区切ると、最初の日は期間の始まりの時刻から後だけを数える |
report.breakdown | transactionType と itemSku のそれぞれに、source と sink ごとの items(name・amount・players)と other(names・amount・players)。品目を送らなかった行の name は null |
scope | 数えた範囲。作者・共同制作者・運営のイベントは含まない |
collecting | funnels と同じ |
量はどれも正の値で、net は入手から消費を引いた値です。量と所持はゲームが送った値のままで、GameRush は確かめません。通貨は人数の多い上位 10 個まで、取引の種類と品目は入手と消費のそれぞれで人数の多い上位 20 個まで返し、3人未満の名前は other にまとめます。latestBalance は人数が5人未満なら null、balanceAvg はその日の人数が5人未満なら null です。量(totals・days の source / sink・内訳の amount)も、入手(消費)した人が5人未満なら null で、net は入手と消費の両方を出せるときだけ値を持ちます。隠した量を同じ応答の合計から引き算で戻せないよう、和の関係(期間の合計 ↔ days、期間の合計 ↔ 内訳の行と other)の中で隠した値が1つだけになるときは、人数が最小のほかの値も null にします。期間の違う2つの応答の差からは戻せることがあります。list と report は、集計に失敗すると source が failed か unavailable になります。
7. 自分のツールからトークンを取る
作者に Studio でトークンを発行して貼ってもらう代わりに、ブラウザで承認してもらって自分のツールがトークンを受け取る形も取れます(RFC 8252 のループバック + PKCE)。Unity の Editor 拡張はこの形です。
- ツールが手元で
http://127.0.0.1:<port>の HTTP サーバを立て、code_verifier(43〜128 文字のランダムな文字列)を作る - ブラウザで下の URL を開く。作者がログインして内容を確かめ、承認ボタンを押す
- ブラウザが
redirect_uri?code=…&state=…へ戻ってくる。stateが送ったものと同じか確かめる exchangeにcodeとcode_verifierを送り、トークンを受け取る
https://gamerush.jp/studio/authorize
?redirect_uri=http://127.0.0.1:53682
&code_challenge=<base64url(sha256(code_verifier))>
&code_challenge_method=S256
&client_name=My%20Build%20Tool
&scopes=games:read,builds:write
&state=<ランダムな値>curl -X POST "https://gamerush.jp/api/api-token-authorizations/exchange" \
-H "Content-Type: application/json" \
-d '{"code":"<戻ってきた code>","codeVerifier":"<code_verifier>","redirectUri":"http://127.0.0.1:53682"}'redirect_uriはhttp://127.0.0.1:<port>/http://localhost:<port>/http://[::1]:<port>だけです。クエリもフラグメントも付けられません。code_challenge_methodはS256だけです。scopesはカンマ区切りです。game_idsにゲーム ID をカンマ区切りで渡すと、トークンの対象をそのゲームに絞れます。games:createとは一緒に使えません。codeはワンタイムで 5 分です。code_verifierを間違えたときは承認からやり直してください。- 応答は
{ token, secret }で、secretがトークンの本体です。有効期限は 90 日です。有効なトークンが 20 本あると409になります。 client_nameは承認画面と Studio のトークン一覧に出ます。