{
  "openapi": "3.1.0",
  "info": {
    "title": "HomeGame24 Integration API",
    "version": "1.0.0",
    "description": "Build against HomeGame24 with a scoped panel API key.\n\n**Quick start**\n1. Create a key under **API Keys** (`pk_…`) and grant only the scopes you need.\n2. Call `/v1` with `Authorization: Bearer pk_…` and `Accept: application/vnd.api+json`.\n3. Use Player Groups for access, then attach a group to a Game Session.\n\nResponses follow JSON:API 1.1. Request and response examples are shown per operation.\n\n**Rate limits**\n- Authenticated `/v1` requests: **120 requests per 60 seconds** per API key.\n- Enforced via Cloudflare Workers Rate Limiting (per Cloudflare location / PoP).\n- `GET /v1/openapi.json` is not rate limited.\n- When exceeded, the API returns **429** with `Retry-After` and `X-RateLimit-Limit` headers.\n- Configure the limit in `wrangler.toml` (`[[ratelimits]]` → `API_RATE_LIMITER`) and keep `src/lib/v1-rate-limit.ts` in sync for docs."
  },
  "servers": [
    {
      "url": "/v1",
      "description": "Production and local base path for the Integration API"
    }
  ],
  "tags": [
    {
      "name": "Players",
      "description": "Create and manage player accounts owned by your admin."
    },
    {
      "name": "Player Groups",
      "description": "Organize players into groups, then assign a group to a Game Session for access control."
    },
    {
      "name": "Wallets",
      "description": "Read balances and adjust chips the same way the panel does."
    },
    {
      "name": "Game Sessions",
      "description": "Launch and configure runs. Set `player_group_uid` to control who can join."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "Send your panel API key as `Authorization: Bearer pk_…`. Create and scope keys under **API Keys** in the panel."
      }
    },
    "schemas": {
      "PlayerResource": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["players"]
          },
          "id": {
            "type": "string",
            "description": "Player UID"
          },
          "attributes": {
            "type": "object",
            "properties": {
              "nickname": {
                "type": "string",
                "nullable": true
              },
              "username": {
                "type": "string",
                "nullable": true
              },
              "email": {
                "type": "string",
                "nullable": true
              },
              "phone": {
                "type": "string",
                "nullable": true
              },
              "extra": {
                "type": "object",
                "additionalProperties": true,
                "nullable": true
              },
              "player_group_uids": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              }
            }
          }
        }
      },
      "PlayerGroupResource": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["player_groups"]
          },
          "id": {
            "type": "string",
            "description": "Player Group UID"
          },
          "attributes": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "description": {
                "type": "string",
                "nullable": true
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              }
            }
          }
        }
      },
      "PlayerBalanceResource": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["player-balances"]
          },
          "id": {
            "type": "string"
          },
          "attributes": {
            "type": "object",
            "properties": {
              "player_uid": {
                "type": "string"
              },
              "unit": {
                "type": "string",
                "description": "Wallet Unit UID"
              },
              "wallet_code": {
                "type": "string",
                "description": "Wallet code. Defaults to `main` for chip wallets."
              },
              "balance": {
                "type": "string"
              }
            }
          }
        }
      },
      "SessionResource": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["game_sessions"]
          },
          "id": {
            "type": "string"
          },
          "attributes": {
            "type": "object"
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              }
            }
          }
        }
      },
      "JsonApiError": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "responses": {
      "TooManyRequests": {
        "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
        "content": {
          "application/vnd.api+json": {
            "schema": {
              "type": "object",
              "properties": {
                "errors": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "status": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "detail": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            },
            "example": {
              "errors": [
                {
                  "status": "429",
                  "title": "Too many requests",
                  "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                }
              ]
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/players": {
      "get": {
        "tags": ["Players"],
        "summary": "List Players",
        "description": "Browse players you own. Scope: `players:read`.\n\nSupports cursor pagination plus JSON:API filters and sorts.\n\n**Filters** — combine as needed:\n- `filter[q][contains]` — search uid, nickname, username, email, or phone\n- `filter[uid][eq|in]` — one UID, or several comma-separated\n- `filter[nickname|username|email|phone][eq|in|contains]` — field match\n\n**Sort** — e.g. `sort=-created_at,nickname` (`-` = descending).\nFields: `uid`, `nickname`, `username`, `email`, `phone`, `created_at`, `updated_at`.",
        "parameters": [
          {
            "name": "page[cursor]",
            "in": "query",
            "description": "Continue from `meta.nextCursor` on the previous page.",
            "schema": {
              "type": "string"
            },
            "example": "01J8ZP0R7K3M9QY4T6W2X5N1AB"
          },
          {
            "name": "page[limit]",
            "in": "query",
            "description": "Results per page. Default 25.",
            "schema": {
              "type": "integer",
              "default": 25,
              "minimum": 1
            },
            "example": 25
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Comma-separated fields. Prefix with `-` for descending.",
            "schema": {
              "type": "string"
            },
            "example": "-created_at,nickname"
          },
          {
            "name": "filter[q][contains]",
            "in": "query",
            "description": "Quick search across uid, nickname, username, email, and phone.",
            "schema": {
              "type": "string"
            },
            "example": "ace"
          },
          {
            "name": "filter[uid][eq]",
            "in": "query",
            "description": "Match a single player UID.",
            "schema": {
              "type": "string"
            },
            "example": "01J8ZP0R7K3M9QY4T6W2X5N1AB"
          },
          {
            "name": "filter[uid][in]",
            "in": "query",
            "description": "Match several player UIDs (comma-separated).",
            "schema": {
              "type": "string"
            },
            "example": "01J8ZP0R7K3M9QY4T6W2X5N1AB,01J8ZP0R7K3M9QY4T6W2X5N1AC"
          },
          {
            "name": "filter[nickname][eq]",
            "in": "query",
            "description": "Exact nickname.",
            "schema": {
              "type": "string"
            },
            "example": "Ace"
          },
          {
            "name": "filter[nickname][contains]",
            "in": "query",
            "description": "Nickname contains this text (case-insensitive).",
            "schema": {
              "type": "string"
            },
            "example": "ac"
          },
          {
            "name": "filter[nickname][in]",
            "in": "query",
            "description": "Any of these nicknames (comma-separated).",
            "schema": {
              "type": "string"
            },
            "example": "Ace,Bob"
          },
          {
            "name": "filter[username][eq]",
            "in": "query",
            "description": "Exact username.",
            "schema": {
              "type": "string"
            },
            "example": "ace_player"
          },
          {
            "name": "filter[username][contains]",
            "in": "query",
            "description": "Username contains this text (case-insensitive).",
            "schema": {
              "type": "string"
            },
            "example": "ace"
          },
          {
            "name": "filter[username][in]",
            "in": "query",
            "description": "Any of these usernames (comma-separated).",
            "schema": {
              "type": "string"
            },
            "example": "ace_player,bob_player"
          },
          {
            "name": "filter[email][eq]",
            "in": "query",
            "description": "Exact email address.",
            "schema": {
              "type": "string"
            },
            "example": "ace@example.com"
          },
          {
            "name": "filter[email][contains]",
            "in": "query",
            "description": "Email contains this text (case-insensitive).",
            "schema": {
              "type": "string"
            },
            "example": "@example.com"
          },
          {
            "name": "filter[email][in]",
            "in": "query",
            "description": "Any of these emails (comma-separated).",
            "schema": {
              "type": "string"
            },
            "example": "ace@example.com,bob@example.com"
          },
          {
            "name": "filter[phone][eq]",
            "in": "query",
            "description": "Exact phone number.",
            "schema": {
              "type": "string"
            },
            "example": "+15551234567"
          },
          {
            "name": "filter[phone][contains]",
            "in": "query",
            "description": "Phone contains this text.",
            "schema": {
              "type": "string"
            },
            "example": "555"
          },
          {
            "name": "filter[phone][in]",
            "in": "query",
            "description": "Any of these phone numbers (comma-separated).",
            "schema": {
              "type": "string"
            },
            "example": "+15551234567,+15559876543"
          }
        ],
        "responses": {
          "200": {
            "description": "Player Collection",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": ["players"]
                          },
                          "id": {
                            "type": "string",
                            "description": "Player UID"
                          },
                          "attributes": {
                            "type": "object",
                            "properties": {
                              "nickname": {
                                "type": "string",
                                "nullable": true
                              },
                              "username": {
                                "type": "string",
                                "nullable": true
                              },
                              "email": {
                                "type": "string",
                                "nullable": true
                              },
                              "phone": {
                                "type": "string",
                                "nullable": true
                              },
                              "extra": {
                                "type": "object",
                                "additionalProperties": true,
                                "nullable": true
                              },
                              "player_group_uids": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "created_at": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "updated_at": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          },
                          "links": {
                            "type": "object",
                            "properties": {
                              "self": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "type": "players",
                      "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                      "attributes": {
                        "nickname": "Ace",
                        "username": "ace_player",
                        "email": "ace@example.com",
                        "phone": "+15551234567",
                        "extra": null,
                        "player_group_uids": ["01J8ZGROUP0000000000000001"],
                        "created_at": "2026-07-01T12:00:00.000Z",
                        "updated_at": "2026-07-01T12:00:00.000Z"
                      },
                      "links": {
                        "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                      }
                    }
                  ],
                  "links": {
                    "self": "https://api.example.com/v1/players?page[limit]=25",
                    "next": null,
                    "prev": null
                  },
                  "meta": {
                    "total": 1,
                    "limit": 25,
                    "nextCursor": null
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "401",
                      "title": "Unauthorized",
                      "detail": "Invalid or missing API key"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Missing Scope",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "403",
                      "title": "Forbidden",
                      "detail": "API key is missing required scope"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Players"],
        "summary": "Create Player",
        "description": "Register a new player under your account. Scope: `players:write`. Password is required and never returned.",
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["players"]
                      },
                      "attributes": {
                        "type": "object",
                        "properties": {
                          "nickname": {
                            "type": "string",
                            "nullable": true
                          },
                          "username": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "nullable": true
                          },
                          "phone": {
                            "type": "string",
                            "nullable": true
                          },
                          "password": {
                            "type": "string",
                            "description": "Required when creating a player. Never returned in responses."
                          },
                          "extra": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          },
                          "player_group_uids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "players",
                  "attributes": {
                    "nickname": "Ace",
                    "username": "ace_player",
                    "email": "ace@example.com",
                    "phone": "+15551234567",
                    "password": "correct-horse-battery",
                    "player_group_uids": ["01J8ZGROUP0000000000000001"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["players"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "nickname": {
                              "type": "string",
                              "nullable": true
                            },
                            "username": {
                              "type": "string",
                              "nullable": true
                            },
                            "email": {
                              "type": "string",
                              "nullable": true
                            },
                            "phone": {
                              "type": "string",
                              "nullable": true
                            },
                            "extra": {
                              "type": "object",
                              "additionalProperties": true,
                              "nullable": true
                            },
                            "player_group_uids": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "players",
                    "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                    "attributes": {
                      "nickname": "Ace",
                      "username": "ace_player",
                      "email": "ace@example.com",
                      "phone": "+15551234567",
                      "extra": null,
                      "player_group_uids": ["01J8ZGROUP0000000000000001"],
                      "created_at": "2026-07-01T12:00:00.000Z",
                      "updated_at": "2026-07-01T12:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                    }
                  },
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation Error",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "400",
                      "title": "Bad Request",
                      "detail": "Validation failed"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "409",
                      "title": "Conflict",
                      "detail": "Username is already taken"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/players/{id}": {
      "get": {
        "tags": ["Players"],
        "summary": "Get Player",
        "description": "Fetch one player by UID. Scope: `players:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Player",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["players"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "nickname": {
                              "type": "string",
                              "nullable": true
                            },
                            "username": {
                              "type": "string",
                              "nullable": true
                            },
                            "email": {
                              "type": "string",
                              "nullable": true
                            },
                            "phone": {
                              "type": "string",
                              "nullable": true
                            },
                            "extra": {
                              "type": "object",
                              "additionalProperties": true,
                              "nullable": true
                            },
                            "player_group_uids": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "players",
                    "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                    "attributes": {
                      "nickname": "Ace",
                      "username": "ace_player",
                      "email": "ace@example.com",
                      "phone": "+15551234567",
                      "extra": null,
                      "player_group_uids": ["01J8ZGROUP0000000000000001"],
                      "created_at": "2026-07-01T12:00:00.000Z",
                      "updated_at": "2026-07-01T12:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                    }
                  },
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Players"],
        "summary": "Update Player",
        "description": "Update profile fields or group membership. Scope: `players:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["players"]
                      },
                      "id": {
                        "type": "string"
                      },
                      "attributes": {
                        "type": "object",
                        "properties": {
                          "nickname": {
                            "type": "string",
                            "nullable": true
                          },
                          "username": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "nullable": true
                          },
                          "phone": {
                            "type": "string",
                            "nullable": true
                          },
                          "password": {
                            "type": "string",
                            "description": "Required when creating a player. Never returned in responses."
                          },
                          "extra": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          },
                          "player_group_uids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "players",
                  "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                  "attributes": {
                    "nickname": "Ace Updated",
                    "email": "ace@example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["players"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "nickname": {
                              "type": "string",
                              "nullable": true
                            },
                            "username": {
                              "type": "string",
                              "nullable": true
                            },
                            "email": {
                              "type": "string",
                              "nullable": true
                            },
                            "phone": {
                              "type": "string",
                              "nullable": true
                            },
                            "extra": {
                              "type": "object",
                              "additionalProperties": true,
                              "nullable": true
                            },
                            "player_group_uids": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "players",
                    "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                    "attributes": {
                      "nickname": "Ace",
                      "username": "ace_player",
                      "email": "ace@example.com",
                      "phone": "+15551234567",
                      "extra": null,
                      "player_group_uids": ["01J8ZGROUP0000000000000001"],
                      "created_at": "2026-07-01T12:00:00.000Z",
                      "updated_at": "2026-07-01T12:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                    }
                  },
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Players"],
        "summary": "Delete Player",
        "description": "Soft-delete a player. Scope: `players:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/players/{id}/balance": {
      "get": {
        "tags": ["Wallets"],
        "summary": "Get Player Balance",
        "description": "Read a player chip balance for a wallet unit. Scope: `wallets:read`. `wallet_code` defaults to `main`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player UID"
          },
          {
            "name": "unit",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Wallet Unit UID (e.g. CHIP)."
          },
          {
            "name": "wallet_code",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "main"
            },
            "description": "Wallet code within the unit. Defaults to `main`."
          }
        ],
        "responses": {
          "200": {
            "description": "Balance",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["player-balances"]
                        },
                        "id": {
                          "type": "string"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "player_uid": {
                              "type": "string"
                            },
                            "unit": {
                              "type": "string",
                              "description": "Wallet Unit UID"
                            },
                            "wallet_code": {
                              "type": "string",
                              "description": "Wallet code. Defaults to `main` for chip wallets."
                            },
                            "balance": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "player-balances",
                    "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                    "attributes": {
                      "player_uid": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                      "unit": "CHIP",
                      "wallet_code": "main",
                      "balance": "1250.00"
                    }
                  },
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB/balance?unit=CHIP&wallet_code=main"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/players/{id}/balance/adjust": {
      "post": {
        "tags": ["Wallets"],
        "summary": "Adjust Player Balance",
        "description": "Set an absolute target `balance`. The API deposits or withdraws the difference — same as chip adjust in the panel. Scope: `wallets:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player UID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["player-balances"]
                      },
                      "attributes": {
                        "type": "object",
                        "required": ["balance", "unit"],
                        "properties": {
                          "balance": {
                            "type": "string",
                            "description": "Absolute target balance. The delta is applied automatically."
                          },
                          "unit": {
                            "type": "string",
                            "description": "Wallet Unit UID."
                          },
                          "wallet_code": {
                            "type": "string",
                            "default": "main",
                            "description": "Defaults to `main`."
                          },
                          "external_transaction_id": {
                            "type": "string",
                            "description": "Optional idempotency / external ledger reference."
                          },
                          "description": {
                            "type": "string",
                            "description": "Optional note stored on the ledger entry."
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "player-balances",
                  "attributes": {
                    "balance": "1300",
                    "unit": "CHIP",
                    "wallet_code": "main",
                    "external_transaction_id": "bonus-2026-07-27-001",
                    "description": "Daily bonus"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Adjusted Balance",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["player-balances"]
                        },
                        "id": {
                          "type": "string"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "player_uid": {
                              "type": "string"
                            },
                            "unit": {
                              "type": "string",
                              "description": "Wallet Unit UID"
                            },
                            "wallet_code": {
                              "type": "string",
                              "description": "Wallet code. Defaults to `main` for chip wallets."
                            },
                            "balance": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "player-balances",
                    "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                    "attributes": {
                      "player_uid": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                      "unit": "CHIP",
                      "wallet_code": "main",
                      "balance": "1300.00"
                    }
                  },
                  "links": {
                    "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB/balance/adjust"
                  },
                  "meta": {
                    "previous_balance": "1250.00",
                    "new_balance": "1300.00",
                    "diff": "50",
                    "external_transaction_id": "bonus-2026-07-27-001"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Insufficient Balance or Validation Error",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "400",
                      "title": "Bad Request",
                      "detail": "Insufficient balance for this adjustment"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/sessions": {
      "get": {
        "tags": ["Game Sessions"],
        "summary": "List Game Sessions",
        "description": "List runs you own, newest first by default. Scope: `sessions:read`.",
        "responses": {
          "200": {
            "description": "Game Session Collection",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": ["game_sessions"]
                          },
                          "id": {
                            "type": "string"
                          },
                          "attributes": {
                            "type": "object"
                          },
                          "links": {
                            "type": "object",
                            "properties": {
                              "self": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "type": "game_sessions",
                      "id": "01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                      "attributes": {
                        "client": {
                          "uid": "01J8ZCLIENT000000000000001",
                          "name": "Poker Cash"
                        },
                        "game": {
                          "uid": "01J8ZGAME00000000000000001",
                          "name": "NL Holdem Cash"
                        },
                        "account_unit": {
                          "uid": "CHIP",
                          "name": "Chips",
                          "symbol": "CHIP",
                          "icon": "chip"
                        },
                        "play_unit": {
                          "uid": "CHIP",
                          "name": "Chips",
                          "symbol": "CHIP",
                          "icon": "chip"
                        },
                        "player_group": {
                          "uid": "01J8ZGROUP0000000000000001",
                          "name": "Regulars"
                        },
                        "url": "https://game.example.com/play/?s=01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                        "status": "Live",
                        "valid_from": "2026-07-27T10:00:00.000Z",
                        "valid_to": "2026-07-28T10:00:00.000Z",
                        "created_at": "2026-07-27T09:00:00.000Z",
                        "updated_at": "2026-07-27T09:00:00.000Z"
                      },
                      "links": {
                        "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                      }
                    }
                  ],
                  "links": {
                    "self": "https://api.example.com/v1/sessions?page[limit]=25",
                    "next": null,
                    "prev": null
                  },
                  "meta": {
                    "total": 1,
                    "limit": 25,
                    "nextCursor": null
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Game Sessions"],
        "summary": "Create Game Session",
        "description": "Start a new run from a game. Optionally attach a Player Group so only those players can join. Scope: `sessions:write`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["game_sessions"]
                      },
                      "attributes": {
                        "type": "object",
                        "required": [
                          "game_uid",
                          "emoji_collection_uid",
                          "message_collection_uid",
                          "avatar_collection_uid"
                        ],
                        "properties": {
                          "game_uid": {
                            "type": "string"
                          },
                          "emoji_collection_uid": {
                            "type": "string"
                          },
                          "message_collection_uid": {
                            "type": "string"
                          },
                          "avatar_collection_uid": {
                            "type": "string"
                          },
                          "player_group_uid": {
                            "type": "string",
                            "nullable": true
                          },
                          "valid_from": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "valid_to": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "options": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "game_sessions",
                  "attributes": {
                    "game_uid": "01J8ZGAME00000000000000001",
                    "emoji_collection_uid": "01J8ZEM0J10000000000000001",
                    "message_collection_uid": "01J8ZMSG000000000000000001",
                    "avatar_collection_uid": "01J8ZAVATAR000000000000001",
                    "player_group_uid": "01J8ZGROUP0000000000000001",
                    "valid_from": "2026-07-27T10:00:00.000Z",
                    "valid_to": "2026-07-28T10:00:00.000Z",
                    "options": {
                      "registration": true,
                      "guest_view": true,
                      "login_method": "username_otp",
                      "login_channels": ["email", "phone"],
                      "theme": "neon",
                      "animation_speed": "medium",
                      "chat": true,
                      "voice": false,
                      "emojis": true,
                      "ai_review": true,
                      "auto_ai_review": false,
                      "suspicion_detection": true,
                      "suspicion_log_level": "warning"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["game_sessions"]
                        },
                        "id": {
                          "type": "string"
                        },
                        "attributes": {
                          "type": "object"
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "game_sessions",
                    "id": "01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                    "attributes": {
                      "client": {
                        "uid": "01J8ZCLIENT000000000000001",
                        "name": "Poker Cash"
                      },
                      "game": {
                        "uid": "01J8ZGAME00000000000000001",
                        "name": "NL Holdem Cash"
                      },
                      "account_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "play_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "player_group": {
                        "uid": "01J8ZGROUP0000000000000001",
                        "name": "Regulars"
                      },
                      "url": "https://game.example.com/play/?s=01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                      "status": "Live",
                      "valid_from": "2026-07-27T10:00:00.000Z",
                      "valid_to": "2026-07-28T10:00:00.000Z",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                    }
                  },
                  "links": {
                    "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{id}": {
      "get": {
        "tags": ["Game Sessions"],
        "summary": "Get Game Session",
        "description": "Fetch one run, including its play URL and assigned Player Group. Scope: `sessions:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Game Session",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["game_sessions"]
                        },
                        "id": {
                          "type": "string"
                        },
                        "attributes": {
                          "type": "object"
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "game_sessions",
                    "id": "01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                    "attributes": {
                      "client": {
                        "uid": "01J8ZCLIENT000000000000001",
                        "name": "Poker Cash"
                      },
                      "game": {
                        "uid": "01J8ZGAME00000000000000001",
                        "name": "NL Holdem Cash"
                      },
                      "account_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "play_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "player_group": {
                        "uid": "01J8ZGROUP0000000000000001",
                        "name": "Regulars"
                      },
                      "url": "https://game.example.com/play/?s=01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                      "status": "Live",
                      "valid_from": "2026-07-27T10:00:00.000Z",
                      "valid_to": "2026-07-28T10:00:00.000Z",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                    }
                  },
                  "links": {
                    "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Game Sessions"],
        "summary": "Update Game Session",
        "description": "Update run settings after checking with the live game server. Scope: `sessions:write`.\n\n- **503** — game server status could not be reached; nothing was saved.\n- **409** — the run refuses changes (for example a tournament already in progress).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["game_sessions"]
                      },
                      "id": {
                        "type": "string"
                      },
                      "attributes": {
                        "type": "object",
                        "properties": {
                          "game_uid": {
                            "type": "string"
                          },
                          "emoji_collection_uid": {
                            "type": "string"
                          },
                          "message_collection_uid": {
                            "type": "string"
                          },
                          "avatar_collection_uid": {
                            "type": "string"
                          },
                          "player_group_uid": {
                            "type": "string",
                            "nullable": true
                          },
                          "valid_from": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "valid_to": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "options": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "game_sessions",
                  "id": "01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                  "attributes": {
                    "valid_to": "2026-07-29T10:00:00.000Z",
                    "options": {
                      "registration": true,
                      "guest_view": true,
                      "login_method": "username_otp",
                      "login_channels": ["email", "phone"],
                      "theme": "neon",
                      "animation_speed": "medium",
                      "chat": false,
                      "voice": false,
                      "emojis": true,
                      "ai_review": true,
                      "auto_ai_review": false,
                      "suspicion_detection": true,
                      "suspicion_log_level": "warning"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["game_sessions"]
                        },
                        "id": {
                          "type": "string"
                        },
                        "attributes": {
                          "type": "object"
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "game_sessions",
                    "id": "01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                    "attributes": {
                      "client": {
                        "uid": "01J8ZCLIENT000000000000001",
                        "name": "Poker Cash"
                      },
                      "game": {
                        "uid": "01J8ZGAME00000000000000001",
                        "name": "NL Holdem Cash"
                      },
                      "account_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "play_unit": {
                        "uid": "CHIP",
                        "name": "Chips",
                        "symbol": "CHIP",
                        "icon": "chip"
                      },
                      "player_group": {
                        "uid": "01J8ZGROUP0000000000000001",
                        "name": "Regulars"
                      },
                      "url": "https://game.example.com/play/?s=01J8ZQ4V2C7H5D9F1G3J6K8M0N",
                      "status": "Live",
                      "valid_from": "2026-07-27T10:00:00.000Z",
                      "valid_to": "2026-07-28T10:00:00.000Z",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                    }
                  },
                  "links": {
                    "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "409": {
            "description": "Change blocked — the live run refuses reconfiguration (for example a running tournament)."
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Game server status unavailable. No changes were saved."
          }
        }
      },
      "delete": {
        "tags": ["Game Sessions"],
        "summary": "Delete Game Session",
        "description": "Remove a run you own. Scope: `sessions:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "links": {
                    "self": "/v1/sessions/01J8ZQ4V2C7H5D9F1G3J6K8M0N"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups": {
      "get": {
        "tags": ["Player Groups"],
        "summary": "List Player Groups",
        "description": "Browse groups you own. Scope: `player-groups:read`.",
        "parameters": [
          {
            "name": "page[cursor]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Continue from `meta.nextCursor`."
          },
          {
            "name": "page[limit]",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25
            },
            "description": "Results per page. Default 25."
          },
          {
            "name": "filter[q][contains]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Search group name.",
            "example": "Regulars"
          }
        ],
        "responses": {
          "200": {
            "description": "Player Group Collection",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": ["player_groups"]
                          },
                          "id": {
                            "type": "string",
                            "description": "Player Group UID"
                          },
                          "attributes": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "description": {
                                "type": "string",
                                "nullable": true
                              },
                              "created_at": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "updated_at": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          },
                          "links": {
                            "type": "object",
                            "properties": {
                              "self": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "type": "player_groups",
                      "id": "01J8ZGROUP0000000000000001",
                      "attributes": {
                        "name": "Regulars",
                        "description": "Weekly cash players",
                        "created_at": "2026-07-27T09:00:00.000Z",
                        "updated_at": "2026-07-27T09:00:00.000Z"
                      },
                      "links": {
                        "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                      }
                    }
                  ],
                  "links": {
                    "self": "https://api.example.com/v1/player-groups?page[limit]=25",
                    "next": null,
                    "prev": null
                  },
                  "meta": {
                    "total": 1,
                    "limit": 25,
                    "nextCursor": null
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "401",
                      "title": "Unauthorized",
                      "detail": "Invalid or missing API key"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Missing Scope",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "403",
                      "title": "Forbidden",
                      "detail": "API key is missing required scope"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Player Groups"],
        "summary": "Create Player Group",
        "description": "Create a named group for access control. Attach it to a Game Session with `player_group_uid`. Scope: `player-groups:write`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["player_groups"]
                      },
                      "attributes": {
                        "type": "object",
                        "required": ["name"],
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "player_groups",
                  "attributes": {
                    "name": "Regulars",
                    "description": "Weekly cash players"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["player_groups"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player Group UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string",
                              "nullable": true
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "player_groups",
                    "id": "01J8ZGROUP0000000000000001",
                    "attributes": {
                      "name": "Regulars",
                      "description": "Weekly cash players",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                    }
                  },
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation Error",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "400",
                      "title": "Bad Request",
                      "detail": "Validation failed"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups/{id}": {
      "get": {
        "tags": ["Player Groups"],
        "summary": "Get Player Group",
        "description": "Fetch one group by UID. Scope: `player-groups:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Player Group",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["player_groups"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player Group UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string",
                              "nullable": true
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "player_groups",
                    "id": "01J8ZGROUP0000000000000001",
                    "attributes": {
                      "name": "Regulars",
                      "description": "Weekly cash players",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                    }
                  },
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Player Groups"],
        "summary": "Update Player Group",
        "description": "Rename a group or update its description. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": ["player_groups"]
                      },
                      "id": {
                        "type": "string"
                      },
                      "attributes": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "player_groups",
                  "id": "01J8ZGROUP0000000000000001",
                  "attributes": {
                    "name": "Regulars",
                    "description": "Updated description"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["player_groups"]
                        },
                        "id": {
                          "type": "string",
                          "description": "Player Group UID"
                        },
                        "attributes": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string",
                              "nullable": true
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        },
                        "links": {
                          "type": "object",
                          "properties": {
                            "self": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "type": "player_groups",
                    "id": "01J8ZGROUP0000000000000001",
                    "attributes": {
                      "name": "Regulars",
                      "description": "Weekly cash players",
                      "created_at": "2026-07-27T09:00:00.000Z",
                      "updated_at": "2026-07-27T09:00:00.000Z"
                    },
                    "links": {
                      "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                    }
                  },
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Player Groups"],
        "summary": "Delete Player Group",
        "description": "Delete a group. Players themselves are not deleted. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups/{id}/players": {
      "get": {
        "tags": ["Player Groups"],
        "summary": "List Players in Group",
        "description": "List members as `players` resources. Scope: `player-groups:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player Group UID"
          },
          {
            "name": "page[cursor]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Continue from `meta.nextCursor`."
          },
          {
            "name": "page[limit]",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25
            },
            "description": "Results per page. Default 25."
          },
          {
            "name": "filter[q][contains]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Search members by nickname, username, and related fields."
          }
        ],
        "responses": {
          "200": {
            "description": "Group Members",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": ["players"]
                          },
                          "id": {
                            "type": "string",
                            "description": "Player UID"
                          },
                          "attributes": {
                            "type": "object",
                            "properties": {
                              "nickname": {
                                "type": "string",
                                "nullable": true
                              },
                              "username": {
                                "type": "string",
                                "nullable": true
                              },
                              "email": {
                                "type": "string",
                                "nullable": true
                              },
                              "phone": {
                                "type": "string",
                                "nullable": true
                              },
                              "extra": {
                                "type": "object",
                                "additionalProperties": true,
                                "nullable": true
                              },
                              "player_group_uids": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "created_at": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "updated_at": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          },
                          "links": {
                            "type": "object",
                            "properties": {
                              "self": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "type": "players",
                      "id": "01J8ZP0R7K3M9QY4T6W2X5N1AB",
                      "attributes": {
                        "nickname": "Ace",
                        "username": "ace_player",
                        "email": "ace@example.com",
                        "phone": "+15551234567",
                        "extra": null,
                        "player_group_uids": ["01J8ZGROUP0000000000000001"],
                        "created_at": "2026-07-01T12:00:00.000Z",
                        "updated_at": "2026-07-01T12:00:00.000Z"
                      },
                      "links": {
                        "self": "/v1/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                      }
                    }
                  ],
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001/players"
                  },
                  "meta": {
                    "total": 1,
                    "limit": 25,
                    "nextCursor": null
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Player Groups"],
        "summary": "Add Player to Group",
        "description": "Add one player to the group. Idempotent if already a member. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player Group UID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "attributes": {
                        "type": "object",
                        "required": ["player_uid"],
                        "properties": {
                          "player_uid": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "type": "player_group_members",
                  "attributes": {
                    "player_uid": "01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Added",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001/players"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups/{id}/players/batch": {
      "post": {
        "tags": ["Player Groups"],
        "summary": "Add Players to Group (Batch)",
        "description": "Add many players at once. Response `meta.added` is the count newly joined. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player Group UID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "attributes": {
                        "type": "object",
                        "required": ["player_uids"],
                        "properties": {
                          "player_uids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "attributes": {
                    "player_uids": ["01J8ZP0R7K3M9QY4T6W2X5N1AB"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Added",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "meta": {
                    "added": 1
                  },
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001/players/batch"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups/{id}/players/batch-remove": {
      "post": {
        "tags": ["Player Groups"],
        "summary": "Remove Players from Group (Batch)",
        "description": "Remove many players at once. Response `meta.removed` is the count removed. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player Group UID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.api+json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "properties": {
                      "attributes": {
                        "type": "object",
                        "required": ["player_uids"],
                        "properties": {
                          "player_uids": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "data": {
                  "attributes": {
                    "player_uids": ["01J8ZP0R7K3M9QY4T6W2X5N1AB"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Removed",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "meta": {
                    "removed": 1
                  },
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001/players/batch-remove"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/player-groups/{id}/players/{playerUid}": {
      "delete": {
        "tags": ["Player Groups"],
        "summary": "Remove Player from Group",
        "description": "Remove one player from the group. Scope: `player-groups:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player Group UID"
          },
          {
            "name": "playerUid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Player UID to remove."
          }
        ],
        "responses": {
          "200": {
            "description": "Removed",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "null"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "jsonapi": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": null,
                  "links": {
                    "self": "/v1/player-groups/01J8ZGROUP0000000000000001/players/01J8ZP0R7K3M9QY4T6W2X5N1AB"
                  },
                  "jsonapi": {
                    "version": "1.1"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "404",
                      "title": "Not Found",
                      "detail": "Resource not found"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (120 requests per 60s per API key, per Cloudflare location). Response includes `Retry-After` (seconds) and `X-RateLimit-Limit`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "errors": [
                    {
                      "status": "429",
                      "title": "Too many requests",
                      "detail": "Rate limit exceeded: 120 requests per 60s per API key. Retry after the window resets."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "x-scopes": [
    "players:read",
    "players:write",
    "player-groups:read",
    "player-groups:write",
    "wallets:read",
    "wallets:write",
    "sessions:read",
    "sessions:write"
  ],
  "x-ratelimit": {
    "limit": 120,
    "periodSeconds": 60,
    "key": "api_key_uid",
    "binding": "API_RATE_LIMITER",
    "notes": "Per API key and per Cloudflare location. OpenAPI document endpoint is exempt. See wrangler.toml [[ratelimits]]."
  }
}
