{
  "openapi": "3.1.0",
  "info": {
    "title": "Citadel game data API",
    "version": "1.0.0",
    "summary": "Public, versioned game data and ship-fit tools for the live build of Citadel.",
    "description": "Game data and fit tools for [Citadel](https://thecitadel.com), always from the live build. The fit tools run the game's own code, so they apply the same rules the game does. The kill routes serve the killboard: every player ship lost, 5 minutes after it happens.\n\n### Rules\n\n- Send a `User-Agent` with your app's name and a way to reach you. Requests with none, or a generic one such as curl or python-requests, still work, but the response carries a `Warning` header.\n- Each client can make 60 requests in a burst, and the allowance refills at 10 a second. Art and `sde.zip` have allowances of their own, and so do the kill routes: 20 in a burst, refilling at 2 a second. Past the limit you get a 429 with `Retry-After`.\n- Send the last response's ETag in `If-None-Match` and you get a 304 until the data changes. `X-Citadel-Build` (or `/v1/status`) tells you when the build changes. If you want everything, download `/v1/sde.zip` once instead of crawling every route.\n\n### Conventions\n\n- An id is the game's asset GUID as a decimal string, and it doesn't change between builds. Boss NPCs that are elite archetypes have ids like `boss:JUGGERNAUT`.\n- Fixed-point values are raw decimal strings: divide by 65536.\n- Enum values are the game's own names. New content brings new values, so don't treat any enum as complete.\n- Errors look like `{ \"error\": { \"code\", \"message\" } }` and use status 400, 404, 405, 413, 415, 429, 500 or 503.\n- Every response carries `X-Citadel-Build`, `Access-Control-Allow-Origin: *` and an `ETag`.\n\n### Kills\n\n- A kill becomes public 5 minutes after the ship dies, so nothing here shows a fight still going on. The feed and the stream list kills in the order they became public.\n- Kill and battle ids look like `48213:7`: the recording, then the death's place in it. Pilot ids are the game's user ids.\n- Hull, item, cipher and artifact ids are the ids the rest of this API uses. Kills recorded before the killboard kept ids have null there; filter those by `hullName`.\n- Each kill names the `build` that recorded it. `X-Citadel-Build` is still the live build.\n- A kill can be withdrawn, for example when it repeats another loss of the same ship, or a pilot asks to be anonymised. After that it answers 404. The feed and the stream don't announce it.\n\n### Stability\n\nNew routes and fields can appear at any time, without notice, so ignore fields you don't recognise. Removing or renaming a field, or changing what it means or its type, only happens in `/v2`. When `/v2` ships, `/v1` keeps running for at least 90 days and its responses carry a `Deprecation` header. Game data isn't part of that promise: items come and go with builds.\n\nThe data and art belong to the game; see the [terms](/docs/TERMS.md).",
    "termsOfService": "https://api.thecitadel.com/docs/TERMS.md"
  },
  "servers": [
    {
      "url": "https://api.thecitadel.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Status",
      "description": "Which build is live."
    },
    {
      "name": "Static data",
      "description": "The live build's content, as full lists or one record at a time."
    },
    {
      "name": "Art",
      "description": "Icons as WebP."
    },
    {
      "name": "UI style",
      "description": "How the game's interface draws things, for clients that want to look like it. This is not game data, so `sde.zip` leaves it out."
    },
    {
      "name": "Bulk",
      "description": "All the data in one download, and this OpenAPI document."
    },
    {
      "name": "Tools",
      "description": "Check a fit, convert it to and from the in-game fit string, read an item's tooltip rows, see what grid consumables can do to a fit, or roll an item's modifiers."
    },
    {
      "name": "Kills",
      "description": "The killboard: every player ship lost, public 5 minutes after it happens. Search kills, follow them with the feed or the stream, and read battles, pilots and leaderboards."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Data",
      "tags": [
        "Status",
        "Static data",
        "Art",
        "Bulk"
      ]
    },
    {
      "name": "Tools",
      "tags": [
        "Tools"
      ]
    },
    {
      "name": "Killboard",
      "tags": [
        "Kills"
      ]
    }
  ],
  "paths": {
    "/v1/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Status"
        ],
        "summary": "The live build",
        "description": "When a new build goes live, `build` changes, so poll this to find out. Every other response carries the build in the `X-Citadel-Build` header.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getStatusHead",
        "tags": [
          "Status"
        ],
        "summary": "The live build (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/items": {
      "get": {
        "operationId": "listItems",
        "tags": [
          "Static data"
        ],
        "summary": "Fittable modules and conduits",
        "description": "Every module and conduit players can get in the live build.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listItemsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Fittable modules and conduits (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/items/{id}": {
      "get": {
        "operationId": "getItem",
        "tags": [
          "Static data"
        ],
        "summary": "One item",
        "parameters": [
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Item"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getItemHead",
        "tags": [
          "Static data"
        ],
        "summary": "One item (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Item"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/hulls": {
      "get": {
        "operationId": "listHulls",
        "tags": [
          "Static data"
        ],
        "summary": "Hulls",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HullList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listHullsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Hulls (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HullList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/hulls/{id}": {
      "get": {
        "operationId": "getHull",
        "tags": [
          "Static data"
        ],
        "summary": "One hull",
        "parameters": [
          {
            "$ref": "#/components/parameters/HullId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Hull"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getHullHead",
        "tags": [
          "Static data"
        ],
        "summary": "One hull (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/HullId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Hull"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/ciphers": {
      "get": {
        "operationId": "listCiphers",
        "tags": [
          "Static data"
        ],
        "summary": "Ciphers",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CipherList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listCiphersHead",
        "tags": [
          "Static data"
        ],
        "summary": "Ciphers (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CipherList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/artifacts": {
      "get": {
        "operationId": "listArtifacts",
        "tags": [
          "Static data"
        ],
        "summary": "Artifacts",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtifactList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listArtifactsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Artifacts (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtifactList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/regalia-sets": {
      "get": {
        "operationId": "listRegaliaSets",
        "tags": [
          "Static data"
        ],
        "summary": "Regalia sets",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegaliaSetList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listRegaliaSetsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Regalia sets (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegaliaSetList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/regalia": {
      "get": {
        "operationId": "listRegalia",
        "tags": [
          "Static data"
        ],
        "summary": "Regalia pieces",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegaliaList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listRegaliaHead",
        "tags": [
          "Static data"
        ],
        "summary": "Regalia pieces (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegaliaList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/heretical-specials": {
      "get": {
        "operationId": "listHereticalSpecials",
        "tags": [
          "Static data"
        ],
        "summary": "Heretical specials",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HereticalSpecialList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listHereticalSpecialsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Heretical specials (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HereticalSpecialList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/harmonic-sets": {
      "get": {
        "operationId": "listHarmonicSets",
        "tags": [
          "Static data"
        ],
        "summary": "Harmonic sets",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HarmonicSetList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listHarmonicSetsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Harmonic sets (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HarmonicSetList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/modifier-pools": {
      "get": {
        "operationId": "listModifierPools",
        "tags": [
          "Static data"
        ],
        "summary": "Modifier pools per module type",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModifierPoolList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listModifierPoolsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Modifier pools per module type (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModifierPoolList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/qualities": {
      "get": {
        "operationId": "listQualities",
        "tags": [
          "Static data"
        ],
        "summary": "Quality rating multipliers",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QualityList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listQualitiesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Quality rating multipliers (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QualityList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/placement-rules": {
      "get": {
        "operationId": "listPlacementRules",
        "tags": [
          "Static data"
        ],
        "summary": "Where each slot type may sit on a fitting grid",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlacementRuleList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listPlacementRulesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Where each slot type may sit on a fitting grid (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlacementRuleList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/affinity": {
      "get": {
        "operationId": "getAffinity",
        "tags": [
          "Static data"
        ],
        "summary": "The affinity tree",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffinityResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getAffinityHead",
        "tags": [
          "Static data"
        ],
        "summary": "The affinity tree (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffinityResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/npcs": {
      "get": {
        "operationId": "listNpcs",
        "tags": [
          "Static data"
        ],
        "summary": "NPC ships, bosses and their weapons",
        "description": "The NPC ships, bosses and weapons players run into. This is the only list that includes things players can't obtain. A boss with no prototype of its own has the id `boss:<archetypeId>`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NpcList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listNpcsHead",
        "tags": [
          "Static data"
        ],
        "summary": "NPC ships, bosses and their weapons (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NpcList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "operationId": "listStats",
        "tags": [
          "Static data"
        ],
        "summary": "Every stat type",
        "description": "Each stat type with the game's label for it and the rules the game uses to display its values.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listStatsHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every stat type (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/grid-consumables": {
      "get": {
        "operationId": "listGridConsumables",
        "tags": [
          "Static data"
        ],
        "summary": "Every grid consumable",
        "description": "The consumables that change a ship's fitting grid. BROKKR SLOT adds a CORE slot beside the grid, each converter turns a CORE slot into one type of hardpoint, and SKULD retypes or destroys a hardpoint or adds a CORE slot beside it. `POST /v1/grid-mods` says where each one can be used on a fit.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GridConsumableList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listGridConsumablesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every grid consumable (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GridConsumableList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/breach-tiers": {
      "get": {
        "operationId": "listBreachTiers",
        "tags": [
          "Static data"
        ],
        "summary": "Every breach tier",
        "description": "The breach tiers a modifier roll can be made at, with the game's name for each. `index` is what `POST /v1/roll` takes as `breachTier`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BreachTierList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listBreachTiersHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every breach tier (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BreachTierList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/ship-classes": {
      "get": {
        "operationId": "listShipClasses",
        "tags": [
          "Static data"
        ],
        "summary": "Every ship class",
        "description": "The game's ship classes, in its order, each with the icon the game's overlay draws for a ship of that class. `unknownArt` is the icon for a ship whose class isn't known. A hull's `shipClass` is one of these names.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipClassList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listShipClassesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every ship class (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipClassList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/ship-roles": {
      "get": {
        "operationId": "listShipRoles",
        "tags": [
          "Static data"
        ],
        "summary": "Every ship role",
        "description": "The roles a hull can have, in the game's order. A hull's `role` is one of these, or `None`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipRoleList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listShipRolesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every ship role (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipRoleList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/death-causes": {
      "get": {
        "operationId": "listDeathCauses",
        "tags": [
          "Static data"
        ],
        "summary": "Every death cause",
        "description": "How a ship can die, in the game's order. A kill's `deathCause` is one of these.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeathCauseList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listDeathCausesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every death cause (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeathCauseList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/zones": {
      "get": {
        "operationId": "listZones",
        "tags": [
          "Static data"
        ],
        "summary": "Every zone",
        "description": "Every zone a kill can name, from the game's travel topology: the public regions in its order, then the private event routes (`isTournament`). A kill's `zone.id` is one of these ids, which `zoneId` filters the kill routes by. Hubs are not zones.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ZoneList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "listZonesHead",
        "tags": [
          "Static data"
        ],
        "summary": "Every zone (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ZoneList"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/ui/fitting-grid": {
      "get": {
        "operationId": "getUiFittingGrid",
        "tags": [
          "UI style"
        ],
        "summary": "How the game draws a fitting grid",
        "description": "The cell size, slot inset, port notches, hardpoint icons and colours the game's fitting panel draws with. Every length is in pixels of a `cellSize` cell, so scale it to the cell size you draw. Use it with a hull's `grid` to draw the grid as the game does. This is the game's UI style, not game data, so `sde.zip` leaves it out.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UiFittingGridResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getUiFittingGridHead",
        "tags": [
          "UI style"
        ],
        "summary": "How the game draws a fitting grid (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UiFittingGridResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/art/{file}": {
      "get": {
        "operationId": "getArt",
        "tags": [
          "Art"
        ],
        "summary": "A WebP image",
        "description": "Art for items, hulls, ciphers, artifacts and NPCs. Take file names from the `art` object on each record. A file name is a hash of the image, so the file behind it never changes and you can cache it for a year. Art has its own, larger rate limit: 600 requests, refilling at 100 a second.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ArtFile"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The WebP image.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "description": "`public, max-age=31536000, immutable`, because the file name contains a hash of the image.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getArtHead",
        "tags": [
          "Art"
        ],
        "summary": "A WebP image (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ArtFile"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "description": "`public, max-age=31536000, immutable`, because the file name contains a hash of the image.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/sde.zip": {
      "get": {
        "operationId": "getSde",
        "tags": [
          "Bulk"
        ],
        "summary": "Every static resource and the art in one zip",
        "description": "Built once when the API starts. It holds one JSON file per static route (`status.json`, `items.json`, `hulls.json`, `ciphers.json`, `artifacts.json`, `regalia-sets.json`, `affinity.json`, `npcs.json`, `stats.json`, `regalia.json`, `heretical-specials.json`, `harmonic-sets.json`, `modifier-pools.json`, `qualities.json`, `placement-rules.json`), the art under `art/` with the art manifest, and `manifest.json`, which names the build and gives a SHA-256 for every other file. Each JSON file is byte for byte what its route serves. The zip is built deterministically, so its ETag changes only when the data does. It has its own rate limit: 5 downloads, then one more every 6 seconds.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getSdeHead",
        "tags": [
          "Bulk"
        ],
        "summary": "Every static resource and the art in one zip (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "tags": [
          "Bulk"
        ],
        "summary": "This OpenAPI document",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "An OpenAPI 3.1 document."
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      },
      "head": {
        "operationId": "getOpenApiHead",
        "tags": [
          "Bulk"
        ],
        "summary": "This OpenAPI document (headers only)",
        "description": "Same status and headers as GET, with no body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "An OpenAPI 3.1 document."
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/fits/evaluate": {
      "post": {
        "operationId": "evaluateFit",
        "tags": [
          "Tools"
        ],
        "summary": "Evaluate a fit",
        "description": "Runs the game's own simulation on the fit and returns its issues, conduit links, regalia groups, stat lines, hull spec sections and rating. Bodies can be up to 256 KB, and a request whose body fails validation still counts against the rate limit. The fit may use any item the build defines, so a pasted fit always loads; anything illegal about it shows up in `issues`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FitBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Evaluation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/fits/import": {
      "post": {
        "operationId": "importFit",
        "tags": [
          "Tools"
        ],
        "summary": "Convert a fit string to a fit",
        "description": "Decodes the game's shareable fit string into a fit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FitStringBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FitBody"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/fits/export": {
      "post": {
        "operationId": "exportFit",
        "tags": [
          "Tools"
        ],
        "summary": "Convert a fit to a fit string",
        "description": "Encodes a fit as the game's shareable fit string.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FitBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FitStringBody"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/items/facts": {
      "post": {
        "operationId": "itemFacts",
        "tags": [
          "Tools"
        ],
        "summary": "Tooltip rows for a rolled item",
        "description": "The rows the game's item tooltip shows for this roll.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ItemBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FactsBody"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/grid-mods": {
      "post": {
        "operationId": "gridMods",
        "tags": [
          "Tools"
        ],
        "summary": "What grid consumables can do to a fit",
        "description": "Lists, for each grid consumable, the cells of the fit's current grid it can be used on and every change one use can make there, by the game's own rules. Only changes an evaluation accepts are listed. A mirrored hull takes none, and `refusal` says so. Cells are numbered row by row from 0, as in `slotOverrides`. A fit the API can't read is a 400.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FitBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GridMods"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/roll": {
      "post": {
        "operationId": "rollItem",
        "tags": [
          "Tools"
        ],
        "summary": "Roll an item's modifiers",
        "description": "Rolls an Augmented or Prototype item's modifiers with the game's own roller, the way a drop rolls them. The answer is the same item with only its modifiers changed. `breachTier` defaults to the highest, and `seed` to one the API picks; the answer gives both, so the same body with them gives the same roll. With `line`, only that modifier is rolled again, against the others. An item that rolls no modifiers from a pool, or a tier or line out of range, is a 400.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RolledItem"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/Starting"
          }
        }
      }
    },
    "/v1/kills": {
      "get": {
        "operationId": "listKills",
        "tags": [
          "Kills"
        ],
        "summary": "Search kills",
        "description": "Kills that match every filter you give, newest first, or by `sort`. Responses are cached for 10 seconds. To follow new kills as they become public, use `/v1/kills/feed` or `/v1/kills/stream`: a page of this list shifts as kills arrive.",
        "parameters": [
          {
            "$ref": "#/components/parameters/KillZone"
          },
          {
            "$ref": "#/components/parameters/KillZoneId"
          },
          {
            "$ref": "#/components/parameters/KillTier"
          },
          {
            "$ref": "#/components/parameters/KillHull"
          },
          {
            "$ref": "#/components/parameters/KillHullName"
          },
          {
            "$ref": "#/components/parameters/KillClass"
          },
          {
            "$ref": "#/components/parameters/KillCause"
          },
          {
            "$ref": "#/components/parameters/KillPilot"
          },
          {
            "$ref": "#/components/parameters/KillKind"
          },
          {
            "$ref": "#/components/parameters/KillSize"
          },
          {
            "$ref": "#/components/parameters/KillBrMin"
          },
          {
            "$ref": "#/components/parameters/KillBrMax"
          },
          {
            "$ref": "#/components/parameters/KillValueMin"
          },
          {
            "$ref": "#/components/parameters/KillValueMax"
          },
          {
            "$ref": "#/components/parameters/KillFrom"
          },
          {
            "$ref": "#/components/parameters/KillTo"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`recent` (the default): newest first. `value`: most valuable first, leaving out kills of unknown value. `br`: highest build rating first.",
            "schema": {
              "type": "string",
              "enum": [
                "recent",
                "value",
                "br"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `nextCursor` of the page before, for the next page. Keep the same filters and sort.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, from 1 to 100. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KillPage"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/kills/feed": {
      "get": {
        "operationId": "getKillFeed",
        "tags": [
          "Kills"
        ],
        "summary": "Kills in the order they became public",
        "description": "Every kill made public after `after`, oldest first. Poll it with the `cursor` it returns and you see each kill once. Without `after` it starts from the first kill on the killboard, so you can also copy everything, a page at a time. A kill added later from an older recording appears here when it becomes public, with its old `occurredAt`. Responses are cached for 10 seconds, so there is no point polling faster than that.",
        "parameters": [
          {
            "$ref": "#/components/parameters/KillZone"
          },
          {
            "$ref": "#/components/parameters/KillZoneId"
          },
          {
            "$ref": "#/components/parameters/KillTier"
          },
          {
            "$ref": "#/components/parameters/KillHull"
          },
          {
            "$ref": "#/components/parameters/KillHullName"
          },
          {
            "$ref": "#/components/parameters/KillClass"
          },
          {
            "$ref": "#/components/parameters/KillCause"
          },
          {
            "$ref": "#/components/parameters/KillPilot"
          },
          {
            "$ref": "#/components/parameters/KillKind"
          },
          {
            "$ref": "#/components/parameters/KillSize"
          },
          {
            "$ref": "#/components/parameters/KillBrMin"
          },
          {
            "$ref": "#/components/parameters/KillBrMax"
          },
          {
            "$ref": "#/components/parameters/KillValueMin"
          },
          {
            "$ref": "#/components/parameters/KillValueMax"
          },
          {
            "$ref": "#/components/parameters/KillFrom"
          },
          {
            "$ref": "#/components/parameters/KillTo"
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "A kill's `cursor`, or the `cursor` of your last call.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, from 1 to 200. Default 100.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedPage"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/kills/stream": {
      "get": {
        "operationId": "streamKills",
        "tags": [
          "Kills"
        ],
        "summary": "Kills as they become public (server-sent events)",
        "description": "A [server-sent events](https://html.spec.whatwg.org/multipage/server-sent-events.html) stream. Each kill that matches your filters arrives as a `kill` event with a `KillSummary` as its data, about 3 seconds after it becomes public. The event's id is the kill's `cursor`.\n\nThe server ends each stream after 10 minutes, and a comment line arrives every 15 seconds while nothing else does. Reconnect with the last id you got in `Last-Event-ID` (a browser's `EventSource` does both for you) and the stream sends what you missed first. That works for an hour. After longer, you get one `gap` event instead, whose data names the span to fetch from `/v1/kills/feed`: everything after `after`, up to and including `until`.\n\nEach client can hold 3 streams open. A fourth gets a 429.",
        "parameters": [
          {
            "$ref": "#/components/parameters/KillZone"
          },
          {
            "$ref": "#/components/parameters/KillZoneId"
          },
          {
            "$ref": "#/components/parameters/KillTier"
          },
          {
            "$ref": "#/components/parameters/KillHull"
          },
          {
            "$ref": "#/components/parameters/KillHullName"
          },
          {
            "$ref": "#/components/parameters/KillClass"
          },
          {
            "$ref": "#/components/parameters/KillCause"
          },
          {
            "$ref": "#/components/parameters/KillPilot"
          },
          {
            "$ref": "#/components/parameters/KillKind"
          },
          {
            "$ref": "#/components/parameters/KillSize"
          },
          {
            "$ref": "#/components/parameters/KillBrMin"
          },
          {
            "$ref": "#/components/parameters/KillBrMax"
          },
          {
            "$ref": "#/components/parameters/KillValueMin"
          },
          {
            "$ref": "#/components/parameters/KillValueMax"
          },
          {
            "$ref": "#/components/parameters/KillFrom"
          },
          {
            "$ref": "#/components/parameters/KillTo"
          },
          {
            "name": "Last-Event-ID",
            "in": "header",
            "required": false,
            "description": "The id of the last event you got, to resume after it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lastEventId",
            "in": "query",
            "required": false,
            "description": "The same, for clients that can't set headers.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The stream.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Events: `kill` (data: a `KillSummary`, id: its cursor) and `gap` (data: `{ after, until, message }`)."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        },
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "curl",
            "source": "# -N prints each event as it arrives. Ctrl-C to stop.\ncurl -N -A 'MyKillBot/1.0 (me@example.com)' 'https://api.thecitadel.com/v1/kills/stream?kind=pvp'"
          },
          {
            "lang": "javascript",
            "label": "JavaScript",
            "source": "// In a web page. EventSource reconnects by itself and resumes after the last kill it saw.\nconst stream = new EventSource(\"https://api.thecitadel.com/v1/kills/stream?kind=pvp\");\nstream.addEventListener(\"kill\", (event) => console.log(JSON.parse(event.data)));\nstream.addEventListener(\"gap\", (event) => console.log(JSON.parse(event.data)));"
          }
        ]
      }
    },
    "/v1/kills/summary": {
      "get": {
        "operationId": "getKillSummary",
        "tags": [
          "Kills"
        ],
        "summary": "Totals for a filter",
        "description": "How many kills match, their ore value, how many pilots lost ships, their average build rating, and the 10 pilots on the most of them. Filter by `hull` or `zone` for a hull's or a zone's record.",
        "parameters": [
          {
            "$ref": "#/components/parameters/KillZone"
          },
          {
            "$ref": "#/components/parameters/KillZoneId"
          },
          {
            "$ref": "#/components/parameters/KillTier"
          },
          {
            "$ref": "#/components/parameters/KillHull"
          },
          {
            "$ref": "#/components/parameters/KillHullName"
          },
          {
            "$ref": "#/components/parameters/KillClass"
          },
          {
            "$ref": "#/components/parameters/KillCause"
          },
          {
            "$ref": "#/components/parameters/KillPilot"
          },
          {
            "$ref": "#/components/parameters/KillKind"
          },
          {
            "$ref": "#/components/parameters/KillSize"
          },
          {
            "$ref": "#/components/parameters/KillBrMin"
          },
          {
            "$ref": "#/components/parameters/KillBrMax"
          },
          {
            "$ref": "#/components/parameters/KillValueMin"
          },
          {
            "$ref": "#/components/parameters/KillValueMax"
          },
          {
            "$ref": "#/components/parameters/KillFrom"
          },
          {
            "$ref": "#/components/parameters/KillTo"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KillTotals"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/kills/{id}": {
      "get": {
        "operationId": "getKill",
        "tags": [
          "Kills"
        ],
        "summary": "One kill",
        "description": "The kill's summary, the ship's fitting and cargo as the game's kill card shows them, and everyone who damaged it. Cached for 5 minutes.",
        "parameters": [
          {
            "$ref": "#/components/parameters/KillId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Kill"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/battles": {
      "get": {
        "operationId": "listBattles",
        "tags": [
          "Kills"
        ],
        "summary": "Battles",
        "description": "Battles, newest first: kills in one recording that each followed the last within 2 minutes. A battle is public once all its kills are.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `nextCursor` of the page before, for the next page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, from 1 to 50. Default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BattlePage"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/battles/{id}": {
      "get": {
        "operationId": "getBattle",
        "tags": [
          "Kills"
        ],
        "summary": "One battle",
        "description": "The battle, its kills in order, and every pilot in it with their kills, losses, damage and value lost.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BattleId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Battle"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/pilots/{id}": {
      "get": {
        "operationId": "getPilot",
        "tags": [
          "Kills"
        ],
        "summary": "One pilot",
        "description": "A pilot's record: kills, final blows, losses, value destroyed and lost, who kills them most and whom they kill most, and the hulls they lose and fly. `/v1/kills?pilot=` lists their kills.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PilotId"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pilot"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    },
    "/v1/leaderboards": {
      "get": {
        "operationId": "getLeaderboards",
        "tags": [
          "Kills"
        ],
        "summary": "Leaderboards",
        "description": "Top killers, final blows and value destroyed, the biggest losses, and the deadliest zones and hulls.",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "`week` (the default), `month` or `all`.",
            "schema": {
              "type": "string",
              "enum": [
                "week",
                "month",
                "all"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "X-Citadel-Build": {
                "$ref": "#/components/headers/Build"
              },
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CORS"
              },
              "Warning": {
                "$ref": "#/components/headers/Warning"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Leaderboards"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          },
          "503": {
            "$ref": "#/components/responses/KillsUnavailable"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "description": "Every error response has this body, with the matching HTTP status.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "A fixed code for the kind of error, such as `not_found`.",
                "enum": [
                  "bad_request",
                  "not_found",
                  "too_large",
                  "rate_limited",
                  "starting",
                  "unavailable",
                  "internal"
                ]
              },
              "message": {
                "type": "string",
                "description": "What went wrong, in English."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ArtKeys": {
        "type": "object",
        "description": "Art for one record. Tier variants appear only where the game has separate art for a tier. They're named after the game's rarities, which is why they're capitalised and the other fields aren't.",
        "properties": {
          "base": {
            "type": "string",
            "description": "API-relative URL of the 128px WebP. For the 256px version, put `@2x` before `.webp`.",
            "pattern": "^/v1/art/[a-z0-9.@_-]+\\.webp$"
          },
          "Augmented": {
            "type": "string",
            "description": "Art for the Augmented tier.",
            "pattern": "^/v1/art/"
          },
          "Prototype": {
            "type": "string",
            "description": "Art for the Prototype tier.",
            "pattern": "^/v1/art/"
          },
          "Artifact": {
            "type": "string",
            "description": "Art for an artifact of the item.",
            "pattern": "^/v1/art/"
          },
          "Heretical": {
            "type": "string",
            "description": "Art for the Heretical tier.",
            "pattern": "^/v1/art/"
          }
        },
        "required": [
          "base"
        ]
      },
      "FactRow": {
        "type": "object",
        "description": "One row of an item tooltip, in the game's own wording. `label` and `value` are upper case, as in the game.",
        "properties": {
          "label": {
            "type": "string"
          },
          "value": {
            "type": [
              "string",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "tone": {
            "type": "string",
            "description": "How the game colours the row.",
            "enum": [
              "Neutral",
              "Positive",
              "Negative"
            ]
          },
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The game's `TooltipStatId` for the stat on this row, such as `CycleDuration` for a turret's FIRE RATE, `TurretReloadRateIdle` for IDLE RECHARGE and `TurretMagazineSize` for MAGAZINE SIZE. Use it to find a row without matching on its label. Null when the game gives the row no id."
          },
          "number": {
            "type": [
              "number",
              "null"
            ],
            "description": "The unrounded number behind `value`, in `unit`: where the tooltip reads 2.9 s, this can be 2.94. It already includes the game's distance scaling and its metre-to-kilometre step, and a multiplier modifier line gives it as a percent. Null when the value is a word. A number that comes from a fixed-point game value is exact to 1/65536."
          }
        },
        "required": [
          "label",
          "value",
          "unit",
          "tone",
          "id",
          "number"
        ]
      },
      "Cell": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer"
          },
          "col": {
            "type": "integer"
          }
        },
        "required": [
          "row",
          "col"
        ]
      },
      "Shape": {
        "type": "object",
        "description": "The item's footprint at rotation 0, on the 5x5 shape grid that ports are anchored to. An item placed at (row, col) covers grid cell (row + cell.row - originRow, col + cell.col - originCol).",
        "properties": {
          "originRow": {
            "type": "integer"
          },
          "originCol": {
            "type": "integer"
          },
          "cells": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Cell"
            }
          }
        },
        "required": [
          "originRow",
          "originCol",
          "cells"
        ]
      },
      "PortCandidate": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer"
          },
          "col": {
            "type": "integer"
          },
          "direction": {
            "type": "string",
            "description": "Up, Down, Left or Right."
          }
        },
        "required": [
          "row",
          "col",
          "direction"
        ]
      },
      "PortRules": {
        "type": "object",
        "description": "An item has at most `maxPorts` ports. Each is one of `candidates`, and no two are the same. Only modules have ports.",
        "properties": {
          "maxPorts": {
            "type": "integer"
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortCandidate"
            }
          }
        },
        "required": [
          "maxPorts",
          "candidates"
        ]
      },
      "Tier": {
        "type": "object",
        "properties": {
          "tier": {
            "type": "integer"
          },
          "min": {
            "type": "string",
            "description": "The lowest value a roll can have, inclusive, as raw fixed point.",
            "pattern": "^-?[0-9]+$"
          },
          "max": {
            "type": "string",
            "description": "The highest value a roll can have, inclusive, as raw fixed point.",
            "pattern": "^-?[0-9]+$"
          },
          "allowed": {
            "type": "boolean"
          }
        },
        "required": [
          "tier",
          "min",
          "max",
          "allowed"
        ]
      },
      "PoolEntry": {
        "type": "object",
        "description": "A modifier line an item can roll.",
        "properties": {
          "stat": {
            "type": "string",
            "description": "A stat id from /v1/stats."
          },
          "operation": {
            "type": "string",
            "description": "Add or Multiply."
          },
          "pool": {
            "type": "string",
            "description": "A module type name, or Role:<ShipRole> for a hull's role pool."
          },
          "group": {
            "type": "integer",
            "description": "Entries in one pool that share a nonzero group exclude each other: an item rolls at most one of them."
          },
          "augmentedOnly": {
            "type": "boolean",
            "description": "Drops only on Augmented items, and stays on an item that becomes Prototype."
          },
          "onlyOnModule": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$",
            "description": "When set, the line rolls only on the item with this id."
          },
          "tiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tier"
            }
          }
        },
        "required": [
          "stat",
          "operation",
          "pool",
          "group",
          "augmentedOnly",
          "onlyOnModule",
          "tiers"
        ]
      },
      "ModifierSlots": {
        "type": "object",
        "properties": {
          "prefix": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PoolEntry"
            }
          },
          "suffix": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PoolEntry"
            }
          }
        },
        "required": [
          "prefix",
          "suffix"
        ]
      },
      "ModifierCount": {
        "type": "object",
        "properties": {
          "rarity": {
            "type": "string"
          },
          "min": {
            "type": "integer"
          },
          "max": {
            "type": "integer"
          }
        },
        "required": [
          "rarity",
          "min",
          "max"
        ]
      },
      "AuthoredRoll": {
        "type": "object",
        "description": "A roll the game's config allows outright: an item with this quality and rarity and no modifiers, ports or references is legal, and its rating is `pointRating`.",
        "properties": {
          "source": {
            "type": "string"
          },
          "quality": {
            "type": "string"
          },
          "rarity": {
            "type": "string"
          },
          "isIdentified": {
            "type": "boolean"
          },
          "pointRating": {
            "type": "integer"
          }
        },
        "required": [
          "source",
          "quality",
          "rarity",
          "isIdentified",
          "pointRating"
        ]
      },
      "ItemRating": {
        "type": "object",
        "description": "How the game computes an item's stored rating: floor((base + contribution) x quality multiplier), plus the `pointRating` of each slotted cipher and of a harmonic set. The multiplier is 1 unless `scalesWithQuality` is set.",
        "properties": {
          "base": {
            "type": "integer"
          },
          "scalesWithQuality": {
            "type": "boolean"
          },
          "tierShares": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "regaliaShare": {
            "type": "integer"
          },
          "hereticalShare": {
            "type": "integer"
          },
          "ascendedHereticalShare": {
            "type": "integer"
          }
        },
        "required": [
          "base",
          "scalesWithQuality",
          "tierShares",
          "regaliaShare",
          "hereticalShare",
          "ascendedHereticalShare"
        ]
      },
      "Roll": {
        "type": "object",
        "description": "Everything an item can roll. References are ids from the other routes.",
        "properties": {
          "qualities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Qualities the item can have, as names."
          },
          "rarities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "modifierCounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModifierCount"
            },
            "description": "How many modifiers each modifier-bearing rarity holds."
          },
          "modifierPool": {
            "$ref": "#/components/schemas/ModifierSlots"
          },
          "typeOverrides": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Module types a THOTH adapter can give the item."
          },
          "artifacts": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            },
            "description": "Ids from /v1/artifacts."
          },
          "regalia": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            },
            "description": "Ids from /v1/regalia."
          },
          "hereticals": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            },
            "description": "Ids from /v1/heretical-specials."
          },
          "harmonicSets": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            },
            "description": "Ids from /v1/harmonic-sets."
          },
          "rating": {
            "$ref": "#/components/schemas/ItemRating"
          },
          "authored": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuthoredRoll"
            }
          }
        },
        "required": [
          "qualities",
          "rarities",
          "modifierCounts",
          "modifierPool",
          "typeOverrides",
          "artifacts",
          "regalia",
          "hereticals",
          "harmonicSets",
          "rating",
          "authored"
        ]
      },
      "Item": {
        "type": "object",
        "description": "A fittable module or conduit players can obtain.",
        "properties": {
          "def": {
            "type": "string",
            "description": "The item's id.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's description from the game, or null."
          },
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FactRow"
            },
            "description": "Tooltip rows for the item's plainest roll. Each row carries the exact `number` behind its text and the game's `id` for its stat, so a turret's FIRE RATE (`CycleDuration`, seconds between shots), IDLE RECHARGE (`TurretReloadRateIdle`) and MAGAZINE SIZE (`TurretMagazineSize`) each come as a separate row."
          },
          "category": {
            "type": "string",
            "description": "Module or Conduit."
          },
          "slotType": {
            "type": "string"
          },
          "slotSize": {
            "type": "string"
          },
          "moduleType": {
            "type": "string"
          },
          "targeting": {
            "type": "string",
            "description": "The module's `ModuleTargetingPolicy`: `CasterAnchored` (own ship), `SelectedEnemy`, `SelectedSquadAlly` (a squadmate), `WorldAim` or `EnemyAreaAroundCaster`."
          },
          "ability": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Ability"
              },
              {
                "type": "null"
              }
            ],
            "description": "The battery ability this module gives its battery, as a turret does, or null."
          },
          "payloads": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "shape": {
            "$ref": "#/components/schemas/Shape"
          },
          "portRules": {
            "$ref": "#/components/schemas/PortRules"
          },
          "roll": {
            "$ref": "#/components/schemas/Roll"
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          },
          "autoActivateOnOverheat": {
            "type": "boolean",
            "description": "The game's `isAutoActivateOnOverheat`. When true, the module switches itself on when its ship enters the Unstable heat zone."
          }
        },
        "required": [
          "def",
          "name",
          "description",
          "facts",
          "category",
          "slotType",
          "slotSize",
          "moduleType",
          "payloads",
          "shape",
          "portRules",
          "roll",
          "art",
          "targeting",
          "ability",
          "autoActivateOnOverheat"
        ]
      },
      "Hull": {
        "type": "object",
        "description": "A hull players can obtain.",
        "properties": {
          "def": {
            "type": "string",
            "description": "The hull's id.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "shipClass": {
            "type": "string",
            "description": "The hull's ship class: one of `/v1/ship-classes`."
          },
          "role": {
            "type": "string",
            "description": "The ship role the hull unlocks (one of `/v1/ship-roles`), or None."
          },
          "rows": {
            "type": "integer"
          },
          "cols": {
            "type": "integer"
          },
          "slots": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A slot type name."
            },
            "description": "The fitting grid in row-major order, with rows x cols entries."
          },
          "baseCargoCapacity": {
            "type": "integer",
            "description": "The hull's cargo slots before bonuses from fitted modules (`ShipStats.baseCargoCapacity`). 0 means the game's maximum cargo size."
          },
          "safetyHoldSlots": {
            "type": "integer",
            "description": "How many safety cargo cells the hull has: cargo cells whose items survive ship loss (`ShipFitting.safetyCargoSlotCount`). `/v1/fits/evaluate` reports the same value as `safety-hold-slots`."
          },
          "roll": {
            "$ref": "#/components/schemas/Roll"
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "def",
          "name",
          "shipClass",
          "role",
          "rows",
          "cols",
          "slots",
          "roll",
          "art",
          "baseCargoCapacity",
          "safetyHoldSlots"
        ]
      },
      "Cipher": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "stat": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          },
          "pointRating": {
            "type": "integer"
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "def",
          "name",
          "stat",
          "operation",
          "value",
          "pointRating",
          "art"
        ]
      },
      "TemplateLine": {
        "type": "object",
        "properties": {
          "stat": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "tier": {
            "type": "integer"
          },
          "min": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          },
          "max": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          },
          "scope": {
            "type": "string",
            "enum": [
              "Local",
              "ShipWide"
            ],
            "description": "`Local` when a line of this stat affects only the item's own module, `ShipWide` when it affects the whole ship. The game decides this with `StatEffectModuleSystem.IsLocalToModule` on the base module: a turret's, launcher's or minelayer's own weapon stats are local, and so is `PortCount`."
          },
          "row": {
            "$ref": "#/components/schemas/FactRow",
            "description": "The range as the tooltip shows a rolled line's bounds (`ItemModifierText.RollRange`). `value` holds the range, such as `8-14`, or `-5 to +5` when it crosses zero, and `unit` is `%` for a multiplier or resistance. When the range sits on one side of zero, the sign is on `minRow` and `maxRow`."
          },
          "minRow": {
            "$ref": "#/components/schemas/FactRow",
            "description": "The lower bound (`min`) as the tooltip shows a line with that value, such as `+8%`."
          },
          "maxRow": {
            "$ref": "#/components/schemas/FactRow",
            "description": "The upper bound (`max`) as the tooltip shows a line with that value."
          }
        },
        "required": [
          "stat",
          "operation",
          "tier",
          "min",
          "max",
          "scope",
          "row",
          "minRow",
          "maxRow"
        ]
      },
      "ScaledStatRange": {
        "type": "object",
        "properties": {
          "rule": {
            "type": "string"
          },
          "min": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          },
          "max": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          }
        },
        "required": [
          "rule",
          "min",
          "max"
        ]
      },
      "Artifact": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "item": {
            "type": "string",
            "description": "The base item the artifact is a version of.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateLine"
            },
            "description": "The artifact's lines, in order."
          },
          "scaledStat": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ScaledStatRange"
              },
              {
                "type": "null"
              }
            ]
          },
          "pointRating": {
            "type": "integer"
          },
          "patinaMax": {
            "type": "integer"
          },
          "targeting": {
            "type": "string",
            "description": "The `ModuleTargetingPolicy` of the artifact's base module, which the artifact is cast as."
          },
          "ability": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Ability"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artifact's own battery ability, which takes over its battery. Null when the artifact keeps its base module's ability."
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ],
            "description": "Only artifacts with an icon of their own have art. The rest use their base item's."
          }
        },
        "required": [
          "def",
          "name",
          "item",
          "modifiers",
          "scaledStat",
          "pointRating",
          "patinaMax",
          "art",
          "targeting",
          "ability"
        ]
      },
      "Regalia": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "item": {
            "type": "string",
            "description": "The base item.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "set": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$",
            "description": "The regalia set it belongs to."
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateLine"
            }
          },
          "scaledStat": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ScaledStatRange"
              },
              {
                "type": "null"
              }
            ]
          },
          "linkedBonuses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SetBonus"
            },
            "description": "What this piece itself grants once 2, 3 or 4 pieces of its set are linked (the game's `partialSetBonuses`)."
          }
        },
        "required": [
          "def",
          "name",
          "item",
          "set",
          "modifiers",
          "scaledStat",
          "linkedBonuses"
        ]
      },
      "RegaliaSet": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "pieces": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A regalia id.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            }
          },
          "bonuses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SetBonus"
            },
            "description": "The set's bonuses by number of linked pieces, as a set-bonus table shows them (the game's `bonus2Piece`, `bonus3Piece` and `bonus4Piece`)."
          }
        },
        "required": [
          "def",
          "name",
          "pieces",
          "bonuses"
        ]
      },
      "HereticalSpecial": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "heresy": {
            "type": "string"
          },
          "ascended": {
            "type": "boolean"
          },
          "moduleTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "def",
          "name",
          "heresy",
          "ascended",
          "moduleTypes"
        ]
      },
      "HarmonicSet": {
        "type": "object",
        "description": "A Normal module whose ports hold exactly these ciphers, in any order, takes the set's cipher key.",
        "properties": {
          "def": {
            "type": "string",
            "description": "An asset GUID as a decimal string: a signed 64-bit integer with no plus sign or leading zeros.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "moduleTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ciphers": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A cipher id.",
              "pattern": "^(0|-?[1-9][0-9]*)$"
            }
          },
          "pointRating": {
            "type": "integer"
          }
        },
        "required": [
          "def",
          "name",
          "description",
          "moduleTypes",
          "ciphers",
          "pointRating"
        ]
      },
      "ModifierPool": {
        "type": "object",
        "properties": {
          "moduleType": {
            "type": "string"
          },
          "modifiers": {
            "$ref": "#/components/schemas/ModifierSlots"
          }
        },
        "required": [
          "moduleType",
          "modifiers"
        ]
      },
      "Quality": {
        "type": "object",
        "properties": {
          "quality": {
            "type": "string"
          },
          "multiplier": {
            "type": "string",
            "description": "The rating multiplier, raw fixed point.",
            "pattern": "^-?[0-9]+$"
          }
        },
        "required": [
          "quality",
          "multiplier"
        ]
      },
      "PlacementRule": {
        "type": "object",
        "description": "Where an item of `slotType` may sit. Every cell it covers must be one of `covers`, and when `hardpoint` is set, at least one of those cells must be of that type.",
        "properties": {
          "slotType": {
            "type": "string"
          },
          "covers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "hardpoint": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "slotType",
          "covers",
          "hardpoint"
        ]
      },
      "AffinityChoice": {
        "type": "object",
        "properties": {
          "option": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "option",
          "name",
          "description"
        ]
      },
      "AffinityTier": {
        "type": "object",
        "properties": {
          "tier": {
            "type": "integer"
          },
          "requiredPoints": {
            "type": "integer"
          },
          "choices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffinityChoice"
            }
          }
        },
        "required": [
          "tier",
          "requiredPoints",
          "choices"
        ]
      },
      "AffinityBonus": {
        "type": "object",
        "properties": {
          "option": {
            "type": "integer"
          },
          "stat": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "valuePerPoint": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "invertDisplaySign": {
            "type": "boolean"
          }
        },
        "required": [
          "option",
          "stat",
          "operation",
          "valuePerPoint",
          "name",
          "description",
          "invertDisplaySign"
        ]
      },
      "AffinityType": {
        "type": "object",
        "properties": {
          "moduleType": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "optionName": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "bonuses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffinityBonus"
            }
          },
          "thresholds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffinityTier"
            }
          }
        },
        "required": [
          "moduleType",
          "name",
          "optionName",
          "description",
          "bonuses",
          "thresholds"
        ]
      },
      "Affinity": {
        "type": "object",
        "description": "The affinity tree.",
        "properties": {
          "maxLevel": {
            "type": "integer"
          },
          "maxPointsPerCategory": {
            "type": "integer"
          },
          "maxPointsPerBonus": {
            "type": "integer"
          },
          "levelXp": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "`levelXp[level - 1]` is the XP a level needs."
          },
          "ratingByPoints": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Rating added by the total points spent."
          },
          "types": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AffinityType"
            }
          },
          "layout": {
            "$ref": "#/components/schemas/AffinityLayout"
          }
        },
        "required": [
          "maxLevel",
          "maxPointsPerCategory",
          "maxPointsPerBonus",
          "levelXp",
          "ratingByPoints",
          "types",
          "layout"
        ]
      },
      "Npc": {
        "type": "object",
        "description": "An NPC ship, boss or NPC-only weapon that players run into. v1 doesn't include their stats or behaviour.",
        "properties": {
          "id": {
            "type": "string",
            "description": "A GUID as a decimal string, or `boss:<archetypeId>` for a boss that is an elite archetype with no prototype of its own. NPC weapons have item GUIDs, but `/v1/items/{id}` doesn't serve them because players can't obtain those weapons.",
            "pattern": "^((0|-?[1-9][0-9]*)|boss:.+)$"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "description": "What it is.",
            "enum": [
              "ship",
              "boss",
              "weapon"
            ]
          },
          "class": {
            "type": [
              "string",
              "null"
            ],
            "description": "The flown ship's class; null on a weapon."
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "The flown ship's role; null when it has none."
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "class",
          "role",
          "art"
        ]
      },
      "Stat": {
        "type": "object",
        "description": "One stat type. The game has no unit per stat type, so there is no unit field.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The stat type's name, as used in modifiers and stat lines."
          },
          "label": {
            "type": "string",
            "description": "The game's label."
          },
          "lowerIsBetter": {
            "type": "boolean"
          },
          "integer": {
            "type": "boolean",
            "description": "True when the game treats the stat's values as whole numbers."
          },
          "invertedSign": {
            "type": "boolean",
            "description": "True when the game shows a multiplier's sign inverted."
          }
        },
        "required": [
          "id",
          "label",
          "lowerIsBetter",
          "integer",
          "invertedSign"
        ]
      },
      "Counts": {
        "type": "object",
        "properties": {
          "hulls": {
            "type": "integer"
          },
          "items": {
            "type": "integer"
          },
          "ciphers": {
            "type": "integer"
          },
          "artifacts": {
            "type": "integer"
          },
          "regaliaSets": {
            "type": "integer"
          }
        },
        "required": [
          "hulls",
          "items",
          "ciphers",
          "artifacts",
          "regaliaSets"
        ]
      },
      "Status": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the live build."
          },
          "liveSince": {
            "type": "string",
            "description": "When the build was exported, ISO 8601 UTC.",
            "format": "date-time"
          },
          "counts": {
            "$ref": "#/components/schemas/Counts"
          }
        },
        "required": [
          "build",
          "liveSince",
          "counts"
        ]
      },
      "ItemList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Item"
            }
          }
        },
        "required": [
          "build",
          "items"
        ]
      },
      "HullList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "hulls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Hull"
            }
          }
        },
        "required": [
          "build",
          "hulls"
        ]
      },
      "CipherList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "ciphers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Cipher"
            }
          }
        },
        "required": [
          "build",
          "ciphers"
        ]
      },
      "ArtifactList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "artifacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Artifact"
            }
          }
        },
        "required": [
          "build",
          "artifacts"
        ]
      },
      "RegaliaSetList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "regaliaSets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RegaliaSet"
            }
          }
        },
        "required": [
          "build",
          "regaliaSets"
        ]
      },
      "RegaliaList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "regalia": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Regalia"
            }
          }
        },
        "required": [
          "build",
          "regalia"
        ]
      },
      "HereticalSpecialList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "hereticalSpecials": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HereticalSpecial"
            }
          }
        },
        "required": [
          "build",
          "hereticalSpecials"
        ]
      },
      "HarmonicSetList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "harmonicSets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HarmonicSet"
            }
          }
        },
        "required": [
          "build",
          "harmonicSets"
        ]
      },
      "ModifierPoolList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "modifierPools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModifierPool"
            }
          }
        },
        "required": [
          "build",
          "modifierPools"
        ]
      },
      "QualityList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "qualities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quality"
            }
          }
        },
        "required": [
          "build",
          "qualities"
        ]
      },
      "PlacementRuleList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "placementRules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlacementRule"
            }
          }
        },
        "required": [
          "build",
          "placementRules"
        ]
      },
      "NpcList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "npcs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Npc"
            }
          }
        },
        "required": [
          "build",
          "npcs"
        ]
      },
      "StatList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "stats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Stat"
            }
          }
        },
        "required": [
          "build",
          "stats"
        ]
      },
      "AffinityResponse": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "affinity": {
            "$ref": "#/components/schemas/Affinity"
          }
        },
        "required": [
          "build",
          "affinity"
        ]
      },
      "OpenModifier": {
        "type": "object",
        "properties": {
          "stat": {
            "type": "string",
            "description": "A stat id from /v1/stats."
          },
          "operation": {
            "type": "string"
          },
          "tier": {
            "type": "integer"
          },
          "value": {
            "type": "string",
            "description": "The rolled value, raw fixed point.",
            "pattern": "^-?[0-9]+$"
          },
          "slot": {
            "type": "integer"
          },
          "isInverted": {
            "type": "boolean"
          },
          "isFractured": {
            "type": "boolean"
          }
        },
        "required": [
          "stat",
          "operation",
          "tier",
          "value",
          "slot",
          "isInverted",
          "isFractured"
        ]
      },
      "OpenPort": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer"
          },
          "col": {
            "type": "integer"
          },
          "direction": {
            "type": "string"
          },
          "cipher": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$",
            "description": "The cipher in the port, or null for an empty one."
          }
        },
        "required": [
          "row",
          "col",
          "direction",
          "cipher"
        ]
      },
      "OpenScaledStat": {
        "type": "object",
        "properties": {
          "rule": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "strength": {
            "type": "string",
            "description": "A fixed-point number as a raw decimal string: divide by 65536.",
            "pattern": "^-?[0-9]+$"
          }
        },
        "required": [
          "rule",
          "strength"
        ]
      },
      "OpenRoll": {
        "type": "object",
        "description": "An item's roll. There's no rating field: the API computes the rating itself and ignores one if you send it.",
        "properties": {
          "quality": {
            "type": "string"
          },
          "rarity": {
            "type": "string"
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenModifier"
            }
          },
          "ports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenPort"
            }
          },
          "artifact": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "regalia": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "heretical": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "ascended": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$",
            "description": "The ascended form that an ascended GULLVEIG BRAND gave, alongside the special in `heretical`."
          },
          "moduleTypeOverride": {
            "type": [
              "string",
              "null"
            ]
          },
          "isIdentified": {
            "type": "boolean"
          },
          "isHarmonized": {
            "type": "boolean"
          },
          "isMirrored": {
            "type": "boolean"
          },
          "harmonicSet": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "scaledStat": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OpenScaledStat"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "quality",
          "rarity",
          "modifiers",
          "ports",
          "artifact",
          "regalia",
          "heretical",
          "ascended",
          "moduleTypeOverride",
          "isIdentified",
          "isHarmonized",
          "isMirrored",
          "harmonicSet",
          "scaledStat"
        ]
      },
      "OpenItem": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "An item or hull id. Any item the build defines is accepted, obtainable or not.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "roll": {
            "$ref": "#/components/schemas/OpenRoll"
          },
          "patina": {
            "type": "integer"
          }
        },
        "required": [
          "def",
          "roll",
          "patina"
        ]
      },
      "OpenModule": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/OpenItem"
          },
          "row": {
            "type": "integer"
          },
          "col": {
            "type": "integer"
          },
          "rotation": {
            "type": "integer",
            "description": "Quarter turns, 0 to 3."
          }
        },
        "required": [
          "item",
          "row",
          "col",
          "rotation"
        ]
      },
      "OpenProgression": {
        "type": "object",
        "properties": {
          "affinityType": {
            "type": "string"
          },
          "affinityXp": {
            "type": "integer"
          },
          "allocatedPoints": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "thresholdSelections": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        },
        "required": [
          "affinityType",
          "affinityXp",
          "allocatedPoints",
          "thresholdSelections"
        ]
      },
      "OpenAmmo": {
        "type": "object",
        "properties": {
          "moduleIndex": {
            "type": "integer"
          },
          "ammoType": {
            "type": "string"
          }
        },
        "required": [
          "moduleIndex",
          "ammoType"
        ]
      },
      "OpenSlotOverride": {
        "type": "object",
        "properties": {
          "cell": {
            "type": "integer",
            "description": "The cell index: row x columns + col."
          },
          "slotType": {
            "type": "string"
          }
        },
        "required": [
          "cell",
          "slotType"
        ]
      },
      "OpenFit": {
        "type": "object",
        "description": "A fit written out by name: GUIDs are decimal strings, enums are their names, and fixed-point values are raw decimal strings. A request may leave fields out. The evaluation reads as much of the fit as it can and reports each missing or unreadable part as an `InvalidFit` issue, with status 200 and `valid: false`, instead of rejecting the request.",
        "properties": {
          "version": {
            "type": "integer",
            "description": "Always 1."
          },
          "hull": {
            "$ref": "#/components/schemas/OpenItem"
          },
          "progression": {
            "$ref": "#/components/schemas/OpenProgression"
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenModule"
            }
          },
          "ammo": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenAmmo"
            }
          },
          "slotOverrides": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpenSlotOverride"
            }
          }
        },
        "required": [
          "version",
          "hull",
          "progression",
          "modules",
          "ammo",
          "slotOverrides"
        ]
      },
      "FitBody": {
        "type": "object",
        "description": "A fit. Fields you leave out are accepted and reported as issues by the evaluation; see `OpenFit`.",
        "properties": {
          "fit": {
            "$ref": "#/components/schemas/OpenFit"
          }
        },
        "required": [
          "fit"
        ]
      },
      "FitStringBody": {
        "type": "object",
        "properties": {
          "fitString": {
            "type": "string",
            "description": "The game's shareable fit string."
          }
        },
        "required": [
          "fitString"
        ]
      },
      "ItemBody": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/OpenItem"
          }
        },
        "required": [
          "item"
        ]
      },
      "FactsBody": {
        "type": "object",
        "properties": {
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FactRow"
            }
          }
        },
        "required": [
          "facts"
        ]
      },
      "EvaluationIssue": {
        "type": "object",
        "properties": {
          "moduleIndex": {
            "type": "integer",
            "description": "Index into the fit's modules; -1 when the issue is about the hull or the fit."
          },
          "kind": {
            "type": "string",
            "description": "The kind of issue, such as `SlotNotFittable`. Kinds don't change between builds."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "moduleIndex",
          "kind",
          "message"
        ]
      },
      "ConduitLink": {
        "type": "object",
        "properties": {
          "moduleIndex": {
            "type": "integer"
          },
          "connectionCount": {
            "type": "integer"
          }
        },
        "required": [
          "moduleIndex",
          "connectionCount"
        ]
      },
      "RegaliaGroup": {
        "type": "object",
        "properties": {
          "set": {
            "type": "string",
            "description": "A regalia set id.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "fittedCount": {
            "type": "integer"
          },
          "moduleIndices": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        },
        "required": [
          "set",
          "fittedCount",
          "moduleIndices"
        ]
      },
      "StatSource": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          },
          "asset": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the item or definition behind the source."
          },
          "affinityType": {
            "type": "string"
          },
          "raw": {
            "type": "number"
          },
          "ratio": {
            "type": "number"
          },
          "effective": {
            "type": "number"
          },
          "isStackingExempt": {
            "type": "boolean"
          }
        },
        "required": [
          "kind",
          "asset",
          "affinityType",
          "raw",
          "ratio",
          "effective",
          "isStackingExempt"
        ]
      },
      "StatLine": {
        "type": "object",
        "properties": {
          "stat": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "total": {
            "type": "number"
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StatSource"
            }
          }
        },
        "required": [
          "stat",
          "stage",
          "operation",
          "total",
          "sources"
        ]
      },
      "ModifierGroup": {
        "type": "object",
        "description": "A category of the MODIFIERS list, in the game's order: Defense, Offense, Reactor, Agility, Targeting, Utility. A category the fit doesn't change is left out.",
        "properties": {
          "category": {
            "type": "string",
            "description": "The category, such as `Agility`."
          },
          "label": {
            "type": "string",
            "description": "The category's name as the game shows it, such as `AGILITY`."
          },
          "rows": {
            "type": "array",
            "description": "Largest change first.",
            "items": {
              "$ref": "#/components/schemas/ModifierRow"
            }
          }
        },
        "required": [
          "category",
          "label",
          "rows"
        ]
      },
      "ModifierRow": {
        "type": "object",
        "description": "One stat's change with every calculation stage combined.",
        "properties": {
          "stat": {
            "type": "string",
            "description": "The stat's id, as `GET /v1/stats` lists it."
          },
          "label": {
            "type": "string",
            "description": "The stat's name as the game shows it, such as `MAX VELOCITY`."
          },
          "operation": {
            "type": "string",
            "description": "`Add`, `Multiply` or `DamageReduction`."
          },
          "total": {
            "type": "number",
            "description": "The combined change. Stages combine in order: `Add` totals add up, `Multiply` totals compound as (1 + a)(1 + b) - 1 and `DamageReduction` totals as 1 - (1 - a)(1 - b). A `Multiply` or `DamageReduction` total is a fraction, so 0.186 reads as +18.6%."
          },
          "sources": {
            "type": "array",
            "description": "The sources of every stage, largest effect first.",
            "items": {
              "$ref": "#/components/schemas/ModifierSource"
            }
          }
        },
        "required": [
          "stat",
          "label",
          "operation",
          "total",
          "sources"
        ]
      },
      "ModifierSource": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          },
          "asset": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the item or definition behind the source."
          },
          "affinityType": {
            "type": "string"
          },
          "raw": {
            "type": "number"
          },
          "ratio": {
            "type": "number"
          },
          "effective": {
            "type": "number"
          },
          "isStackingExempt": {
            "type": "boolean"
          },
          "parts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModifierPart"
            }
          }
        },
        "required": [
          "kind",
          "asset",
          "affinityType",
          "raw",
          "ratio",
          "effective",
          "isStackingExempt",
          "parts"
        ],
        "description": "A source of a modifier row, as in `StatSource`, with `parts`. The game stacks a fitted module's lines on one stat (its own stat, rolls, ciphers, harmonic lines) as one source, and `parts` lists each of them. Empty when the source is its module's only line, or isn't a module's."
      },
      "ModifierPart": {
        "type": "object",
        "description": "One line inside a module's stacked source.",
        "properties": {
          "kind": {
            "type": "string"
          },
          "asset": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the item or definition behind the line."
          },
          "raw": {
            "type": "number",
            "description": "The line's own value, before the stacking penalty."
          }
        },
        "required": [
          "kind",
          "asset",
          "raw"
        ]
      },
      "SpecValue": {
        "type": "object",
        "description": "The game shows `text` followed by `unit`.",
        "properties": {
          "text": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "number": {
            "type": [
              "number",
              "null"
            ],
            "description": "The shown number in that unit, or null for a word such as STABLE."
          }
        },
        "required": [
          "text",
          "unit",
          "number"
        ]
      },
      "SpecHelp": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "title",
          "text"
        ]
      },
      "SpecRow": {
        "type": "object",
        "description": "A row of the game's hull spec panel.",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "primary": {
            "$ref": "#/components/schemas/SpecValue"
          },
          "secondary": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SpecValue"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when the row is a comparison: `primary` is the stat before, `secondary` the stat now."
          },
          "primaryTone": {
            "type": "string"
          },
          "secondaryTone": {
            "type": "string"
          },
          "help": {
            "$ref": "#/components/schemas/SpecHelp"
          }
        },
        "required": [
          "id",
          "label",
          "primary",
          "secondary",
          "primaryTone",
          "secondaryTone",
          "help"
        ]
      },
      "SpecSection": {
        "type": "object",
        "description": "A section of the game's hull spec panel, in the panel's order.",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecRow"
            }
          }
        },
        "required": [
          "id",
          "label",
          "rows"
        ]
      },
      "Evaluation": {
        "type": "object",
        "properties": {
          "buildSha": {
            "type": "string"
          },
          "valid": {
            "type": "boolean",
            "description": "False when `issues` isn't empty."
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvaluationIssue"
            }
          },
          "conduits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConduitLink"
            }
          },
          "regaliaSets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RegaliaGroup"
            }
          },
          "stats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StatLine"
            },
            "description": "One line per stat, operation and calculation stage, so a stat that modules and an affinity both change has two lines. `modifierGroups` combines them the way the game shows them."
          },
          "rating": {
            "type": "integer"
          },
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpecSection"
            }
          },
          "modifierGroups": {
            "type": "array",
            "description": "The fit's stat changes as the game's hull spec panel lists them under MODIFIERS: by category, with one row per stat and operation and every calculation stage combined. Empty for an invalid fit.",
            "items": {
              "$ref": "#/components/schemas/ModifierGroup"
            }
          }
        },
        "required": [
          "buildSha",
          "valid",
          "issues",
          "conduits",
          "regaliaSets",
          "stats",
          "rating",
          "sections",
          "modifierGroups"
        ]
      },
      "Ability": {
        "type": "object",
        "description": "A battery ability, worded as the game words it (upper case).",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "description"
        ]
      },
      "GrantModifier": {
        "type": "object",
        "description": "A fixed stat modifier a set or piece bonus grants.",
        "properties": {
          "stat": {
            "type": "string",
            "description": "A stat id from `/v1/stats`."
          },
          "operation": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "description": "The value set in the game data, as a raw fixed-point decimal string (divide by 65536), in the stat system's format: a Multiply of 1.45 means +45%. `row.number` holds the same value as the tooltip shows it, unrounded, so a Multiply comes as a percent.",
            "pattern": "^-?[0-9]+$"
          },
          "row": {
            "$ref": "#/components/schemas/FactRow",
            "description": "The line as the item tooltip words it, such as MAX VELOCITY +12.5%."
          }
        },
        "required": [
          "stat",
          "operation",
          "value",
          "row"
        ]
      },
      "GrantEffect": {
        "type": "object",
        "description": "A grant that is not a stat line, worded as the game words it.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "Triggered",
              "ScaledStat",
              "RuntimeStatRule",
              "PassiveStateTick"
            ],
            "description": "What the text is for each kind. Triggered: the effect's tooltip text. ScaledStat: the rule's tooltip template, which may contain `{value}`. RuntimeStatRule and PassiveStateTick: the rule's description."
          },
          "rule": {
            "type": "string",
            "description": "The rule's asset id.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "text": {
            "type": "string"
          },
          "chance": {
            "oneOf": [
              {
                "type": "string",
                "description": "A fixed-point number as a raw decimal string: divide by 65536.",
                "pattern": "^-?[0-9]+$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Triggered only. The grant's chance as fixed point, where 65536 means always."
          },
          "strength": {
            "oneOf": [
              {
                "type": "string",
                "description": "A fixed-point number as a raw decimal string: divide by 65536.",
                "pattern": "^-?[0-9]+$"
              },
              {
                "type": "null"
              }
            ],
            "description": "ScaledStat only: the grant's strength."
          },
          "displayText": {
            "type": "string",
            "description": "The line as the game's tooltip shows it, with its numbers filled in (`EffectGrantText`). A Triggered effect below 100% starts with its chance, such as `65% ...`, and a ScaledStat's `{value}` becomes the number the game shows. The chance is already in the text, so don't add it again."
          },
          "chanceNumber": {
            "type": [
              "number",
              "null"
            ],
            "description": "Triggered only: the chance in `displayText` as a fraction, where 1 means always, exactly as the fixed-point value holds it. Null for the other kinds."
          }
        },
        "required": [
          "kind",
          "rule",
          "text",
          "chance",
          "strength",
          "displayText",
          "chanceNumber"
        ]
      },
      "SetBonus": {
        "type": "object",
        "description": "What a set, or one of its pieces, grants once `pieces` pieces of the set are linked. Only the tiers the game shows are listed, meaning enabled tiers with at least one grant, in order of `pieces`.",
        "properties": {
          "pieces": {
            "type": "integer",
            "description": "2, 3 or 4."
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GrantModifier"
            }
          },
          "effects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GrantEffect"
            }
          }
        },
        "required": [
          "pieces",
          "modifiers",
          "effects"
        ]
      },
      "GridConsumable": {
        "type": "object",
        "description": "A consumable that changes a fitting grid.",
        "properties": {
          "def": {
            "type": "string",
            "description": "The item id.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "description": "`FittingGridExtender` (adds a cell beside the grid) or `FittingCoreSlotTransformer` (changes a cell)."
          },
          "behavior": {
            "type": "string",
            "description": "`FixedTarget` (always the same change) or `RandomCorrupt` (SKULD: one of several changes)."
          },
          "fixedTargetSlotType": {
            "type": [
              "string",
              "null"
            ],
            "description": "The hardpoint a converter makes; null for the others."
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "def",
          "name",
          "kind",
          "behavior",
          "fixedTargetSlotType",
          "art"
        ]
      },
      "BreachTier": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0,
            "description": "What `POST /v1/roll` takes as `breachTier`."
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "index",
          "name"
        ]
      },
      "GridConsumableList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "gridConsumables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GridConsumable"
            }
          }
        },
        "required": [
          "build",
          "gridConsumables"
        ]
      },
      "BreachTierList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "breachTiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreachTier"
            }
          }
        },
        "required": [
          "build",
          "breachTiers"
        ]
      },
      "ShipClass": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "art": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "name",
          "art"
        ]
      },
      "ShipClassList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "shipClasses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShipClass"
            }
          },
          "unknownArt": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ArtKeys"
              },
              {
                "type": "null"
              }
            ],
            "description": "The overlay's icon for a ship whose class isn't known."
          }
        },
        "required": [
          "build",
          "shipClasses",
          "unknownArt"
        ]
      },
      "ShipRoleList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "shipRoles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "build",
          "shipRoles"
        ]
      },
      "DeathCauseList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "deathCauses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "build",
          "deathCauses"
        ]
      },
      "Zone": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The zone's id, such as `crusaders_pass`: what a kill's `zone.id` holds."
          },
          "name": {
            "type": "string",
            "description": "The zone's name, as the game shows it. Not unique: an event route can reuse a zone's name."
          },
          "tiers": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0
            },
            "description": "The breach tiers the zone's rooms run at, as `/v1/breach-tiers` indexes them. A zone picks one of its rooms each cycle, so a kill's `zone.tier` is one of these."
          },
          "isTravelLane": {
            "type": "boolean",
            "description": "A travel lane rather than a dungeon."
          },
          "isTournament": {
            "type": "boolean",
            "description": "A private event route, which the public map never shows."
          }
        },
        "required": [
          "id",
          "name",
          "tiers",
          "isTravelLane",
          "isTournament"
        ]
      },
      "ZoneList": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "zones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Zone"
            }
          }
        },
        "required": [
          "build",
          "zones"
        ]
      },
      "GridModResult": {
        "type": "object",
        "description": "A cell a use changes, and the slot type it leaves there (`None` for a destroyed cell).",
        "properties": {
          "cell": {
            "type": "integer"
          },
          "slotType": {
            "type": "string"
          }
        },
        "required": [
          "cell",
          "slotType"
        ]
      },
      "GridModTarget": {
        "type": "object",
        "description": "A cell the consumable can be used on, and every change a use can make: one for a fixed consumable, several for SKULD.",
        "properties": {
          "cell": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GridModResult"
            }
          }
        },
        "required": [
          "cell",
          "results"
        ]
      },
      "GridModOption": {
        "type": "object",
        "properties": {
          "def": {
            "type": "string",
            "description": "The grid consumable, as `/v1/grid-consumables` lists it.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "targets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GridModTarget"
            }
          }
        },
        "required": [
          "def",
          "targets"
        ]
      },
      "GridModBudget": {
        "type": "object",
        "description": "What the fit's grid changes have used up: extender cells out of `maxExpansions`, and the hardpoint types whose one converter is spent.",
        "properties": {
          "expansions": {
            "type": "integer"
          },
          "maxExpansions": {
            "type": "integer"
          },
          "convertersSpent": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "expansions",
          "maxExpansions",
          "convertersSpent"
        ]
      },
      "GridMods": {
        "type": "object",
        "properties": {
          "buildSha": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "refusal": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why no consumable can be used at all (a mirrored hull); null otherwise."
          },
          "budget": {
            "$ref": "#/components/schemas/GridModBudget"
          },
          "consumables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GridModOption"
            }
          }
        },
        "required": [
          "buildSha",
          "refusal",
          "budget",
          "consumables"
        ]
      },
      "RollBody": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/OpenItem"
          },
          "breachTier": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "An index from `/v1/breach-tiers`. Leave it out for the highest."
          },
          "seed": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Seeds the roll. Leave it out and the API picks one."
          },
          "line": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Roll only this modifier again, by its index in `item.roll.modifiers`."
          }
        },
        "required": [
          "item"
        ]
      },
      "RolledItem": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/OpenItem"
          },
          "breachTier": {
            "type": "integer",
            "minimum": 0
          },
          "seed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "item",
          "breachTier",
          "seed"
        ]
      },
      "AffinityLayout": {
        "type": "object",
        "description": "Where a progression stores each value. The points on a bonus are at `allocatedPoints[moduleTypes[type] * optionsPerType + option]`. A threshold choice is at `thresholdSelections[moduleTypes[type] * tiersPerType + tier]`, and `selectionUnset` there means no choice was made.",
        "properties": {
          "moduleTypes": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Each module type's number, as used above."
          },
          "optionsPerType": {
            "type": "integer",
            "minimum": 1,
            "description": "The most bonuses a module type can have."
          },
          "tiersPerType": {
            "type": "integer",
            "minimum": 1,
            "description": "The most threshold tiers a module type can have."
          },
          "allocationSlots": {
            "type": "integer",
            "minimum": 1,
            "description": "The longest `allocatedPoints` can be."
          },
          "thresholdSlots": {
            "type": "integer",
            "minimum": 1,
            "description": "The longest `thresholdSelections` can be."
          },
          "selectionUnset": {
            "type": "integer",
            "minimum": 0,
            "description": "The value of a threshold with no choice made."
          }
        },
        "required": [
          "moduleTypes",
          "optionsPerType",
          "tiersPerType",
          "allocationSlots",
          "thresholdSlots",
          "selectionUnset"
        ]
      },
      "GridArtRect": {
        "type": "object",
        "description": "A rectangle in pixels of a `cellSize` cell, measured from the top left of the slot box.",
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          },
          "width": {
            "type": "number"
          },
          "height": {
            "type": "number"
          }
        },
        "required": [
          "x",
          "y",
          "width",
          "height"
        ]
      },
      "GridPortNotch": {
        "type": "object",
        "description": "The notch a port cuts into a module's tile, drawn inside the slot box of the port's cell.",
        "properties": {
          "body": {
            "$ref": "#/components/schemas/GridArtRect"
          },
          "bridge": {
            "$ref": "#/components/schemas/GridArtRect",
            "description": "The part that reaches into the next cell. Its width and height are 0 when there is none."
          },
          "borders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GridArtRect"
            },
            "description": "The notch's edge lines."
          }
        },
        "required": [
          "body",
          "bridge",
          "borders"
        ]
      },
      "GridHardpointIcon": {
        "type": "object",
        "description": "A hardpoint icon as SVG path data.",
        "properties": {
          "viewBox": {
            "type": "string"
          },
          "paths": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The `d` attribute of each path."
          }
        },
        "required": [
          "viewBox",
          "paths"
        ]
      },
      "FittingGridStyle": {
        "type": "object",
        "description": "How the game's fitting panel draws a grid.",
        "properties": {
          "cellSize": {
            "type": "integer",
            "minimum": 1,
            "description": "The cell size, in pixels, that every other length here is measured in."
          },
          "slotInset": {
            "type": "number",
            "minimum": 0,
            "description": "How far each slot box sits inside its cell, on every side."
          },
          "ports": {
            "type": "object",
            "description": "The notches for each kind of port, one per direction, in the order up, down, left, right.",
            "properties": {
              "FemaleOpen": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GridPortNotch"
                },
                "description": "A port with nothing joined to it."
              },
              "MaleAttached": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GridPortNotch"
                },
                "description": "A port joined to a conduit."
              },
              "Expansion": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GridPortNotch"
                },
                "description": "A port on an expansion cell, where a cipher sits."
              }
            },
            "required": [
              "FemaleOpen",
              "MaleAttached",
              "Expansion"
            ]
          },
          "hardpoints": {
            "type": "object",
            "description": "The icon the game draws on an empty hardpoint cell, keyed by the slot type a hull's `grid` names the cell with.",
            "additionalProperties": {
              "$ref": "#/components/schemas/GridHardpointIcon"
            }
          },
          "colors": {
            "type": "object",
            "description": "The colours the grid uses for its states, such as `InvalidRed` and `ConduitConnected`, as CSS `rgba()`.",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "cellSize",
          "slotInset",
          "ports",
          "hardpoints",
          "colors"
        ]
      },
      "UiFittingGridResponse": {
        "type": "object",
        "properties": {
          "build": {
            "type": "string",
            "description": "The commit SHA of the build."
          },
          "fittingGrid": {
            "$ref": "#/components/schemas/FittingGridStyle"
          }
        },
        "required": [
          "build",
          "fittingGrid"
        ]
      },
      "HullRef": {
        "type": "object",
        "description": "A hull by id and name.",
        "properties": {
          "def": {
            "type": [
              "string",
              "null"
            ],
            "description": "The hull's id: a player hull's, which `/v1/hulls/{id}` resolves, or an NPC ship's, which `/v1/npcs` lists. Null for a kill recorded before the killboard kept ids.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string",
            "description": "The hull's name, as the game shows it."
          },
          "class": {
            "type": [
              "string",
              "null"
            ],
            "description": "The hull's class, such as Cruiser, or null when the recording didn't keep it."
          },
          "art": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The hull's image as a full URL on https://art.thecitadel.com: the 128px WebP, and the 256px one with `@2x` before `.webp`. A victim's hull is drawn at its rarity. Null when the live build has no image for the id."
          }
        },
        "required": [
          "def",
          "name",
          "class",
          "art"
        ]
      },
      "ZoneRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The zone's region id, or null when the recording kept none."
          },
          "name": {
            "type": "string",
            "description": "The zone's name, as the game shows it. Empty for a kill recorded without one."
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "KillZone": {
        "type": "object",
        "description": "Where the ship died.",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The zone's region id, or null when the recording kept none. One of `/v1/zones`."
          },
          "name": {
            "type": "string",
            "description": "The zone's name, as the game shows it. Empty for a kill recorded without one."
          },
          "tier": {
            "type": "integer",
            "description": "The breach tier, from 0."
          },
          "isTravelLane": {
            "type": "boolean",
            "description": "Whether the ship died in a travel lane."
          }
        },
        "required": [
          "id",
          "name",
          "tier",
          "isTravelLane"
        ]
      },
      "Party": {
        "type": "object",
        "description": "A pilot or an NPC.",
        "properties": {
          "pilotId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pilot's id, or null for an NPC."
          },
          "name": {
            "type": "string",
            "description": "The pilot's name, or the NPC's."
          },
          "hull": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HullRef"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "pilotId",
          "name",
          "hull"
        ]
      },
      "Victim": {
        "type": "object",
        "description": "The pilot who lost the ship.",
        "properties": {
          "pilotId": {
            "type": "string",
            "description": "The pilot's id, as `/v1/pilots/{id}` takes it."
          },
          "name": {
            "type": "string",
            "description": "The pilot's name when the ship died."
          },
          "hull": {
            "$ref": "#/components/schemas/HullRef"
          },
          "rarity": {
            "type": [
              "string",
              "null"
            ],
            "description": "The hull's rarity, or null when the recording didn't keep it."
          },
          "buildRating": {
            "type": "integer",
            "description": "The ship's build rating when it died."
          }
        },
        "required": [
          "pilotId",
          "name",
          "hull",
          "rarity",
          "buildRating"
        ]
      },
      "KillValue": {
        "type": "object",
        "description": "What the ship was worth in ore, as the game's kill card computes it: build rating times the recycle payout.",
        "properties": {
          "hull": {
            "type": "integer",
            "description": "Ore value of the hull."
          },
          "fitting": {
            "type": "integer",
            "description": "Ore value of the fitted modules."
          },
          "cargo": {
            "type": "integer",
            "description": "Ore value of the cargo."
          },
          "total": {
            "type": "integer",
            "description": "The three added together."
          }
        },
        "required": [
          "hull",
          "fitting",
          "cargo",
          "total"
        ]
      },
      "KillLinks": {
        "type": "object",
        "properties": {
          "killCam": {
            "type": [
              "string",
              "null"
            ],
            "description": "The fight's 3D kill cam viewer, when the kill feed published one."
          },
          "clip": {
            "type": [
              "string",
              "null"
            ],
            "description": "A rendered video of the fight (MP4), when the kill feed published one."
          }
        },
        "required": [
          "killCam",
          "clip"
        ]
      },
      "KillSummary": {
        "type": "object",
        "description": "A kill as lists, the feed and the stream show it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The kill's id: the recording's id and the death's sequence in it.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "cursor": {
            "type": "string",
            "description": "This kill's place in the feed. Pass it as `after` to `/v1/kills/feed`, or as `Last-Event-ID` to the stream, to continue after it."
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the ship died."
          },
          "listedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the kill became public: 5 minutes after it happened, or later for a kill added from an older recording."
          },
          "build": {
            "type": "string",
            "description": "The commit SHA of the game build that recorded the kill."
          },
          "zone": {
            "$ref": "#/components/schemas/KillZone"
          },
          "deathCause": {
            "type": "string",
            "description": "How the ship died, as the game names it: one of `/v1/death-causes`."
          },
          "victim": {
            "$ref": "#/components/schemas/Victim"
          },
          "value": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KillValue"
              },
              {
                "type": "null"
              }
            ],
            "description": "Null when the build that recorded the kill didn't keep the kill card."
          },
          "attackerCount": {
            "type": "integer",
            "description": "Pilots and NPCs that damaged the ship."
          },
          "playerAttackerCount": {
            "type": "integer",
            "description": "Pilots, other than the victim, that damaged the ship."
          },
          "isPvp": {
            "type": "boolean",
            "description": "Whether any pilot other than the victim damaged the ship."
          },
          "isSolo": {
            "type": "boolean",
            "description": "Whether exactly one attacker damaged the ship."
          },
          "finalBlow": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Party"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who landed the final blow, or null when nothing did (a ship lost to its reactor, say)."
          },
          "battleId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The battle the kill belongs to, or null for a lone kill.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "links": {
            "$ref": "#/components/schemas/KillLinks"
          }
        },
        "required": [
          "id",
          "cursor",
          "occurredAt",
          "listedAt",
          "build",
          "zone",
          "deathCause",
          "victim",
          "value",
          "attackerCount",
          "playerAttackerCount",
          "isPvp",
          "isSolo",
          "finalBlow",
          "battleId",
          "links"
        ]
      },
      "Attacker": {
        "type": "object",
        "properties": {
          "pilotId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pilot's id, or null for an NPC."
          },
          "name": {
            "type": "string",
            "description": "The pilot's name, or the NPC's."
          },
          "hull": {
            "$ref": "#/components/schemas/HullRef"
          },
          "buildRating": {
            "type": "integer",
            "description": "The attacker's build rating."
          },
          "damage": {
            "type": "number",
            "description": "Damage dealt to the ship, shields included."
          },
          "shieldDamage": {
            "type": "number",
            "description": "The part of `damage` dealt to shields."
          },
          "isFinalBlow": {
            "type": "boolean",
            "description": "Whether this attacker landed the final blow."
          }
        },
        "required": [
          "pilotId",
          "name",
          "hull",
          "buildRating",
          "damage",
          "shieldDamage",
          "isFinalBlow"
        ]
      },
      "ShipAffinityPoints": {
        "type": "object",
        "properties": {
          "moduleType": {
            "type": "string",
            "description": "The affinity, by module type."
          },
          "points": {
            "type": "integer",
            "description": "Points spent in it."
          }
        },
        "required": [
          "moduleType",
          "points"
        ]
      },
      "ShipAffinity": {
        "type": "object",
        "description": "The ship's level and affinity points.",
        "properties": {
          "level": {
            "type": "integer",
            "description": "The ship's level."
          },
          "maxLevel": {
            "type": "integer",
            "description": "The highest level the ship could reach."
          },
          "points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShipAffinityPoints"
            },
            "description": "The affinities holding any points."
          }
        },
        "required": [
          "level",
          "maxLevel",
          "points"
        ]
      },
      "ItemModifier": {
        "type": "object",
        "properties": {
          "stat": {
            "type": "string",
            "description": "The stat, by the game's name for it, as `/v1/stats` lists it."
          },
          "operation": {
            "type": "string",
            "description": "How the modifier applies, such as `PercentAdd`."
          },
          "tier": {
            "type": "integer",
            "description": "The modifier's tier."
          },
          "value": {
            "type": "number",
            "description": "The modifier's value."
          },
          "isFractured": {
            "type": "boolean",
            "description": "Whether the modifier is fractured."
          },
          "label": {
            "type": "string",
            "description": "The stat's name, as the game's item tooltip shows it."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The signed value as the game's item tooltip shows it, in the units its row reads in: `+5%` for a multiplier or a resistance, else the number, such as `+12`. The game also badges the row `T` and its `tier` when that is above 0, and draws a fractured one in the harmonic accent. Null for a stat whose row is its name alone (VENDOR LICENSE), or one the live build doesn't know."
          },
          "tone": {
            "type": "string",
            "enum": [
              "Positive",
              "Negative",
              "Neutral"
            ],
            "description": "Whether the modifier helps the ship (Positive), hurts it (Negative) or neither, as the game colours the row."
          }
        },
        "required": [
          "stat",
          "operation",
          "tier",
          "value",
          "isFractured",
          "label",
          "text",
          "tone"
        ]
      },
      "ItemPort": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer",
            "description": "The port's row in the module's unrotated 5x5 shape grid."
          },
          "col": {
            "type": "integer",
            "description": "The port's column in the same grid."
          },
          "direction": {
            "type": "string",
            "description": "Which side of its cell the port faces: Up, Down, Left or Right."
          },
          "state": {
            "type": "string",
            "description": "The port's state, as the game draws it."
          },
          "cipher": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the cipher in the port, which `/v1/ciphers` lists, or null.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "cipherArt": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The image of the cipher in the port as a full URL on https://art.thecitadel.com, or null."
          }
        },
        "required": [
          "row",
          "col",
          "direction",
          "state",
          "cipher",
          "cipherArt"
        ]
      },
      "ContainerItem": {
        "type": "object",
        "description": "An item in a fitting or cargo grid.",
        "properties": {
          "def": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's id, which `/v1/items/{id}` resolves for items players can still get. Null for a kill recorded before the killboard kept ids.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "name": {
            "type": "string",
            "description": "The item's name."
          },
          "art": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The item's image as a full URL on https://art.thecitadel.com, picked as the game picks it: the artifact's own icon, else the image its rarity has, else its base icon. `@2x` before `.webp` is the 256px one. Null when the live build doesn't have the item."
          },
          "category": {
            "type": "string",
            "description": "The item's category, such as Module or Resource."
          },
          "slotType": {
            "type": "string",
            "description": "The slot type the item takes."
          },
          "shape": {
            "type": "string",
            "description": "The item's shape."
          },
          "row": {
            "type": "integer",
            "description": "The row of the item's anchor cell."
          },
          "col": {
            "type": "integer",
            "description": "The column of the item's anchor cell."
          },
          "rotation": {
            "type": "integer",
            "description": "Quarter turns clockwise."
          },
          "rarity": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's rarity."
          },
          "quality": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's quality, or null when the recording didn't keep its roll."
          },
          "quantity": {
            "type": "integer",
            "description": "How many, for a stack."
          },
          "isDestroyed": {
            "type": "boolean",
            "description": "Whether the item was destroyed with the ship. An item that wasn't could be looted."
          },
          "artifact": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the item's artifact, which `/v1/artifacts` lists, or null.",
            "pattern": "^(0|-?[1-9][0-9]*)$"
          },
          "pointRating": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The item's rolled point rating, or null when the recording didn't keep its roll."
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemModifier"
            },
            "description": "The item's rolled modifiers. Empty when it has none or the recording didn't keep its roll."
          },
          "ports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemPort"
            }
          }
        },
        "required": [
          "def",
          "name",
          "art",
          "category",
          "slotType",
          "shape",
          "row",
          "col",
          "rotation",
          "rarity",
          "quality",
          "quantity",
          "isDestroyed",
          "artifact",
          "pointRating",
          "modifiers",
          "ports"
        ]
      },
      "Container": {
        "type": "object",
        "description": "A fitting or cargo grid and what was in it.",
        "properties": {
          "rows": {
            "type": "integer"
          },
          "columns": {
            "type": "integer"
          },
          "slots": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A slot type name, or None for a cell that isn't part of the grid."
            },
            "description": "Each cell's slot type, row by row, with rows x columns entries."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContainerItem"
            }
          }
        },
        "required": [
          "rows",
          "columns",
          "slots",
          "items"
        ]
      },
      "Kill": {
        "type": "object",
        "description": "One kill: its summary, the ship's fitting and cargo, and everyone who damaged it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The kill's id: the recording's id and the death's sequence in it.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "cursor": {
            "type": "string",
            "description": "This kill's place in the feed. Pass it as `after` to `/v1/kills/feed`, or as `Last-Event-ID` to the stream, to continue after it."
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the ship died."
          },
          "listedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the kill became public: 5 minutes after it happened, or later for a kill added from an older recording."
          },
          "build": {
            "type": "string",
            "description": "The commit SHA of the game build that recorded the kill."
          },
          "zone": {
            "$ref": "#/components/schemas/KillZone"
          },
          "deathCause": {
            "type": "string",
            "description": "How the ship died, as the game names it: one of `/v1/death-causes`."
          },
          "victim": {
            "$ref": "#/components/schemas/Victim"
          },
          "value": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KillValue"
              },
              {
                "type": "null"
              }
            ],
            "description": "Null when the build that recorded the kill didn't keep the kill card."
          },
          "attackerCount": {
            "type": "integer",
            "description": "Pilots and NPCs that damaged the ship."
          },
          "playerAttackerCount": {
            "type": "integer",
            "description": "Pilots, other than the victim, that damaged the ship."
          },
          "isPvp": {
            "type": "boolean",
            "description": "Whether any pilot other than the victim damaged the ship."
          },
          "isSolo": {
            "type": "boolean",
            "description": "Whether exactly one attacker damaged the ship."
          },
          "finalBlow": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Party"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who landed the final blow, or null when nothing did (a ship lost to its reactor, say)."
          },
          "battleId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The battle the kill belongs to, or null for a lone kill.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "links": {
            "$ref": "#/components/schemas/KillLinks"
          },
          "totalDamage": {
            "type": "number",
            "description": "All damage the ship took."
          },
          "affinity": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ShipAffinity"
              },
              {
                "type": "null"
              }
            ],
            "description": "Null when the recording didn't keep the kill card."
          },
          "fitting": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Container"
              },
              {
                "type": "null"
              }
            ],
            "description": "The ship's fitting grid, or null when the recording didn't keep the kill card."
          },
          "cargo": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Container"
              },
              {
                "type": "null"
              }
            ],
            "description": "The ship's cargo grid, or null when the recording didn't keep the kill card."
          },
          "attackers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attacker"
            },
            "description": "Everyone that damaged the ship, most damage first."
          }
        },
        "required": [
          "id",
          "cursor",
          "occurredAt",
          "listedAt",
          "build",
          "zone",
          "deathCause",
          "victim",
          "value",
          "attackerCount",
          "playerAttackerCount",
          "isPvp",
          "isSolo",
          "finalBlow",
          "battleId",
          "links",
          "totalDamage",
          "affinity",
          "fitting",
          "cargo",
          "attackers"
        ]
      },
      "KillPage": {
        "type": "object",
        "properties": {
          "kills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KillSummary"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass it as `cursor` for the next page, with the same filters and sort. Null on the last page."
          }
        },
        "required": [
          "kills",
          "nextCursor"
        ]
      },
      "FeedPage": {
        "type": "object",
        "properties": {
          "kills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KillSummary"
            },
            "description": "Kills in the order they became public, oldest first."
          },
          "cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass it as `after` on your next call. It is the last kill's cursor, or your `after` again when nothing new is public. Null only when there are no kills at all."
          }
        },
        "required": [
          "kills",
          "cursor"
        ]
      },
      "PilotCount": {
        "type": "object",
        "properties": {
          "pilotId": {
            "type": "string",
            "description": "The pilot's id."
          },
          "name": {
            "type": "string",
            "description": "The pilot's most recent name in these kills."
          },
          "hull": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/HullRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The hull the pilot flew most in these kills."
          },
          "count": {
            "type": "integer",
            "description": "How many kills: what is counted depends on the list."
          },
          "value": {
            "type": "integer",
            "description": "The ore value of the kills counted, where known."
          }
        },
        "required": [
          "pilotId",
          "name",
          "hull",
          "count",
          "value"
        ]
      },
      "HullCount": {
        "type": "object",
        "properties": {
          "hull": {
            "$ref": "#/components/schemas/HullRef"
          },
          "count": {
            "type": "integer",
            "description": "How many kills."
          }
        },
        "required": [
          "hull",
          "count"
        ]
      },
      "ZoneCount": {
        "type": "object",
        "properties": {
          "zone": {
            "$ref": "#/components/schemas/ZoneRef"
          },
          "count": {
            "type": "integer",
            "description": "How many kills."
          },
          "value": {
            "type": "integer",
            "description": "Their ore value, where known."
          }
        },
        "required": [
          "zone",
          "count",
          "value"
        ]
      },
      "KillTotals": {
        "type": "object",
        "properties": {
          "kills": {
            "type": "integer",
            "description": "Kills that match."
          },
          "valueDestroyed": {
            "type": "integer",
            "description": "Their ore value, where known."
          },
          "pilots": {
            "type": "integer",
            "description": "Different pilots who lost a ship."
          },
          "averageBuildRating": {
            "type": "integer",
            "description": "The lost ships' average build rating."
          },
          "pvpKills": {
            "type": "integer",
            "description": "Kills where another pilot dealt damage."
          },
          "topKillers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 10 pilots on the most of these kills; `count` is their kills."
          }
        },
        "required": [
          "kills",
          "valueDestroyed",
          "pilots",
          "averageBuildRating",
          "pvpKills",
          "topKillers"
        ]
      },
      "LostShip": {
        "type": "object",
        "properties": {
          "killId": {
            "type": "string",
            "description": "The kill.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "hull": {
            "$ref": "#/components/schemas/HullRef"
          }
        },
        "required": [
          "killId",
          "hull"
        ]
      },
      "BattleSummary": {
        "type": "object",
        "description": "Kills in one recording that each followed the last within 2 minutes.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The battle's id: its recording and its first kill's sequence.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The first kill."
          },
          "endedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The last kill."
          },
          "zone": {
            "$ref": "#/components/schemas/ZoneRef"
          },
          "killCount": {
            "type": "integer",
            "description": "Kills in the battle."
          },
          "valueDestroyed": {
            "type": "integer",
            "description": "Their ore value, where known."
          },
          "pilotCount": {
            "type": "integer",
            "description": "Pilots who lost a ship or dealt damage."
          },
          "lost": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LostShip"
            },
            "description": "Every ship lost, in order."
          },
          "attackerHulls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullRef"
            },
            "description": "Every hull, pilot or NPC, that dealt damage."
          }
        },
        "required": [
          "id",
          "startedAt",
          "endedAt",
          "zone",
          "killCount",
          "valueDestroyed",
          "pilotCount",
          "lost",
          "attackerHulls"
        ]
      },
      "BattlePilot": {
        "type": "object",
        "properties": {
          "pilotId": {
            "type": "string",
            "description": "The pilot's id."
          },
          "name": {
            "type": "string",
            "description": "The pilot's name."
          },
          "hulls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullRef"
            },
            "description": "The hulls the pilot flew in the battle."
          },
          "kills": {
            "type": "integer",
            "description": "Kills the pilot damaged."
          },
          "losses": {
            "type": "integer",
            "description": "Ships the pilot lost."
          },
          "damage": {
            "type": "number",
            "description": "Damage the pilot dealt to ships that died."
          },
          "valueLost": {
            "type": "integer",
            "description": "Ore value of the pilot's losses, where known."
          }
        },
        "required": [
          "pilotId",
          "name",
          "hulls",
          "kills",
          "losses",
          "damage",
          "valueLost"
        ]
      },
      "Battle": {
        "type": "object",
        "description": "One battle, its kills and every pilot in it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The battle's id: its recording and its first kill's sequence.",
            "pattern": "^[0-9]+:[0-9]+$"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The first kill."
          },
          "endedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The last kill."
          },
          "zone": {
            "$ref": "#/components/schemas/ZoneRef"
          },
          "killCount": {
            "type": "integer",
            "description": "Kills in the battle."
          },
          "valueDestroyed": {
            "type": "integer",
            "description": "Their ore value, where known."
          },
          "pilotCount": {
            "type": "integer",
            "description": "Pilots who lost a ship or dealt damage."
          },
          "lost": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LostShip"
            },
            "description": "Every ship lost, in order."
          },
          "attackerHulls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullRef"
            },
            "description": "Every hull, pilot or NPC, that dealt damage."
          },
          "kills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KillSummary"
            },
            "description": "The battle's kills, in order."
          },
          "pilots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BattlePilot"
            },
            "description": "Every pilot in the battle, most kills first."
          }
        },
        "required": [
          "id",
          "startedAt",
          "endedAt",
          "zone",
          "killCount",
          "valueDestroyed",
          "pilotCount",
          "lost",
          "attackerHulls",
          "kills",
          "pilots"
        ]
      },
      "BattlePage": {
        "type": "object",
        "properties": {
          "battles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BattleSummary"
            },
            "description": "Newest first."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass it as `cursor` for the next page. Null on the last page."
          }
        },
        "required": [
          "battles",
          "nextCursor"
        ]
      },
      "Pilot": {
        "type": "object",
        "description": "A pilot's record on the killboard.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The pilot's id."
          },
          "name": {
            "type": "string",
            "description": "The pilot's most recent name."
          },
          "kills": {
            "type": "integer",
            "description": "Other pilots' ships this pilot damaged before they died."
          },
          "finalBlows": {
            "type": "integer",
            "description": "Final blows this pilot landed."
          },
          "losses": {
            "type": "integer",
            "description": "Ships this pilot lost."
          },
          "valueDestroyed": {
            "type": "integer",
            "description": "Ore value of the ships counted in `kills`, where known."
          },
          "valueLost": {
            "type": "integer",
            "description": "Ore value of the pilot's losses, where known."
          },
          "efficiency": {
            "type": [
              "number",
              "null"
            ],
            "description": "`valueDestroyed` over both values, from 0 to 1, or null when both are 0."
          },
          "nemeses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 5 pilots who killed this pilot most; `count` is how often."
          },
          "victims": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 5 pilots this pilot killed most; `count` is how often."
          },
          "hullsLost": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullCount"
            },
            "description": "The 5 hulls this pilot lost most."
          },
          "hullsFlown": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullCount"
            },
            "description": "The 5 hulls this pilot flew most when dealing damage."
          }
        },
        "required": [
          "id",
          "name",
          "kills",
          "finalBlows",
          "losses",
          "valueDestroyed",
          "valueLost",
          "efficiency",
          "nemeses",
          "victims",
          "hullsLost",
          "hullsFlown"
        ]
      },
      "Leaderboards": {
        "type": "object",
        "properties": {
          "window": {
            "type": "string",
            "enum": [
              "week",
              "month",
              "all"
            ],
            "description": "The last 7 days, the last 30, or all time."
          },
          "topKillers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 10 pilots on the most kills; `count` is kills."
          },
          "topFinalBlows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 10 pilots with the most final blows; `count` is final blows."
          },
          "topDestroyers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PilotCount"
            },
            "description": "The 10 pilots who destroyed the most ore value; `count` is kills."
          },
          "biggestLosses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KillSummary"
            },
            "description": "The 10 most valuable ships lost."
          },
          "deadliestZones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ZoneCount"
            },
            "description": "The 10 zones with the most kills."
          },
          "deadliestHulls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HullCount"
            },
            "description": "The 10 hulls pilots killed with most."
          }
        },
        "required": [
          "window",
          "topKillers",
          "topFinalBlows",
          "topDestroyers",
          "biggestLosses",
          "deadliestZones",
          "deadliestHulls"
        ]
      }
    },
    "headers": {
      "Build": {
        "description": "The commit SHA of the build that answered.",
        "schema": {
          "type": "string"
        }
      },
      "ETag": {
        "description": "A strong ETag: the SHA-256 of the response body, or the file name for art. Send it back in `If-None-Match`.",
        "schema": {
          "type": "string"
        }
      },
      "CacheControl": {
        "description": "How long a response may be reused.",
        "schema": {
          "type": "string"
        }
      },
      "Warning": {
        "description": "Sent when the request has no User-Agent or a generic one, with the value `299 - \"Send a User-Agent naming your app and a contact\"`. The request is still served.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Whole seconds to wait before retrying.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "CORS": {
        "description": "Always `*`. The API doesn't use credentials.",
        "schema": {
          "type": "string",
          "const": "*"
        }
      }
    },
    "parameters": {
      "ItemId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "An item id: an asset GUID as a decimal string, with no plus sign or leading zeros, that fits in a signed 64-bit integer. Anything else gets a 400.",
        "schema": {
          "type": "string",
          "pattern": "^(0|-?[1-9][0-9]*)$"
        }
      },
      "HullId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "A hull id: an asset GUID as a decimal string, with no plus sign or leading zeros, that fits in a signed 64-bit integer. Anything else gets a 400.",
        "schema": {
          "type": "string",
          "pattern": "^(0|-?[1-9][0-9]*)$"
        }
      },
      "ArtFile": {
        "name": "file",
        "in": "path",
        "required": true,
        "description": "A file name taken from an art URL: lower-case letters, digits and `.` `@` `_` `-`, ending in `.webp`.",
        "schema": {
          "type": "string",
          "pattern": "^[a-z0-9.@_-]+\\.webp$"
        }
      },
      "IfNoneMatch": {
        "name": "If-None-Match",
        "in": "header",
        "required": false,
        "description": "An ETag from an earlier response. If it still matches, you get a 304.",
        "schema": {
          "type": "string"
        }
      },
      "KillZone": {
        "name": "zone",
        "in": "query",
        "required": false,
        "description": "Only kills in this zone, by name, such as `CHARTER'S REACH`.",
        "schema": {
          "type": "string"
        }
      },
      "KillZoneId": {
        "name": "zoneId",
        "in": "query",
        "required": false,
        "description": "Only kills in this zone, by id, as `/v1/zones` lists them. Prefer it to `zone`: names aren't unique.",
        "schema": {
          "type": "string"
        }
      },
      "KillTier": {
        "name": "tier",
        "in": "query",
        "required": false,
        "description": "Only kills at this breach tier.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "KillHull": {
        "name": "hull",
        "in": "query",
        "required": false,
        "description": "Only ships of this hull, by id, as `/v1/hulls` lists them.",
        "schema": {
          "type": "string",
          "pattern": "^(0|-?[1-9][0-9]*)$"
        }
      },
      "KillHullName": {
        "name": "hullName",
        "in": "query",
        "required": false,
        "description": "Only ships of this hull, by name, such as `SERAPH`. Use it for kills recorded before the killboard kept ids.",
        "schema": {
          "type": "string"
        }
      },
      "KillClass": {
        "name": "class",
        "in": "query",
        "required": false,
        "description": "Only hulls of this class, such as `Cruiser`.",
        "schema": {
          "type": "string"
        }
      },
      "KillCause": {
        "name": "cause",
        "in": "query",
        "required": false,
        "description": "Only deaths with this cause, such as `ReconnectLoss`.",
        "schema": {
          "type": "string"
        }
      },
      "KillPilot": {
        "name": "pilot",
        "in": "query",
        "required": false,
        "description": "Only kills this pilot lost a ship in or damaged a ship in.",
        "schema": {
          "type": "string"
        }
      },
      "KillKind": {
        "name": "kind",
        "in": "query",
        "required": false,
        "description": "`pvp`: another pilot dealt damage. `pve`: only NPCs did.",
        "schema": {
          "type": "string",
          "enum": [
            "pvp",
            "pve"
          ]
        }
      },
      "KillSize": {
        "name": "size",
        "in": "query",
        "required": false,
        "description": "`solo`: one attacker. `gang`: more than one.",
        "schema": {
          "type": "string",
          "enum": [
            "solo",
            "gang"
          ]
        }
      },
      "KillBrMin": {
        "name": "brMin",
        "in": "query",
        "required": false,
        "description": "Only ships with at least this build rating.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "KillBrMax": {
        "name": "brMax",
        "in": "query",
        "required": false,
        "description": "Only ships with at most this build rating.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "KillValueMin": {
        "name": "valueMin",
        "in": "query",
        "required": false,
        "description": "Only kills worth at least this much ore. Kills of unknown value never match.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "KillValueMax": {
        "name": "valueMax",
        "in": "query",
        "required": false,
        "description": "Only kills worth at most this much ore. Kills of unknown value never match.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "KillFrom": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "Only kills on or after this day (UTC).",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "KillTo": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "Only kills on or before this day (UTC).",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "KillId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "A kill id, such as `48213:7`.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]+:[0-9]+$",
          "example": "48213:7"
        }
      },
      "BattleId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "A battle id, such as `48213:5`.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]+:[0-9]+$",
          "example": "48213:5"
        }
      },
      "PilotId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "A pilot id, as kills give it.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Something in the request is malformed: the id, the body or the file name. Code `bad_request`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "NotFound": {
        "description": "Nothing has that id, or the route doesn't exist. Code `not_found`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "TooLarge": {
        "description": "The body is over 256 KB. Code `too_large`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "RateLimited": {
        "description": "This client has used up its rate limit. Wait `Retry-After` seconds. Code `rate_limited`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Starting": {
        "description": "The API is still starting up. Code `starting`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Internal": {
        "description": "Something failed unexpectedly. Code `internal`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "The route doesn't take this method; `Allow` lists the ones it does. Code `bad_request`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          },
          "Allow": {
            "description": "The methods the route takes.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "The body isn't sent as `application/json`. Code `bad_request`.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "NotModified": {
        "description": "The `If-None-Match` tag still matches, so no body is sent.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          }
        }
      },
      "KillsUnavailable": {
        "description": "The killboard can't be read right now (code `unavailable`), or the API is still starting up (code `starting`). Retry shortly.",
        "headers": {
          "X-Citadel-Build": {
            "$ref": "#/components/headers/Build"
          },
          "Access-Control-Allow-Origin": {
            "$ref": "#/components/headers/CORS"
          },
          "Warning": {
            "$ref": "#/components/headers/Warning"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      }
    }
  }
}
