REST API リファレンス
SDK は、この HTTPS + JSON API を薄くラップしたクライアントです。どのエンジン、ツール、サーバーからでも API を直接利用できます。
コードのコメントと API 名は、SDK と一致させるため英語のままにしています。
基本#
ベース URL:https://majacloud.majanite.com/v1。localhost からのリクエストを除き、HTTPS が必須です。リクエストボディは Content-Type: application/json の JSON で送信します。
OpenAPI 3.1 定義をダウンロードして、クライアントを生成したり、Postman や Insomnia にインポートしたりできます。
ヘッダー#
| ヘッダー | 意味 |
|---|---|
X-Project-ID | ダッシュボードのプロジェクト ID(常に必要)。 |
X-Client-Key | 公開クライアントキー(常に必要。ビルドに含めても安全)。 |
X-Secret-Key | クライアントキーの代わりに使う、サーバー用のシークレットキー(サーバー間通信のみ)。 |
Authorization | プレイヤー向けエンドポイントでは Bearer <access_token>。 |
X-Device-ID | 任意のインストール ID(ゲストのデバイスラベルとして使用)。 |
X-Majacloud-SDK | 任意のクライアント名とバージョン(例: unity/2.0.0)。 |
レスポンス#
すべてのレスポンスは ok を含む JSON です。エラーの場合は、安定した code、message、request_id、場合によっては details も含まれます。
var top = await Majacloud.Leaderboards.GetTopAsync("coins", 10);
if (top.Ok)
{
foreach (var entry in top.Value.Entries)
Debug.Log($"#{entry.Rank} {entry.PlayerName} {entry.Score}");
}
else if (top.Error.IsRetryable)
{
// Network, timeout, 5xx or rate limit: try again later
Debug.Log("Retry in " + top.Error.RetryAfterSeconds + " s");
}
else
{
Debug.LogWarning(top.Error.Code + ": " + top.Error.Message + " (" + top.Error.RequestId + ")");
}var top := await Majacloud.leaderboards.get_top("coins", 10)
if top.ok:
for entry in top.value.entries:
print("#%d %s %d" % [entry.rank, entry.player_name, entry.score])
elif top.is_retryable():
# Network, timeout, 5xx or rate limit: try again later
print("Retry in ", top.retry_after, " s")
else:
push_warning("%s: %s (%s)" % [top.error, top.message, top.request_id])const top = await mc.leaderboards.getTop('coins', { limit: 10 });
if (top.ok) {
for (const entry of top.value.entries) {
console.log(`#${entry.rank} ${entry.player_name} ${entry.score}`);
}
} else if (top.error.retryable) {
// Network, timeout, 5xx or rate limit: try again later
console.log('Retry in', top.error.retryAfter, 's');
} else {
console.warn(`${top.error.code}: ${top.error.message} (${top.error.requestId})`);
}// Success
{ "ok": true, "entries": [ … ], "total": 42 }
// Error (HTTP 4xx/5xx)
{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Project rate limit reached. Try again in a minute.",
"request_id": "6f1c2a9e-…",
"details": { "limit": 120, "window": "minute" }
}
}例#
export PROJECT_ID="<project id>" CLIENT_KEY="pk_live_…"
curl https://majacloud.majanite.com/v1/project -H "X-Project-ID: $PROJECT_ID" -H "X-Client-Key: $CLIENT_KEY"
curl -X POST https://majacloud.majanite.com/v1/auth/guest -H "X-Project-ID: $PROJECT_ID" -H "X-Client-Key: $CLIENT_KEY" \
-H "Content-Type: application/json" -d '{}'エンドポイント#
プロジェクト#
GET/projectプロジェクト情報、プラン、リモートコンフィグの公開鍵クライアントキー
レスポンス 200
{
"ok": true,
"project": {
"id": "8f3c…",
"name": "Space Runner",
"plan": "free",
"config_version": 12,
"config_public_key_xml": "<RSAKeyValue>…</RSAKeyValue>",
"config_public_key_pem": "-----BEGIN PUBLIC KEY-----\n…\n-----END PUBLIC KEY-----\n",
"services": {
"player_auth": true,
"leaderboards": true,
"remote_config": true,
"cloud_save": true,
"rewards": true
}
}
}
プレイヤー認証#
POST/auth/guestゲストプレイヤーとセッションを作成クライアントキー
ボディ
{
"device_id": "optional installation id"
}
レスポンス 201
{
"ok": true,
"auth_method": "guest",
"access_token": "eyJ2IjoyLCJ0IjoiYWNjZXNz…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "2d0f…",
"refresh_expires_in": 2592000,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false
}
}
POST/auth/refreshリフレッシュトークンをローテーションし、新しいアクセストークンを取得クライアントキー
ボディ
{
"refresh_token": "…"
}
レスポンス 200
{
"ok": true,
"auth_method": "guest",
"access_token": "eyJ2IjoyLCJ0IjoiYWNjZXNz…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "2d0f…",
"refresh_expires_in": 2592000,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false
}
}
エラー
unauthorized (reason: invalid | expired | revoked | reused)
POST/auth/logoutセッションを失効クライアントキー
ボディ
{
"refresh_token": "optional"
}
レスポンス 200
{
"ok": true,
"revoked": true
}
POST/auth/link/startWeb ログインを開始(ゲストをメールアドレスまたは Google と連携)プレイヤートークン
ボディ
{
"code_challenge": "base64url(sha256(verifier))",
"code_challenge_method": "S256",
"return_url": "optional, https on this host or an allowlisted scheme"
}
レスポンス 201
{
"ok": true,
"flow_id": "uuid",
"flow_token": "…",
"auth_url": "https://majacloud.majanite.com/player-auth.php?flow_id=…&flow_token=…",
"expires_at": "2026-10-09T08:27:00Z",
"poll_interval_seconds": 3
}
GET/auth/link/statusログインフローの状態をポーリングクライアントキー
クエリ
flow_id— uuidflow_token— …
レスポンス 200
{
"ok": true,
"status": "pending | completed | consumed | expired",
"exchange_code": "(only when completed)",
"expires_at": "…"
}
POST/auth/link/exchange完了したフローをセッションと交換クライアントキー
ボディ
{
"flow_id": "uuid",
"exchange_code": "…",
"code_verifier": "the original verifier"
}
レスポンス 200
{
"ok": true,
"auth_method": "guest",
"access_token": "eyJ2IjoyLCJ0IjoiYWNjZXNz…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "2d0f…",
"refresh_expires_in": 2592000,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false
},
"merged_guest": true
}
GET/players/meログイン中のプレイヤープレイヤートークン
レスポンス 200
{
"ok": true,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false
}
}
PATCH/players/me表示名を変更プレイヤートークン
ボディ
{
"display_name": "Nova"
}
レスポンス 200
{
"ok": true,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false
}
}
GET/players/{player_id}任意のプレイヤーを読み取り(シークレットキー)シークレットキー
レスポンス 200
{
"ok": true,
"player": {
"id": "c7a1…",
"player_id": "player_3f9c…",
"display_name": "Guest 4821",
"auth_type": "guest",
"email_verified": false,
"email": "nova@example.com",
"wallets": [
{
"currency": "coins",
"balance": 150
}
]
}
}
リーダーボード#
POST/leaderboards/{slug}/scoresスコアを送信プレイヤートークン
ボディ
{
"score": 120
}
レスポンス 200
{
"ok": true,
"accepted": true,
"entry": {
"rank": 1,
"player_id": "player_3f9c…",
"player_name": "Nova",
"score": 9840,
"score_updated_at": "2026-10-09T08:12:00Z",
"is_me": false
},
"period": {
"key": "2026-W41",
"ends_at": "2026-10-12T00:00:00Z"
}
}
エラー
validation (bounds)rate_limited (cooldown)plan_limit (entry cap)
GET/leaderboards/{slug}/entries上位のエントリークライアントキー
クエリ
limit— 1-100 (default 10)offset— 0+period— current | previous
レスポンス 200
{
"ok": true,
"leaderboard": {
"slug": "coins",
"name": "Coins",
"sort_type": "DESC",
"score_mode": "BEST",
"reset_rule": "WEEKLY"
},
"period": {
"key": "2026-W41",
"ends_at": "2026-10-12T00:00:00Z"
},
"entries": [
{
"rank": 1,
"player_id": "player_3f9c…",
"player_name": "Nova",
"score": 9840,
"score_updated_at": "2026-10-09T08:12:00Z",
"is_me": false
}
],
"total": 42,
"limit": 10,
"offset": 0,
"max_entries": 10
}
GET/leaderboards/{slug}/me自分の順位とスコアプレイヤートークン
クエリ
period— current | previous
レスポンス 200
{
"ok": true,
"entry": {
"rank": 1,
"player_id": "player_3f9c…",
"player_name": "Nova",
"score": 9840,
"score_updated_at": "2026-10-09T08:12:00Z",
"is_me": false
},
"total": 42
}
GET/leaderboards/{slug}/around-me自分の順位の前後のエントリープレイヤートークン
クエリ
radius— 1-25 (default 3)
レスポンス 200
{
"ok": true,
"entries": [
{
"rank": 1,
"player_id": "player_3f9c…",
"player_name": "Nova",
"score": 9840,
"score_updated_at": "2026-10-09T08:12:00Z",
"is_me": false
}
],
"me": {
"rank": 1,
"player_id": "player_3f9c…",
"player_name": "Nova",
"score": 9840,
"score_updated_at": "2026-10-09T08:12:00Z",
"is_me": false
},
"total": 42
}
リモートコンフィグ#
GET/configRSA 署名付きのライブコンフィグ。If-None-Match を送ると 304 が返りますクライアントキー
レスポンス 200
{
"ok": true,
"project_id": "8f3c…",
"version": 12,
"checksum": "sha256 of data",
"data": "base64url(JSON payload)",
"signature": "base64 RSA-SHA256 over data",
"signature_algorithm": "rsa-sha256",
"signing_key_id": "config-v1",
"configs": [
{
"key": "enemy_damage",
"type": "number",
"value": "25"
}
]
}
クラウドセーブ#
GET/cloud保存済みのキーを一覧表示プレイヤートークン
レスポンス 200
{
"ok": true,
"keys": [
{
"key": "progress",
"revision": 3,
"size_bytes": 180,
"updated_at": "…"
}
],
"total_bytes": 180
}
GET/cloud/{key}ドキュメントを読み込みプレイヤートークン
レスポンス 200
{
"ok": true,
"key": "progress",
"data": {
"level": 3
},
"revision": 3,
"size_bytes": 180,
"updated_at": "…"
}
PUT/cloud/{key}ドキュメントを保存(期待するリビジョンは任意)プレイヤートークン
ボディ
{
"data": {
"level": 4
},
"revision": "optional: expected current revision (0 = create only)"
}
レスポンス 200
{
"ok": true,
"key": "progress",
"revision": 4,
"size_bytes": 190,
"updated_at": "…",
"created": false
}
エラー
revision_mismatch (details.current_revision)plan_limit (storage)
DELETE/cloud/{key}ドキュメントを削除プレイヤートークン
レスポンス 200
{
"ok": true,
"key": "progress",
"deleted": true
}
報酬とウォレット#
GET/rewards有効な報酬(プレイヤートークンがある場合は受け取り可否のフラグ付き)クライアントキー
レスポンス 200
{
"ok": true,
"rewards": [
{
"reward_key": "daily_coins",
"name": "Daily coins",
"amount": 50,
"currency": "coins",
"cooldown": "daily",
"claimable": true,
"next_claim_at": null
}
]
}
POST/rewards/claim報酬を受け取るプレイヤートークン
ボディ
{
"reward_key": "daily_coins"
}
レスポンス 200
{
"ok": true,
"accepted": true,
"reward_key": "daily_coins",
"amount": 50,
"currency": "coins",
"balance": 150,
"next_claim_at": "2026-10-10T00:00:00Z"
}
エラー
conflict (already claimed; details.next_claim_at)
GET/walletウォレットの残高プレイヤートークン
レスポンス 200
{
"ok": true,
"wallets": [
{
"currency": "coins",
"balance": 150,
"updated_at": "…"
}
]
}