# Game Stats AI API ## Overview This API is used to import data from your game. It's recommended to call the API from a backend server supporting your game but you can also call it from clients of the game. In order to use the API you'll need to know your API token and your account ID. API tokens are scoped to an account and can be created on the API tokens page in your account settings at https://gamestats.ai/api_tokens. Your account ID is shown on that same API tokens page. Send the key on every request in the `Authorization` header using the `Bearer` scheme: `Authorization: Bearer `. ## MCP server We also host a Model Context Protocol (MCP) server so AI assistants can read your analytics. Point an MCP client at `/api/v1/mcp` and authenticate with the same `Authorization: Bearer ` header. It exposes read-only tools generated from this spec (listing and reading reports, listing accounts, the authenticated user, and ping). Call `tools/list` for the full, self-describing tool catalog. Base URL: `https://gamestats.ai` Replace `$GAMESTATS_API_TOKEN` in the examples with your API token and `{account_id}` with your numeric account ID. Both are on your API tokens page at https://gamestats.ai/api_tokens. ## Getting Started Verify connectivity and authentication before sending game data. It's recommended to successfully call the ping endpoint and monitor https://gamestats.ai/pings to confirm that your requests are reaching the API before moving on to the rest of the endpoints. ### GET /api/v1/accounts List your accounts ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts" ``` Responses: - `200`: accounts listed - `401`: unauthorized Example response: ```json [ { "id": 12, "name": "My Game" }, { "id": 34, "name": "My Other Game" } ] ``` ### GET /api/v1/me Show the authenticated user ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/me" ``` Responses: - `200`: authenticated user returned ### POST /api/v1/pings Pings the API ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/pings" ``` Responses: - `201`: ping received ### GET /api/v1/accounts/{account_id}/versions List the versions for a game | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/versions" ``` Responses: - `200`: versions listed - `401`: unauthorized Example response: ```json [ { "id": 21, "name": "1.4", "created_at": "2026-07-20T18:00:00.000Z" }, { "id": 12, "name": "1.3", "created_at": "2026-06-01T18:00:00.000Z" } ] ``` ## Matches Track what happens during a match between a number of players. The characters endpoint only needs to be called once for each character when a new version of your game is released. The character images endpoint is used to upload an image of a character to be displayed alongside character names in reports. This is optional and only needs to be done once per character. The matches endpoint should be called once at the end of each match. ### GET /api/v1/accounts/{account_id}/attribute_reports List attribute reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/attribute_reports" ``` Responses: - `200`: attribute reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Win Rate by Stage", "description": "Win rate broken down by match attribute." }, { "id": 15, "label": "Rounds by Stage", "description": "Number of rounds played on each stage." } ] ``` ### GET /api/v1/accounts/{account_id}/attribute_reports/{id} Show an attribute report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `event_type_id` | query | array | no | Filter to one or more event type IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/attribute_reports/{id}?page=2" ``` Responses: - `200`: attribute report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Win Rate by Stage", "description": "Win rate broken down by match attribute.", "metrics": [ { "label": "Wins", "format": "unformatted" }, { "label": "Win Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Volcanic Rim", "values": [ { "metric": "Wins", "value": 512 }, { "metric": "Win Rate", "value": 0.54 } ] }, { "subject": "Suzaku Castle", "values": [ { "metric": "Wins", "value": 431 }, { "metric": "Win Rate", "value": 0.48 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ### GET /api/v1/accounts/{account_id}/character_attribute_reports List character attribute reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/character_attribute_reports" ``` Responses: - `200`: character attribute reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Win Rate by Element and Rarity", "description": "Win rate grouped by character attributes." }, { "id": 19, "label": "Pick Rate by Element", "description": "Pick rate grouped by character element." } ] ``` ### GET /api/v1/accounts/{account_id}/character_attribute_reports/{id} Show a character attribute report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `event_type_id` | query | array | no | Filter to one or more event type IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/character_attribute_reports/{id}?page=2" ``` Responses: - `200`: character attribute report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Win Rate by Element and Rarity", "description": "Win rate grouped by character attributes.", "metrics": [ { "label": "Win Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Fire / Legendary", "attributes": [ { "name": "element", "value": "Fire" }, { "name": "rarity", "value": "Legendary" } ], "values": [ { "metric": "Win Rate", "value": 0.63 } ] }, { "subject": "Water / Rare", "attributes": [ { "name": "element", "value": "Water" }, { "name": "rarity", "value": "Rare" } ], "values": [ { "metric": "Win Rate", "value": 0.49 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ### POST /api/v1/accounts/{account_id}/character_images Create a Character Image | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `character_external_id` | formData | string | yes | The external ID you used in the Characters API | | `image` | formData | file | yes | The image of the character | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -F "character_external_id=string" \ -F "image=@/path/to/image.png" \ "https://gamestats.ai/api/v1/accounts/{account_id}/character_images" ``` Responses: - `201`: character image created ### GET /api/v1/accounts/{account_id}/character_reports List character reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/character_reports" ``` Responses: - `200`: character reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Damage by Character", "description": "Average damage dealt by each character." }, { "id": 18, "label": "Win Rate by Character", "description": "Win rate for each character." } ] ``` ### GET /api/v1/accounts/{account_id}/character_reports/{id} Show a character report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `event_type_id` | query | array | no | Filter to one or more event type IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/character_reports/{id}?page=2" ``` Responses: - `200`: character report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Damage by Character", "description": "Average damage dealt by each character.", "metrics": [ { "label": "Avg Damage", "format": "unformatted" }, { "label": "Win Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Ryu", "values": [ { "metric": "Avg Damage", "value": 1423.5 }, { "metric": "Win Rate", "value": 0.61 } ] }, { "subject": "Ken", "values": [ { "metric": "Avg Damage", "value": 1387.2 }, { "metric": "Win Rate", "value": 0.57 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ### POST /api/v1/accounts/{account_id}/characters Create a Character for a Version | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `external_id` | string | yes | The external ID uniquely identifies a character. The same ID should be used across versions. If multiple requests are sent for the same external ID and version name, the existing records will be updated. | | `name` | string | yes | The name of the character. This does not currently vary from version to version. | | `description` | string | no | This is a description of the character. It can be either plain text or Markdown. See https://www.markdownguide.org/cheat-sheet/ for an understanding of Markdown. | | `version_name` | string | no | The attributes in this request correspond to this version name. Character attributes can vary from version to version. | | `character_attributes` | object | no | Key-value pairs. These are displayed in reports and can be configured as filters. | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "external_id": "your_character_id", "name": "A character", "description": "This is a **bolded** description. This is an *italicized* description.", "version_name": "1.0", "character_attributes": { "Type": "Fire", "Rarity": "Common" } }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/characters" ``` Responses: - `201`: character for version queued for creation - `422`: invalid request ### POST /api/v1/accounts/{account_id}/matches Creates a Match | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `external_id` | string | no | The external ID uniquely identifies a match. If multiple requests are sent for the same external ID, the existing records will be updated. | | `version_name` | string | yes | The match in this request corresponds to this version name. | | `match_at` | string | no | The match in this request corresponds to this version name. | | `match_attributes` | object | no | | | `match_players` | object[] | no | | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "external_id": "your_match_id", "version_name": "1.0", "match_at": "2022-08-09T23:26:01UTC", "match_attributes": { "stage": "A stage" }, "match_players": [ { "username": "a_player_123", "match_attributes": { "elo": 1600 }, "match_events": [ { "character_external_id": "your_character_id", "event_type_name": "chosen_fighter", "match_attributes": { "level": 42 } } ] } ] }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/matches" ``` Responses: - `201`: match queued for creation - `422`: invalid request ### GET /api/v1/accounts/{account_id}/player_reports List player reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/player_reports" ``` Responses: - `200`: player reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Matches Played by Player", "description": "Matches played by each player." }, { "id": 21, "label": "Win Rate by Player", "description": "Win rate for each player." } ] ``` ### GET /api/v1/accounts/{account_id}/player_reports/{id} Show a player report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `event_type_id` | query | array | no | Filter to one or more event type IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/player_reports/{id}?page=2" ``` Responses: - `200`: player report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Matches Played by Player", "description": "Matches played by each player.", "metrics": [ { "label": "Matches", "format": "unformatted" }, { "label": "Win Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "shoto_main", "values": [ { "metric": "Matches", "value": 214 }, { "metric": "Win Rate", "value": 0.58 } ] }, { "subject": "grappler99", "values": [ { "metric": "Matches", "value": 188 }, { "metric": "Win Rate", "value": 0.44 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ## Progressions Track level progress, player level, season progression and more over time. The progression events endpoint should be called at the completion of a milestone (i.e. starting a level, finishing a level, collecting 100 coins, etc.). ### POST /api/v1/accounts/{account_id}/progression_events Creates a Progression Event | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `version_name` | string | yes | The progression event in this request corresponds to this version name. | | `player_username` | string | yes | The username for the player. | | `progression_name` | string | yes | | | `progression_type_name` | string | yes | | | `progression_milestone_name` | string | yes | If not provided, the milestone name will be the same as the milestone type name. | | `progression_milestone_type_name` | string | yes | | | `is_new_instance` | boolean | no | If provided, the progression event in this request is considered the start of a new instances occurring at this time. There's no need to provide started_at if this is set. | | `started_at` | string | no | If provided, the progression event in this request is considered the start of a new instances occurring at this time. | | `time_elapsed` | integer | no | This is the amount of "time" that has passed since the start of the instance. If this is the first event in the instance, it will likely be 0. Any unit of measurement can be used (ticks, seconds, minutes, etc) but you must be consistent across events. | | `occurred_at` | string | yes | This represents the time the event occurs. | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "version_name": "1.0", "player_username": "a_player_123", "progression_name": "string", "progression_type_name": "string", "progression_milestone_name": "string", "progression_milestone_type_name": "string", "is_new_instance": true, "started_at": "2022-08-09T23:26:01UTC", "time_elapsed": 0, "occurred_at": "2022-08-09T23:26:01UTC" }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/progression_events" ``` Responses: - `201`: progression event queued for creation - `422`: invalid request ### GET /api/v1/accounts/{account_id}/progression_reports List progression reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/progression_reports" ``` Responses: - `200`: progression reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Level Progression", "description": "Completion rates and timing across levels." }, { "id": 25, "label": "Season Progression", "description": "Progress through the current season." } ] ``` ### GET /api/v1/accounts/{account_id}/progression_reports/{id} Show a progression report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/progression_reports/{id}?page=2" ``` Responses: - `200`: progression report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Level Progression", "description": "Completion rates and timing across levels.", "metrics": [ { "label": "Average Time Elapsed", "format": "unformatted" }, { "label": "# of Instances", "format": "unformatted" }, { "label": "Completion Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Level 1", "values": [ { "metric": "Average Time Elapsed", "value": 142.5 }, { "metric": "# of Instances", "value": 5000 }, { "metric": "Completion Rate", "value": 0.92 } ] }, { "subject": "Level 2", "values": [ { "metric": "Average Time Elapsed", "value": 210.3 }, { "metric": "# of Instances", "value": 4200 }, { "metric": "Completion Rate", "value": 0.78 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ## Achievements Define achievements and track unlock rates across players. The achievement events endpoint should be called when a player unlocks an achievement. Achievements are created automatically the first time they are sent, and sending the same achievement for the same player again has no effect. You can also add an achievement directly (before any player unlocks it) so it counts toward your completion rates. ### POST /api/v1/accounts/{account_id}/achievement_events Creates an Achievement Event | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `version_name` | string | yes | The achievement unlock in this request corresponds to this version name. | | `player_username` | string | yes | The username for the player. | | `achievement_name` | string | yes | The name of the achievement the player unlocked. Achievements are created automatically the first time they are sent. | | `occurred_at` | string | yes | This represents the time the player unlocked the achievement. Sending the same achievement for the same player again has no effect. | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "version_name": "1.0", "player_username": "a_player_123", "achievement_name": "First Blood", "occurred_at": "2022-08-09T23:26:01UTC" }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/achievement_events" ``` Responses: - `201`: achievement event queued for creation - `422`: invalid request ### POST /api/v1/accounts/{account_id}/achievement_images Create an Achievement Image | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `achievement_name` | formData | string | yes | The name of the achievement to attach the image to | | `image` | formData | file | yes | The image of the achievement | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -F "achievement_name=string" \ -F "image=@/path/to/image.png" \ "https://gamestats.ai/api/v1/accounts/{account_id}/achievement_images" ``` Responses: - `201`: achievement image created ### GET /api/v1/accounts/{account_id}/achievement_reports List achievement reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/achievement_reports" ``` Responses: - `200`: achievement reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Achievements", "description": "Unlock counts and rates for every achievement." }, { "id": 24, "label": "Rare Achievements", "description": "Achievements unlocked by the fewest players." } ] ``` ### GET /api/v1/accounts/{account_id}/achievement_reports/{id} Show an achievement report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/achievement_reports/{id}?page=2" ``` Responses: - `200`: achievement report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Achievements", "description": "Unlock counts and rates for every achievement.", "metrics": [ { "label": "# of Players Unlocked", "format": "unformatted" }, { "label": "% of Players", "format": "percentage" } ], "filters": [], "rows": [ { "subject": "First Blood", "values": [ { "metric": "# of Players Unlocked", "value": 1240 }, { "metric": "% of Players", "value": 0.82 } ] }, { "subject": "Flawless Victory", "values": [ { "metric": "# of Players Unlocked", "value": 356 }, { "metric": "% of Players", "value": 0.24 } ] }, { "subject": "All 2 achievements", "values": [ { "metric": "# of Players Unlocked", "value": 312 }, { "metric": "% of Players", "value": 0.21 } ] } ] } ``` ### POST /api/v1/accounts/{account_id}/achievements Creates an Achievement | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | yes | The name of the achievement. Adding an achievement that no player has unlocked yet lets it count toward your completion rates. Sending the same name again returns the existing achievement. | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "First Blood" }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/achievements" ``` Responses: - `201`: achievement created - `422`: invalid request ### GET /api/v1/accounts/{account_id}/players/achievements List a player's unlocked achievements | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `username` | query | string | yes | The player's username. | | `page` | query | integer | no | Page of unlocks to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total `count`, and total number of `pages`. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/players/achievements?username=hero&page=2" ``` Responses: - `200`: player's unlocked achievements returned - `404`: player not found - `401`: unauthorized Example response: ```json { "achievement_unlocks": [ { "achievement": "First Blood", "occurred_at": "2026-01-15T10:22:00Z" }, { "achievement": "First Blood", "occurred_at": "2026-01-02T09:00:00Z" } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ## Archetypes Group characters into play-style archetypes for reports. ### GET /api/v1/accounts/{account_id}/archetype_reports List archetype reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/archetype_reports" ``` Responses: - `200`: archetype reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Win Rate by Archetype", "description": "Win rate for each play-style archetype." }, { "id": 23, "label": "Pick Rate by Archetype", "description": "How often each archetype is played." } ] ``` ### GET /api/v1/accounts/{account_id}/archetype_reports/{id} Show an archetype report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `event_type_id` | query | array | no | Filter to one or more event type IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/archetype_reports/{id}?page=2" ``` Responses: - `200`: archetype report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Win Rate by Archetype", "description": "Win rate for each play-style archetype.", "metrics": [ { "label": "Win Rate", "format": "percentage" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Ryu, Ken, Akuma", "values": [ { "metric": "Win Rate", "value": 0.56 } ] }, { "subject": "Zangief, Birdie", "values": [ { "metric": "Win Rate", "value": 0.47 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ## Events Track any in-game event and report on the properties you send with it. The events endpoint should be called whenever an in-game event you want to track occurs. Event names, versions, and players are created automatically the first time they are sent. The event attributes bag is a free-form set of string, number, or boolean values that you can report on later. ### GET /api/v1/accounts/{account_id}/event_reports List event reports | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/event_reports" ``` Responses: - `200`: event reports listed - `401`: unauthorized Example response: ```json [ { "id": 12, "label": "Damage by Form", "description": "Total damage broken down by combat form." }, { "id": 15, "label": "Ability Uses by Zone", "description": "How often abilities are used in each zone." } ] ``` ### GET /api/v1/accounts/{account_id}/event_reports/{id} Show an event report | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | | `id` | path | integer | yes | The report ID. | | `page` | query | integer | no | Page of report rows to return (1-based, defaults to 1). The response `pagination` object reports the current `page`, total row `count`, and total number of `pages`; request pages 1..`pages` to read the full report. | | `version_id` | query | array | no | Filter to one or more game version IDs. Discover valid IDs from the `filters` in the response. | | `occurred_after` | query | array | no | Only include data from the last N days. Allowed values: 1, 7, 30. | | `threshold` | query | array | no | Minimum and maximum bounds for the report threshold filter, as [min, max]. | ```bash curl \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ "https://gamestats.ai/api/v1/accounts/{account_id}/event_reports/{id}?page=2" ``` Responses: - `200`: event report returned - `404`: report not found - `401`: unauthorized Example response: ```json { "id": 12, "label": "Damage by Form", "description": "Total damage broken down by combat form.", "metrics": [ { "label": "Uses", "format": "unformatted" }, { "label": "Total Damage", "format": "unformatted" } ], "filters": [ { "name": "version_id", "type": "category", "label": "Version", "values": [ { "value": "1", "label": "1.0" } ] }, { "name": "occurred_after", "type": "category", "label": "From", "values": [ { "value": "7", "label": "Last 7 days" } ] } ], "rows": [ { "subject": "Cow", "values": [ { "metric": "Uses", "value": 512 }, { "metric": "Total Damage", "value": 8123 } ] }, { "subject": "Deer", "values": [ { "metric": "Uses", "value": 431 }, { "metric": "Total Damage", "value": 5210 } ] } ], "pagination": { "page": 1, "count": 2, "pages": 1 } } ``` ### POST /api/v1/accounts/{account_id}/events Creates an Event | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `event_name` | string | yes | The name of the event, e.g. "form_session" or "ability_used". | | `version_name` | string | yes | The event in this request corresponds to this version name. | | `player_username` | string | no | The username for the player. Optional: omit for playerless telemetry. | | `occurred_at` | string | yes | This represents the time the event occurs. | | `event_attributes` | object | no | A free-form bag of string, number, or boolean values describing the event. Numeric strings are coerced to numbers. | ```bash curl \ -X POST \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_name": "ability_used", "version_name": "1.0", "player_username": "a_player_123", "occurred_at": "2022-08-09T23:26:01UTC", "event_attributes": { "form": "Cow", "ability": "Stampede", "times_used": 3, "damage_ratio": 1.8, "ranked": true } }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/events" ``` Responses: - `201`: event queued for creation - `422`: invalid request ## Players Manage players. Applies across all game modules. ### PATCH /api/v1/accounts/{account_id}/players/rename Rename a Player | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `account_id` | path | integer | yes | Your account ID. | Request body (JSON): | Field | Type | Required | Description | | --- | --- | --- | --- | | `username` | string | yes | The player's current username. | | `new_username` | string | yes | The player's new username. Must be unique within the account. | ```bash curl \ -X PATCH \ -H "Accept: application/json" \ -H "Authorization: Bearer $GAMESTATS_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "username": "old_username", "new_username": "new_username" }' \ "https://gamestats.ai/api/v1/accounts/{account_id}/players/rename" ``` Responses: - `200`: player renamed - `404`: player not found - `422`: new username is blank - `401`: unauthorized