{
  "openapi": "3.0.3",
  "info": {
    "title": "Bike Reliability — UK Motorcycle MOT Reliability API",
    "description": "Free, read-only JSON API for UK motorcycle reliability statistics: every make and model ranked by real first-time MOT pass rates, with common failure areas. Derived from the DVSA anonymised MOT results dataset (classes 1 & 2). Free to use: keyless calls are limited to 50 requests/day per IP; a free API key (sent in the X-Api-Key header) lifts the daily limit into the thousands. Keys are free and issued to sites that show a visible dofollow link back to bikereliability.co.uk — request one at https://bikereliability.co.uk/developers. Statistics are CC BY 4.0 — please credit \"Bike Reliability\" and link to bikereliability.co.uk. Human docs: https://bikereliability.co.uk/developers",
    "version": "1.0.0",
    "contact": { "name": "Bike Reliability", "url": "https://bikereliability.co.uk/developers" },
    "license": { "name": "CC BY 4.0 (statistics); source data OGL v3.0 (DVSA)", "url": "https://creativecommons.org/licenses/by/4.0/" }
  },
  "servers": [{ "url": "https://bikereliability.co.uk/api/v1", "description": "Production" }],
  "tags": [{ "name": "Makes" }, { "name": "Models" }],
  "paths": {
    "/makes": {
      "get": {
        "tags": ["Makes"],
        "summary": "Make league table — every make ranked by first-time MOT pass rate",
        "parameters": [
          { "name": "min_tests", "in": "query", "schema": { "type": "integer", "default": 1000, "minimum": 100 }, "description": "Minimum MOT tests for a make to qualify (guards against tiny-sample noise)." }
        ],
        "responses": {
          "200": {
            "description": "Makes ranked by pass rate.",
            "content": { "application/json": { "schema": {
              "allOf": [
                { "$ref": "#/components/schemas/Envelope" },
                { "type": "object", "properties": { "count": { "type": "integer" }, "makes": { "type": "array", "items": { "$ref": "#/components/schemas/MakeRow" } } } }
              ]
            } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/makes/{slug}": {
      "get": {
        "tags": ["Makes"],
        "summary": "One make — pass rate, rank, common failure areas, and its models",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Make slug, e.g. honda." }],
        "responses": {
          "200": {
            "description": "The make with rank, failure areas and per-model breakdown.",
            "content": { "application/json": { "schema": {
              "allOf": [
                { "$ref": "#/components/schemas/Envelope" },
                { "type": "object", "properties": { "make": { "$ref": "#/components/schemas/MakeDetail" } } }
              ]
            } } }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/models/{makeSlug}/{modelSlug}": {
      "get": {
        "tags": ["Models"],
        "summary": "One model — pass rate, ranks (overall / within make / by type), common failures",
        "parameters": [
          { "name": "makeSlug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "modelSlug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "The model detail.",
            "content": { "application/json": { "schema": {
              "allOf": [
                { "$ref": "#/components/schemas/Envelope" },
                { "type": "object", "properties": { "model": { "$ref": "#/components/schemas/ModelDetail" } } }
              ]
            } } }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "responses": {
      "NotFound": { "description": "No matching record.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": {
        "description": "Rate limit exceeded. Keyless callers get 50 requests/day per IP; send a free API key in the X-Api-Key header for a much higher daily limit.",
        "headers": { "Retry-After": { "schema": { "type": "integer" } } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Optional free API key. Keyless is 50 requests/day per IP; a key lifts the daily limit into the thousands. Keys are free and issued to sites showing a visible dofollow link back to bikereliability.co.uk — request one at https://bikereliability.co.uk/developers."
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "properties": {
          "dataset": { "type": "string" },
          "api_version": { "type": "string", "example": "v1" },
          "licence": { "type": "string" },
          "source": { "type": "string", "format": "uri" },
          "attribution": { "type": "string" },
          "period": { "type": "string", "example": "2005–2025" }
        }
      },
      "MakeRow": {
        "type": "object",
        "properties": {
          "rank": { "type": "integer" },
          "make": { "type": "string" },
          "slug": { "type": "string" },
          "tests": { "type": "integer" },
          "pass_pct": { "type": "number" },
          "advisory_pct": { "type": "number", "description": "Pass after rectification at station (PRS)." },
          "fail_pct": { "type": "number" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "MakeDetail": {
        "type": "object",
        "properties": {
          "make": { "type": "string" },
          "slug": { "type": "string" },
          "tests": { "type": "integer" },
          "pass_pct": { "type": "number" },
          "advisory_pct": { "type": "number" },
          "fail_pct": { "type": "number" },
          "rank": { "type": "object", "nullable": true, "properties": { "position": { "type": "integer" }, "of": { "type": "integer" } } },
          "common_failures": { "type": "array", "items": { "$ref": "#/components/schemas/Failure" } },
          "models": { "type": "array", "items": { "type": "object", "properties": {
            "model": { "type": "string" }, "slug": { "type": "string" }, "tests": { "type": "integer" },
            "pass_pct": { "type": "number" }, "url": { "type": "string", "format": "uri" } } } },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "ModelDetail": {
        "type": "object",
        "properties": {
          "make": { "type": "string" },
          "make_slug": { "type": "string" },
          "model": { "type": "string" },
          "model_slug": { "type": "string" },
          "tests": { "type": "integer" },
          "pass_pct": { "type": "number" },
          "advisory_pct": { "type": "number" },
          "fail_pct": { "type": "number" },
          "median_mileage": { "type": "number", "nullable": true },
          "cc": { "type": "number", "nullable": true },
          "ranks": {
            "type": "object",
            "nullable": true,
            "properties": {
              "overall": { "type": "object", "properties": { "position": { "type": "integer" }, "of": { "type": "integer" } } },
              "within_make": { "type": "object", "properties": { "position": { "type": "integer" }, "of": { "type": "integer" } } },
              "type": { "type": "object", "nullable": true, "properties": { "name": { "type": "string" }, "position": { "type": "integer" }, "of": { "type": "integer" } } }
            }
          },
          "common_failures": { "type": "array", "items": { "$ref": "#/components/schemas/Failure" } },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "Failure": {
        "type": "object",
        "properties": {
          "area": { "type": "string", "example": "Brakes" },
          "defects": { "type": "integer" },
          "tests_with_defect": { "type": "integer" }
        }
      },
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string", "example": "not_found" }, "message": { "type": "string" } }
      }
    }
  }
}
