{
  "openapi": "3.0.0",
  "paths": {
    "/api/v1/health": {
      "get": {
        "operationId": "HealthController_check",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponseDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Liveness check",
        "tags": [
          "health"
        ]
      }
    },
    "/api/v1/vin/generate": {
      "get": {
        "description": "Every VIN is structurally valid and decodes correctly, and its randomised serial is not taken from any real-vehicle record. A random serial can still coincide with a real VIN by chance, so never present a generated VIN as a real vehicle identifier.",
        "operationId": "VinController_generate",
        "parameters": [
          {
            "name": "count",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 1,
              "type": "integer"
            }
          },
          {
            "name": "majorOnly",
            "required": false,
            "in": "query",
            "description": "Draw only from the curated major makes. Ignored when an explicit `make` is supplied.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "make",
            "required": false,
            "in": "query",
            "description": "One make, or several. Repeat the parameter to name more than one — `?make=Ford&make=Toyota` returns either. Makes combine as OR with each other and as AND with every other filter. Makes come from NHTSA’s VPIC database, which covers US-market vehicles only.",
            "schema": {
              "maxItems": 25,
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 64
              }
            }
          },
          {
            "name": "model",
            "required": false,
            "in": "query",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "name": "year",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1900,
              "maximum": 2100,
              "type": "integer"
            }
          },
          {
            "name": "bodyStyle",
            "required": false,
            "in": "query",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "name": "fuelType",
            "required": false,
            "in": "query",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "name": "seed",
            "required": false,
            "in": "query",
            "description": "Any string or integer. The same seed returns the same batch.",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Generated VINs, each with its decode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "The filter combination is well formed but matches no vehicle in the dataset. `details.filters` echoes what was applied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "500": {
            "description": "An unexpected failure. The body carries no internal detail and no stack trace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Generate synthetic VINs",
        "tags": [
          "vin"
        ]
      }
    },
    "/api/v1/vin/validate/{vin}": {
      "get": {
        "description": "Pure arithmetic — this endpoint does not consult the VPIC database.",
        "operationId": "VinController_validate",
        "parameters": [
          {
            "name": "vin",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Always 200, including for input that is not a VIN — knowing *why* a VIN is wrong is the useful part.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateResultDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Check a VIN’s structure and check digit",
        "tags": [
          "vin"
        ]
      }
    },
    "/api/v1/vin/decode/{vin}": {
      "get": {
        "operationId": "VinController_decodeOne",
        "parameters": [
          {
            "name": "vin",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A structurally valid but undecodable VIN is still a 200, carrying everything derivable plus `errors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecodeResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "500": {
            "description": "An unexpected failure. The body carries no internal detail and no stack trace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Decode a single VIN, with NCIC codes",
        "tags": [
          "vin"
        ]
      }
    },
    "/api/v1/vin/decode": {
      "post": {
        "operationId": "VinController_decodeBatch",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DecodeBatchDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One entry per submitted VIN, in order. A malformed or failing entry gets a rejection entry of the same shape rather than failing the request, so this route has no 500.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecodeBatchResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeded the byte limit, which `details.limitBytes` states exactly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Decode up to 100 VINs",
        "tags": [
          "vin"
        ]
      }
    },
    "/api/v1/reference/makes": {
      "get": {
        "description": "Counts let a caller avoid offering a filter that would match nothing. For a sparse field the counts sum to less than the dataset size.",
        "operationId": "ReferenceController_makes",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "How many items to return. Omit for the whole list. When either `limit` or `offset` is given, `meta.total` reports the number of items before the page was taken.",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "How many items to skip before the page. Omit for the whole list.",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "name": "majorOnly",
            "required": false,
            "in": "query",
            "description": "Return only the curated major makes rather than all of them. Counts and `meta.skeletonCount` are unchanged.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MakesResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Makes available to generate, with a count each",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/reference/models": {
      "get": {
        "operationId": "ReferenceController_models",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "How many items to return. Omit for the whole list. When either `limit` or `offset` is given, `meta.total` reports the number of items before the page was taken.",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "How many items to skip before the page. Omit for the whole list.",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "name": "make",
            "required": true,
            "in": "query",
            "description": "The make to list models for.",
            "schema": {
              "maxLength": 64,
              "example": "Tesla",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelCollectionDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "The make is not in the dataset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Models available for a make",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/reference/years": {
      "get": {
        "operationId": "ReferenceController_years",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/YearCollectionDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Model years available, ascending",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/reference/body-styles": {
      "get": {
        "operationId": "ReferenceController_bodyStyles",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValueCountCollectionDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Body styles available, with counts",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/reference/fuel-types": {
      "get": {
        "operationId": "ReferenceController_fuelTypes",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValueCountCollectionDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Fuel types available, with counts",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/reference/wmi/{wmi}": {
      "get": {
        "operationId": "ReferenceController_wmi",
        "parameters": [
          {
            "name": "wmi",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WmiSummaryDto"
                }
              }
            }
          },
          "404": {
            "description": "No skeleton in the dataset carries this WMI.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "World Manufacturer Identifier summary",
        "tags": [
          "reference"
        ]
      }
    },
    "/api/v1/ncic/makes": {
      "get": {
        "operationId": "NcicController_makes",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "How many items to return. Omit for the whole list. When either `limit` or `offset` is given, `meta.total` reports the number of items before the page was taken.",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "How many items to skip before the page. Omit for the whole list.",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Case-insensitive substring of the code or the name.",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NcicCollectionDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "NCIC vehicle make codes (NIEM 6.0)",
        "tags": [
          "ncic"
        ]
      }
    },
    "/api/v1/ncic/colors": {
      "get": {
        "operationId": "NcicController_colors",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "How many items to return. Omit for the whole list. When either `limit` or `offset` is given, `meta.total` reports the number of items before the page was taken.",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "How many items to skip before the page. Omit for the whole list.",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Case-insensitive substring of the code or the name.",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NcicCollectionDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "NCIC vehicle colour codes",
        "tags": [
          "ncic"
        ]
      }
    },
    "/api/v1/ncic/styles": {
      "get": {
        "description": "Codes retired by the NCIC 2000 Code Manual in 2002 are flagged `retired: true`. They remain in the NIEM dataset for reference but must not be written to a title or registration.",
        "operationId": "NcicController_styles",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "How many items to return. Omit for the whole list. When either `limit` or `offset` is given, `meta.total` reports the number of items before the page was taken.",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "How many items to skip before the page. Omit for the whole list.",
            "schema": {
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Case-insensitive substring of the code or the name.",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NcicCollectionDto"
                }
              }
            }
          },
          "400": {
            "description": "Malformed input. `details.violations` lists the per-field messages, one string each.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "NCIC vehicle style codes",
        "tags": [
          "ncic"
        ]
      }
    },
    "/api/v1/ncic/make/{nameOrCode}": {
      "get": {
        "operationId": "NcicController_make",
        "parameters": [
          {
            "name": "nameOrCode",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NcicMakeDto"
                }
              }
            }
          },
          "404": {
            "description": "Neither an NCIC make code nor a make name matched.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` are all set on this response, and all four are exposed through CORS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorDto"
                }
              }
            }
          }
        },
        "summary": "Resolve a make in either direction",
        "tags": [
          "ncic"
        ]
      }
    }
  },
  "info": {
    "title": "VIN Foundry API",
    "description": "Free, keyless VIN generation and decoding. Generated VINs are synthetic: each uses a real manufacturer prefix with a randomised serial, so it is structurally valid and decodes correctly, and none is taken from a real-vehicle record. A random serial can still coincide with a real VIN by chance, so never present a generated VIN as a real vehicle identifier.",
    "version": "1.0",
    "contact": {}
  },
  "tags": [
    {
      "name": "vin",
      "description": "Generate, decode and validate VINs"
    },
    {
      "name": "reference",
      "description": "What the dataset covers"
    },
    {
      "name": "ncic",
      "description": "NCIC code lookups (NIEM 6.0)"
    },
    {
      "name": "health",
      "description": "Liveness"
    }
  ],
  "servers": [],
  "components": {
    "schemas": {
      "HealthResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "ok"
          }
        },
        "required": [
          "status"
        ]
      },
      "ApiErrorDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "integer",
            "example": 429,
            "description": "The HTTP status, repeated here so a logged body is self-contained."
          },
          "error": {
            "type": "string",
            "example": "Too Many Requests",
            "description": "The standard HTTP reason phrase for `statusCode`. Never an internal class name."
          },
          "message": {
            "type": "string",
            "example": "Rate limit exceeded. Retry in 60 seconds.",
            "description": "One human-readable sentence. Always a string, never an array."
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "example": {},
            "description": "Structured specifics for this status: `violations` (an array of strings) on a validation 400, `filters` on a no-match 404, `limitBytes` on a 413. An empty object when there is nothing to add — the key is always present."
          }
        },
        "required": [
          "statusCode",
          "error",
          "message",
          "details"
        ]
      },
      "CheckDigitDto": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "Whether `actual` matches `expected`."
          },
          "actual": {
            "type": "string",
            "nullable": true,
            "description": "The character at VIN position 9, or null if there is none."
          },
          "expected": {
            "type": "string",
            "nullable": true,
            "description": "What 49 CFR 565.15 says belongs at position 9, or null when the input is not structurally a VIN and no digit is derivable."
          }
        },
        "required": [
          "valid",
          "actual",
          "expected"
        ]
      },
      "NcicCodesDto": {
        "type": "object",
        "properties": {
          "make": {
            "type": "string",
            "nullable": true,
            "example": "TESL"
          },
          "color": {
            "type": "string",
            "nullable": true,
            "description": "Always null here — a VIN does not encode colour."
          },
          "style": {
            "type": "string",
            "nullable": true,
            "example": "LL"
          }
        },
        "required": [
          "make",
          "color",
          "style"
        ]
      },
      "GeneratedVinDto": {
        "type": "object",
        "properties": {
          "vin": {
            "type": "string",
            "example": "5YJ3A1EA8RF123456",
            "description": "A synthetic 17-character VIN."
          },
          "wmiCode": {
            "type": "string",
            "example": "5YJ",
            "description": "The VIN's first three characters — the World Manufacturer Identifier, as a bare string. Named apart from decode's rich `wmi` object so one name never means two types."
          },
          "make": {
            "type": "string",
            "example": "Tesla"
          },
          "model": {
            "type": "string",
            "example": "Model 3"
          },
          "year": {
            "type": "integer",
            "example": 2024
          },
          "manufacturer": {
            "type": "string",
            "example": "TESLA, INC."
          },
          "vehicleType": {
            "type": "string",
            "example": "Passenger Car"
          },
          "bodyStyle": {
            "type": "string",
            "nullable": true,
            "example": "Hatchback"
          },
          "fuelType": {
            "type": "string",
            "nullable": true,
            "example": "Electric"
          },
          "trim": {
            "type": "string",
            "nullable": true
          },
          "doors": {
            "type": "string",
            "nullable": true,
            "example": "5"
          },
          "gvwr": {
            "type": "string",
            "nullable": true
          },
          "plantCity": {
            "type": "string",
            "nullable": true,
            "example": "FREMONT"
          },
          "plantCountry": {
            "type": "string",
            "nullable": true,
            "example": "UNITED STATES (USA)"
          },
          "checkDigit": {
            "$ref": "#/components/schemas/CheckDigitDto"
          },
          "ncic": {
            "$ref": "#/components/schemas/NcicCodesDto"
          },
          "synthetic": {
            "type": "boolean",
            "example": true,
            "description": "Always true. The serial is randomised rather than taken from any real-vehicle record. A random serial can still coincide with a real VIN by chance, so never present this as a real vehicle identifier."
          }
        },
        "required": [
          "vin",
          "wmiCode",
          "make",
          "model",
          "year",
          "manufacturer",
          "vehicleType",
          "bodyStyle",
          "fuelType",
          "trim",
          "doors",
          "gvwr",
          "plantCity",
          "plantCountry",
          "checkDigit",
          "ncic",
          "synthetic"
        ]
      },
      "CountMetaDto": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The number of items in `data`."
          }
        },
        "required": [
          "count"
        ]
      },
      "GenerateResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GeneratedVinDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/CountMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "ValidateResultDto": {
        "type": "object",
        "properties": {
          "vin": {
            "type": "string",
            "description": "The input, normalised and truncated to 32 characters."
          },
          "valid": {
            "type": "boolean",
            "description": "Structurally valid **and** the check digit matches."
          },
          "structurallyValid": {
            "type": "boolean",
            "description": "17 characters drawn from the VIN alphabet (never I, O or Q)."
          },
          "checkDigit": {
            "$ref": "#/components/schemas/CheckDigitDto"
          },
          "modelYear": {
            "type": "integer",
            "nullable": true,
            "example": 1989
          },
          "region": {
            "type": "string",
            "nullable": true,
            "example": "North America"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "United States"
          }
        },
        "required": [
          "vin",
          "valid",
          "structurallyValid",
          "checkDigit",
          "modelYear",
          "region",
          "country"
        ]
      },
      "DecodeResultDto": {
        "type": "object",
        "properties": {
          "vin": {
            "type": "string",
            "example": "5UXFA13564LU32275",
            "description": "Normalised: upper-cased, trimmed."
          },
          "wmiCode": {
            "type": "string",
            "example": "5UX",
            "description": "The VIN's first three characters."
          },
          "decoded": {
            "type": "boolean",
            "description": "Whether a VPIC pattern matched. A false here still returns everything derivable from the VIN itself."
          },
          "checkDigit": {
            "$ref": "#/components/schemas/CheckDigitDto"
          },
          "modelYear": {
            "type": "integer",
            "nullable": true,
            "example": 2004
          },
          "region": {
            "type": "string",
            "nullable": true,
            "example": "North America"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "United States"
          },
          "vehicle": {
            "type": "object",
            "additionalProperties": true,
            "description": "The decoder's vehicle block. Empty when nothing decoded."
          },
          "wmi": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "The decoder's rich WMI block, or null. The bare string is `wmiCode`."
          },
          "plant": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "ncic": {
            "$ref": "#/components/schemas/NcicCodesDto"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Structured decode problems. A malformed batch entry carries `{code: \"malformed\", message}` here rather than failing the whole request."
          }
        },
        "required": [
          "vin",
          "wmiCode",
          "decoded",
          "checkDigit",
          "modelYear",
          "region",
          "country",
          "vehicle",
          "wmi",
          "plant",
          "ncic",
          "errors"
        ]
      },
      "DecodeBatchDto": {
        "type": "object",
        "properties": {
          "vins": {
            "maxItems": 100,
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "vins"
        ]
      },
      "DecodeBatchResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "One entry per submitted VIN, in the order submitted.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DecodeResultDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/CountMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "ValueCountDto": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "example": "Tesla"
          },
          "count": {
            "type": "integer",
            "example": 1284
          }
        },
        "required": [
          "value",
          "count"
        ]
      },
      "MakesMetaDto": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The number of items in `data`."
          },
          "total": {
            "type": "integer",
            "description": "The number of items before the page was taken. Present only when `limit` or `offset` was given."
          },
          "skeletonCount": {
            "type": "integer",
            "description": "Skeletons in the whole dataset — a different quantity from `count`, which is the number of makes listed."
          }
        },
        "required": [
          "count",
          "skeletonCount"
        ]
      },
      "MakesResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValueCountDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/MakesMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "PagedMetaDto": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The number of items in `data`."
          },
          "total": {
            "type": "integer",
            "description": "The number of items before the page was taken. Present only when `limit` or `offset` was given."
          }
        },
        "required": [
          "count"
        ]
      },
      "ModelCollectionDto": {
        "type": "object",
        "properties": {
          "data": {
            "example": [
              "Model 3",
              "Model S"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/PagedMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "YearCollectionDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "example": [
              1980,
              1981,
              1982
            ]
          },
          "meta": {
            "$ref": "#/components/schemas/CountMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "ValueCountCollectionDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValueCountDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/CountMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "WmiSummaryDto": {
        "type": "object",
        "properties": {
          "wmi": {
            "type": "string",
            "example": "5YJ"
          },
          "makes": {
            "example": [
              "Tesla"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "manufacturers": {
            "example": [
              "TESLA, INC."
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "vehicleTypes": {
            "example": [
              "Passenger Car"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "yearFrom": {
            "type": "integer",
            "example": 2012
          },
          "yearTo": {
            "type": "integer",
            "example": 2027
          },
          "skeletonCount": {
            "type": "integer",
            "description": "Skeletons in the dataset under this WMI."
          }
        },
        "required": [
          "wmi",
          "makes",
          "manufacturers",
          "vehicleTypes",
          "yearFrom",
          "yearTo",
          "skeletonCount"
        ]
      },
      "NcicCodeEntryDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "TOYT"
          },
          "name": {
            "type": "string",
            "example": "Toyota"
          },
          "retired": {
            "type": "boolean",
            "description": "Only on `/ncic/styles`. True for codes the NCIC 2000 Code Manual retired in 2002: still in the NIEM dataset for reference, but they must not be written to a title or registration."
          }
        },
        "required": [
          "code",
          "name"
        ]
      },
      "NcicCollectionDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Sorted by code.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NcicCodeEntryDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/PagedMetaDto"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "NcicMakeDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "TOYT"
          },
          "name": {
            "type": "string",
            "example": "Toyota"
          }
        },
        "required": [
          "code",
          "name"
        ]
      }
    }
  }
}
