{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/unicum-gg/json-schema/unicum-gg-battle-detail-response-schema.json",
  "title": "BattleDetailResponse",
  "description": "A whole battle, as the clients that played it reported it.",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/unicum-gg-openapi.json#/components/schemas/BattleDetailResponse",
  "type": "object",
  "properties": {
    "mapImage": {
      "type": [
        "string",
        "null"
      ],
      "description": "The minimap this battle was played on, resolved for its own mode: a mode that redraws the map into a smaller play area ships its own picture, and this is that one."
    },
    "mapBounds": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "bottomLeft": {
          "type": "object",
          "properties": {
            "x": {
              "type": "number"
            },
            "z": {
              "type": "number"
            }
          },
          "required": [
            "x",
            "z"
          ]
        },
        "upperRight": {
          "type": "object",
          "properties": {
            "x": {
              "type": "number"
            },
            "z": {
              "type": "number"
            }
          },
          "required": [
            "x",
            "z"
          ]
        }
      },
      "required": [
        "bottomLeft",
        "upperRight"
      ],
      "description": "The arena's extent in metres, which places a replay's coordinates on that image."
    },
    "mapOverlay": {
      "anyOf": [
        {
          "$ref": "#/$defs/mapOverlay"
        },
        {
          "type": "null"
        }
      ],
      "description": "What this battle's mode puts on the minimap, already projected into `mapBounds`. Null when the arena declares nothing for it."
    },
    "id": {
      "type": "string"
    },
    "startedAt": {
      "type": "string",
      "format": "date-time"
    },
    "map": {
      "type": "string"
    },
    "gameplay": {
      "type": [
        "string",
        "null"
      ]
    },
    "battleType": {
      "type": "number"
    },
    "duration": {
      "type": [
        "number",
        "null"
      ]
    },
    "winnerTeam": {
      "type": [
        "number",
        "null"
      ]
    },
    "finishReason": {
      "type": [
        "number",
        "null"
      ]
    },
    "clientVersion": {
      "type": [
        "string",
        "null"
      ]
    },
    "server": {
      "type": [
        "string",
        "null"
      ],
      "description": "The cluster it ran on, when the results carried one."
    },
    "reporters": {
      "type": "number",
      "description": "How many clients reported this battle."
    },
    "hasReplay": {
      "type": "boolean",
      "description": "Whether the archive holds this battle's replay file, and so whether the 2D viewer has anything to draw. False for most battles: a replay only exists when a player who was there had recording on."
    },
    "mark": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "percent": {
          "type": "number"
        },
        "previous": {
          "type": [
            "number",
            "null"
          ]
        },
        "account": {
          "type": "number"
        }
      },
      "required": [
        "percent",
        "previous",
        "account"
      ],
      "description": "Where one player's mark of excellence stood when this battle ended, and where it stood at the end of their previous battle in the same tank, with `account` naming whose gun it is. The figure comes from that client's own results and belongs to them alone, so a reader showing another participant must not show it. The game gives no 'before' of its own, so the movement is only knowable by looking at the battle before. Null when the reporting client is too old to send it, when the mode does not count towards marks, or when no earlier battle in that tank is held."
    },
    "participants": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/BattleParticipant"
      },
      "description": "Every vehicle, both teams, by team then by damage."
    }
  },
  "required": [
    "mapImage",
    "mapBounds",
    "mapOverlay",
    "id",
    "startedAt",
    "map",
    "gameplay",
    "battleType",
    "duration",
    "winnerTeam",
    "finishReason",
    "clientVersion",
    "server",
    "reporters",
    "hasReplay",
    "mark",
    "participants"
  ],
  "$defs": {
    "BattleLineupTank": {
      "type": "object",
      "properties": {
        "tank": {
          "anyOf": [
            {
              "$ref": "#/$defs/BattleTank"
            },
            {
              "type": "null"
            }
          ],
          "description": "The tank, named. Null for one the catalogue does not carry, or one the client did not report."
        },
        "tankId": {
          "type": [
            "number",
            "null"
          ],
          "description": "`typeCompDescr`, kept when the catalogue cannot name it."
        },
        "damage": {
          "type": "number"
        },
        "radio": {
          "type": "number"
        },
        "track": {
          "type": "number"
        },
        "stun": {
          "type": "number"
        },
        "blocked": {
          "type": "number"
        },
        "spotted": {
          "type": "number"
        },
        "kills": {
          "type": "number"
        },
        "xp": {
          "type": "number"
        },
        "lifeTime": {
          "type": "number",
          "description": "Seconds this tank was on the field."
        },
        "deathReason": {
          "type": "number",
          "description": "`-1` when it survived, otherwise the game's own reason code."
        }
      },
      "required": [
        "tank",
        "tankId",
        "damage",
        "radio",
        "track",
        "stun",
        "blocked",
        "spotted",
        "kills",
        "xp",
        "lifeTime",
        "deathReason"
      ],
      "description": "One tank of a vehicle that fought in several. Frontline lets a player respawn in another tank, and the results carry one record per tank."
    },
    "BattleLoadoutCrew": {
      "type": "object",
      "properties": {
        "role": {
          "type": "string",
          "description": "The seat, in the reader's language: commander, gunner, driver…"
        },
        "roleImage": {
          "type": [
            "string",
            "null"
          ],
          "description": "The seat's badge."
        },
        "skills": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "image": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "image"
            ]
          },
          "description": "The skills this seat carries, taught or granted by its role, in the order they were learned."
        }
      },
      "required": [
        "role",
        "roleImage",
        "skills"
      ]
    },
    "BattleLoadoutShell": {
      "type": "object",
      "properties": {
        "kind": {
          "type": "string",
          "description": "AP, APCR, HEAT or HE, in the reader's language."
        },
        "count": {
          "type": "number",
          "description": "How many were loaded."
        },
        "premium": {
          "type": "boolean",
          "description": "Whether the round costs gold."
        },
        "image": {
          "type": "string",
          "description": "The round's icon."
        }
      },
      "required": [
        "kind",
        "count",
        "premium",
        "image"
      ]
    },
    "BattleLoadoutSlot": {
      "type": "object",
      "properties": {
        "name": {
          "type": [
            "string",
            "null"
          ],
          "description": "The item's name in the reader's language, or null for a free slot. Position is kept, so a free slot is an entry rather than a gap: a device's grade and category depend on the slot it sits in."
        },
        "image": {
          "type": [
            "string",
            "null"
          ],
          "description": "The item's picture, or null where Wargaming publishes none. A named slot with no picture is drawn as its name, not as a hole."
        },
        "overlay": {
          "type": [
            "string",
            "null"
          ],
          "description": "The grade mark drawn in the corner, for a device that has one, or null."
        }
      },
      "required": [
        "name",
        "image",
        "overlay"
      ]
    },
    "BattleParticipant": {
      "type": "object",
      "properties": {
        "id": {
          "type": "number",
          "description": "Battle-scoped vehicle id, unique within the battle."
        },
        "account": {
          "type": "number",
          "description": "Wargaming account id, absent for a bot."
        },
        "player": {
          "anyOf": [
            {
              "$ref": "#/$defs/BattlePlayer"
            },
            {
              "type": "null"
            }
          ],
          "description": "How the site names this player: the nickname, the clan they wear and the crests they have earned. Null for a bot, or for an account nobody has ever looked up here."
        },
        "team": {
          "type": "number"
        },
        "squad": {
          "type": "number",
          "description": "Their platoon's number within their team, from 1, as the game's own results screen numbers it. Absent when they went in alone, in a mode with no platoons (a training room among them), and on battles recorded before platoons were reported."
        },
        "tank": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "id": {
              "type": "number"
            },
            "name": {
              "type": "string"
            },
            "shortName": {
              "type": "string"
            },
            "tier": {
              "type": "number"
            },
            "type": {
              "type": "string"
            },
            "nation": {
              "type": "string"
            },
            "tag": {
              "type": "string"
            },
            "slug": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "id",
            "name",
            "shortName",
            "tier",
            "type",
            "nation",
            "tag",
            "slug"
          ]
        },
        "lineup": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLineupTank"
          },
          "description": "Every tank this vehicle fought in, when it was more than one (Frontline respawns). `tank` is then only the first, and `own` and `rating` cover all of them."
        },
        "own": {
          "type": "object",
          "additionalProperties": {
            "type": "number"
          },
          "propertyNames": {
            "type": "string"
          },
          "description": "Their whole line, exactly as the client's results reported it: damage, radio, track, stun, blocked, received, shots, hits, piercings, spotted, kills, lifeTime, deathReason, capturePoints, xp, credits, health, maxHealth."
        },
        "medals": {
          "type": "array",
          "items": {
            "type": "number"
          },
          "description": "The medals this battle awarded them, by the game's own ids. Absent when there are none, which is the usual case."
        },
        "rating": {
          "type": "object",
          "additionalProperties": {
            "type": [
              "number",
              "null"
            ]
          },
          "propertyNames": {
            "type": "string"
          },
          "description": "What this battle scored them, keyed by metric (`wn7`, `wn8`, `wnx`), against their own vehicle's expected values."
        },
        "loadouts": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleParticipantLoadout"
          },
          "description": "What this vehicle had fitted, one entry per life, named in the requested language and pictured. Absent for almost every participant, and that is the designed state: a loadout exists only where a recording of the battle carried it, which means the player who recorded it and any team mate they followed after dying. Nothing is ever known this way about the other team, because the server strips the devices out of every other vehicle's public information before it is broadcast."
        }
      },
      "required": [
        "id",
        "player",
        "team",
        "tank",
        "own",
        "rating"
      ],
      "description": "One vehicle in a battle, named and rated."
    },
    "BattleParticipantLoadout": {
      "type": "object",
      "properties": {
        "life": {
          "type": "number",
          "description": "Counted from zero, in the order the lives were played. Always zero outside a mode with respawns."
        },
        "optDevices": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutSlot"
          }
        },
        "boosters": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutSlot"
          }
        },
        "consumables": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutSlot"
          }
        },
        "shells": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutShell"
          }
        },
        "fieldMods": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutSlot"
          },
          "description": "The field modifications this vehicle carried, in the tree's own order. Present far more often than the rest: a recording carries these for everyone who has any."
        },
        "crew": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BattleLoadoutCrew"
          }
        }
      },
      "required": [
        "life",
        "optDevices",
        "boosters",
        "consumables",
        "shells",
        "fieldMods",
        "crew"
      ],
      "description": "One vehicle's loadout for one life, named and pictured."
    },
    "BattlePlayer": {
      "type": "object",
      "properties": {
        "accountId": {
          "type": "number"
        },
        "nickname": {
          "type": "string"
        },
        "clanTag": {
          "type": [
            "string",
            "null"
          ]
        },
        "clanColor": {
          "type": [
            "string",
            "null"
          ]
        },
        "isVerified": {
          "type": "boolean",
          "description": "The owner signed in here with this Wargaming account."
        },
        "isSupporter": {
          "type": "boolean",
          "description": "An active, non-anonymous support subscription."
        },
        "twitchLogin": {
          "type": [
            "string",
            "null"
          ],
          "description": "Their Twitch channel, when the account has linked one."
        },
        "tournamentWins": {
          "type": "number"
        },
        "tournamentFeaturedWins": {
          "type": "number"
        },
        "tournamentBestTitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "onslaughtBestTier": {
          "type": [
            "string",
            "null"
          ]
        },
        "onslaughtBestRank": {
          "type": [
            "number",
            "null"
          ]
        },
        "onslaughtSeasons": {
          "type": "number"
        }
      },
      "required": [
        "accountId",
        "nickname",
        "clanTag",
        "clanColor",
        "isVerified",
        "isSupporter",
        "twitchLogin",
        "tournamentWins",
        "tournamentFeaturedWins",
        "tournamentBestTitle",
        "onslaughtBestTier",
        "onslaughtBestRank",
        "onslaughtSeasons"
      ],
      "description": "A participant's public identity."
    },
    "BattleTank": {
      "type": "object",
      "properties": {
        "id": {
          "type": "number",
          "description": "`typeCompDescr`, which is the catalogue's own tank id."
        },
        "name": {
          "type": "string"
        },
        "shortName": {
          "type": "string"
        },
        "tier": {
          "type": "number"
        },
        "type": {
          "type": "string",
          "description": "`mediumTank`, `heavyTank`, …"
        },
        "nation": {
          "type": "string"
        },
        "tag": {
          "type": "string",
          "description": "The client's own tag, which the icon is addressed by."
        },
        "slug": {
          "type": [
            "string",
            "null"
          ],
          "description": "Our slug for the vehicle page, null when it has none."
        }
      },
      "required": [
        "id",
        "name",
        "shortName",
        "tier",
        "type",
        "nation",
        "tag",
        "slug"
      ],
      "description": "A vehicle as a battle row names it."
    },
    "mapOverlay": {
      "type": "object",
      "properties": {
        "bounds": {
          "type": "object",
          "properties": {
            "bottomLeft": {
              "type": "object",
              "properties": {
                "x": {
                  "type": "number"
                },
                "z": {
                  "type": "number"
                }
              },
              "required": [
                "x",
                "z"
              ]
            },
            "upperRight": {
              "type": "object",
              "properties": {
                "x": {
                  "type": "number"
                },
                "z": {
                  "type": "number"
                }
              },
              "required": [
                "x",
                "z"
              ]
            }
          },
          "required": [
            "bottomLeft",
            "upperRight"
          ]
        },
        "widthMeters": {
          "type": "number"
        },
        "heightMeters": {
          "type": "number"
        },
        "bases": {
          "type": "object",
          "properties": {
            "team1": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/marker"
              }
            },
            "team2": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/marker"
              }
            }
          },
          "required": [
            "team1",
            "team2"
          ]
        },
        "spawns": {
          "type": "object",
          "properties": {
            "team1": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/marker"
              }
            },
            "team2": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/marker"
              }
            }
          },
          "required": [
            "team1",
            "team2"
          ]
        },
        "controlPoint": {
          "anyOf": [
            {
              "$ref": "#/$defs/marker"
            },
            {
              "type": "null"
            }
          ]
        },
        "pois": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "marker": {
                "$ref": "#/$defs/marker"
              },
              "type": {
                "type": "number"
              }
            },
            "required": [
              "marker",
              "type"
            ]
          }
        }
      },
      "required": [
        "bounds",
        "widthMeters",
        "heightMeters",
        "bases",
        "spawns",
        "controlPoint",
        "pois"
      ]
    },
    "marker": {
      "type": "object",
      "properties": {
        "left": {
          "type": "number"
        },
        "top": {
          "type": "number"
        }
      },
      "required": [
        "left",
        "top"
      ]
    }
  }
}