{
 "openapi": "3.0.3",
 "info": {
  "title": "MotorcycleDB API",
  "version": "1.1.0",
  "description": "Read-only motorcycle specifications, recalls and VIN decoding. Docs: https://www.motorcycledb.com/api/docs.php - Terms: https://www.motorcycledb.com/api/terms.php"
 },
 "servers": [
  {
   "url": "https://www.motorcycledb.com/api/v1"
  }
 ],
 "security": [
  {
   "bearer": []
  },
  {
   "apiKey": []
  }
 ],
 "paths": {
  "/bikes": {
   "get": {
    "summary": "Search and list bikes",
    "operationId": "listBikes",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Free-text make + model search; ignores spaces and hyphens (mt09 finds MT-09). A model year, seat height ('under 750mm seat'), engine size ('over 600cc') or a lone category ('naked 2024') in q fills that filter when it isn't set; meta.interpreted shows what was taken out.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "make",
      "in": "query",
      "required": false,
      "description": "Manufacturer. Exact name (case-insensitive) if one exists, otherwise partial: Harley finds Harley-Davidson",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "model",
      "in": "query",
      "required": false,
      "description": "Model name, partial; ignores spaces and hyphens",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "year",
      "in": "query",
      "required": false,
      "description": "Exact model year",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "year_min",
      "in": "query",
      "required": false,
      "description": "Earliest model year",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "year_max",
      "in": "query",
      "required": false,
      "description": "Latest model year",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "category",
      "in": "query",
      "required": false,
      "description": "Category name, case-insensitive; see /categories",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "powertrain",
      "in": "query",
      "required": false,
      "description": "ice or electric",
      "schema": {
       "type": "string",
       "enum": [
        "ice",
        "electric"
       ]
      }
     },
     {
      "name": "cc_min",
      "in": "query",
      "required": false,
      "description": "Minimum capacity, cc",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "cc_max",
      "in": "query",
      "required": false,
      "description": "Maximum capacity, cc",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "hp_min",
      "in": "query",
      "required": false,
      "description": "Minimum power, hp",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "hp_max",
      "in": "query",
      "required": false,
      "description": "Maximum power, hp",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "abs",
      "in": "query",
      "required": false,
      "description": "true = ABS fitted as standard",
      "schema": {
       "type": "string",
       "enum": [
        "true"
       ]
      }
     },
     {
      "name": "seat_height_max",
      "in": "query",
      "required": false,
      "description": "Maximum seat height, mm",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "seat_height_min",
      "in": "query",
      "required": false,
      "description": "Minimum seat height, mm",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "description": "id, name, year, capacity_cc, power_hp, seat_height_mm or popularity; prefix - for descending (e.g. -popularity). Bikes missing the value sort last.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "detail",
      "in": "query",
      "required": false,
      "description": "summary (default) or full: full returns the typed spec, description and dates for every result",
      "schema": {
       "type": "string",
       "enum": [
        "summary",
        "full"
       ]
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number, default 1",
      "schema": {
       "type": "integer",
       "minimum": 1
      }
     },
     {
      "name": "per_page",
      "in": "query",
      "required": false,
      "description": "Results per page, default 20, max 100 (max 50 with detail=full, where each bike returned counts as one request)",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "oneOf": [
             {
              "$ref": "#/components/schemas/BikeSummary"
             },
             {
              "$ref": "#/components/schemas/BikeFull"
             }
            ]
           }
          },
          "meta": {
           "$ref": "#/components/schemas/Meta"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Invalid parameter",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/bikes/{id}": {
   "get": {
    "summary": "Full specification for one bike",
    "operationId": "getBike",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "allOf": [
            {
             "$ref": "#/components/schemas/BikeFull"
            },
            {
             "type": "object",
             "properties": {
              "character_profile": {
               "type": "object",
               "nullable": true
              }
             }
            }
           ]
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "No bike with that id",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/categories": {
   "get": {
    "summary": "Category names with bike counts",
    "operationId": "listCategories",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "name": {
              "type": "string"
             },
             "bike_count": {
              "type": "integer"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/makes": {
   "get": {
    "summary": "Manufacturers",
    "operationId": "listMakes",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Partial name, ignores spaces and hyphens",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number, default 1",
      "schema": {
       "type": "integer",
       "minimum": 1
      }
     },
     {
      "name": "per_page",
      "in": "query",
      "required": false,
      "description": "Results per page, default 20, max 100 (max 50 with detail=full, where each bike returned counts as one request)",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "model_count": {
              "type": "integer"
             },
             "url": {
              "type": "string"
             }
            }
           }
          },
          "meta": {
           "$ref": "#/components/schemas/Meta"
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/makes/{id}/models": {
   "get": {
    "summary": "Models for one manufacturer",
    "operationId": "listMakeModels",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number, default 1",
      "schema": {
       "type": "integer",
       "minimum": 1
      }
     },
     {
      "name": "per_page",
      "in": "query",
      "required": false,
      "description": "Results per page, default 20, max 100 (max 50 with detail=full, where each bike returned counts as one request)",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "name": {
              "type": "string"
             },
             "year_from": {
              "type": "integer"
             },
             "year_to": {
              "type": "integer"
             },
             "model_years_on_record": {
              "type": "integer"
             },
             "url": {
              "type": "string"
             }
            }
           }
          },
          "meta": {
           "$ref": "#/components/schemas/Meta"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "No manufacturer with that id",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/recalls": {
   "get": {
    "summary": "Safety recalls (US NHTSA campaigns)",
    "operationId": "listRecalls",
    "parameters": [
     {
      "name": "make",
      "in": "query",
      "required": false,
      "description": "Exact manufacturer name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "model",
      "in": "query",
      "required": false,
      "description": "Partial model name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "year",
      "in": "query",
      "required": false,
      "description": "Exact model year",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number, default 1",
      "schema": {
       "type": "integer",
       "minimum": 1
      }
     },
     {
      "name": "per_page",
      "in": "query",
      "required": false,
      "description": "Results per page, default 20, max 100 (max 50 with detail=full, where each bike returned counts as one request)",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "type": "object"
           }
          },
          "meta": {
           "$ref": "#/components/schemas/Meta"
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/vin/{vin}": {
   "get": {
    "summary": "Decode a VIN (US-market, NHTSA vPIC)",
    "operationId": "decodeVin",
    "parameters": [
     {
      "name": "vin",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "minLength": 6,
       "maxLength": 17
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "type": "object"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing or too-short VIN",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "VIN could not be decoded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Key revoked, trial used up, or no active plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit exceeded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "description": "Authorization: Bearer mdb_..."
   },
   "apiKey": {
    "type": "apiKey",
    "in": "header",
    "name": "X-Api-Key"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "object",
      "properties": {
       "code": {
        "type": "string"
       },
       "message": {
        "type": "string"
       }
      }
     }
    }
   },
   "Meta": {
    "type": "object",
    "properties": {
     "page": {
      "type": "integer"
     },
     "per_page": {
      "type": "integer"
     },
     "total": {
      "type": "integer"
     },
     "total_pages": {
      "type": "integer"
     }
    }
   },
   "BikeSummary": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer"
     },
     "make": {
      "type": "string"
     },
     "model": {
      "type": "string"
     },
     "year": {
      "type": "integer"
     },
     "category": {
      "type": "string",
      "nullable": true
     },
     "capacity_cc": {
      "type": "number",
      "nullable": true
     },
     "power_hp": {
      "type": "number",
      "nullable": true
     },
     "seat_height_mm": {
      "type": "integer",
      "nullable": true
     },
     "url": {
      "type": "string",
      "format": "uri"
     },
     "image_url": {
      "type": "string",
      "format": "uri",
      "nullable": true,
      "description": "Main photo"
     },
     "thumb_url": {
      "type": "string",
      "format": "uri",
      "nullable": true,
      "description": "Main photo, thumbnail size"
     }
    }
   },
   "BikeFull": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer"
     },
     "make": {
      "type": "string"
     },
     "model": {
      "type": "string"
     },
     "year": {
      "type": "integer"
     },
     "url": {
      "type": "string",
      "format": "uri"
     },
     "description": {
      "type": "string",
      "nullable": true
     },
     "notable_features": {
      "type": "string",
      "nullable": true
     },
     "spec": {
      "$ref": "#/components/schemas/Spec"
     },
     "updated_at": {
      "type": "string",
      "format": "date",
      "nullable": true
     },
     "verified_at": {
      "type": "string",
      "format": "date",
      "nullable": true,
      "description": "Last date these specs were checked against a published source"
     },
     "image_url": {
      "type": "string",
      "format": "uri",
      "nullable": true,
      "description": "Main photo"
     },
     "thumb_url": {
      "type": "string",
      "format": "uri",
      "nullable": true,
      "description": "Main photo, thumbnail size"
     },
     "photos": {
      "type": "array",
      "description": "Up to 6 photos, as shown on the bike page",
      "items": {
       "type": "object",
       "properties": {
        "url": {
         "type": "string",
         "format": "uri"
        },
        "thumb_url": {
         "type": "string",
         "format": "uri"
        }
       }
      }
     }
    }
   },
   "Spec": {
    "type": "object",
    "nullable": true,
    "description": "Typed spec values; units are in each key name. null = not on record.",
    "properties": {
     "category": {
      "type": "string",
      "nullable": true
     },
     "category_2": {
      "type": "string",
      "nullable": true
     },
     "engine": {
      "type": "object",
      "properties": {
       "powertrain": {
        "type": "string",
        "enum": [
         "ICE",
         "Electric"
        ],
        "nullable": true
       },
       "capacity_cc": {
        "type": "number",
        "nullable": true
       },
       "engine_config": {
        "type": "string",
        "nullable": true
       },
       "cylinders": {
        "type": "integer",
        "nullable": true
       },
       "engine_cycle": {
        "type": "integer",
        "description": "2 = two-stroke, 4 = four-stroke",
        "nullable": true
       },
       "bore_mm": {
        "type": "number",
        "nullable": true
       },
       "stroke_mm": {
        "type": "number",
        "nullable": true
       },
       "compression_ratio": {
        "type": "number",
        "nullable": true
       },
       "valves_per_cyl": {
        "type": "integer",
        "nullable": true
       },
       "cooling": {
        "type": "string",
        "enum": [
         "air",
         "oil_air",
         "liquid"
        ],
        "nullable": true
       },
       "fuel_system": {
        "type": "string",
        "nullable": true
       },
       "aspiration": {
        "type": "string",
        "nullable": true
       },
       "ignition": {
        "type": "string",
        "nullable": true
       },
       "starter": {
        "type": "string",
        "nullable": true
       },
       "lubrication": {
        "type": "string",
        "nullable": true
       }
      }
     },
     "performance": {
      "type": "object",
      "properties": {
       "power_hp": {
        "type": "number",
        "nullable": true
       },
       "power_kw": {
        "type": "number",
        "nullable": true
       },
       "power_rpm": {
        "type": "integer",
        "nullable": true
       },
       "torque_nm": {
        "type": "number",
        "nullable": true
       },
       "torque_rpm": {
        "type": "integer",
        "nullable": true
       },
       "top_speed_kmh": {
        "type": "number",
        "nullable": true
       },
       "zero_100_s": {
        "type": "number",
        "nullable": true
       },
       "zero_60_s": {
        "type": "number",
        "nullable": true
       }
      }
     },
     "electric": {
      "type": "object",
      "properties": {
       "motor_type": {
        "type": "string",
        "nullable": true
       },
       "motor_kw": {
        "type": "number",
        "nullable": true
       },
       "power_rated_kw": {
        "type": "number",
        "nullable": true
       },
       "power_peak_kw": {
        "type": "number",
        "nullable": true
       },
       "battery_kwh": {
        "type": "number",
        "nullable": true
       },
       "range_km": {
        "type": "number",
        "nullable": true
       },
       "charge_time_h": {
        "type": "number",
        "nullable": true
       }
      }
     },
     "drivetrain": {
      "type": "object",
      "properties": {
       "transmission": {
        "type": "string",
        "nullable": true
       },
       "gear_count": {
        "type": "integer",
        "nullable": true
       },
       "final_drive": {
        "type": "string",
        "nullable": true
       },
       "clutch": {
        "type": "string",
        "nullable": true
       }
      }
     },
     "chassis": {
      "type": "object",
      "properties": {
       "frame_type": {
        "type": "string",
        "nullable": true
       },
       "front_suspension": {
        "type": "string",
        "nullable": true
       },
       "front_travel_mm": {
        "type": "number",
        "nullable": true
       },
       "rear_suspension": {
        "type": "string",
        "nullable": true
       },
       "rear_travel_mm": {
        "type": "number",
        "nullable": true
       },
       "rake_deg": {
        "type": "number",
        "nullable": true
       },
       "trail_mm": {
        "type": "number",
        "nullable": true
       },
       "front_brake": {
        "type": "string",
        "nullable": true
       },
       "front_brake_mm": {
        "type": "number",
        "nullable": true
       },
       "rear_brake": {
        "type": "string",
        "nullable": true
       },
       "rear_brake_mm": {
        "type": "number",
        "nullable": true
       },
       "abs_type": {
        "type": "string",
        "enum": [
         "yes",
         "dual_channel",
         "switchable",
         "optional",
         "unspecified"
        ],
        "nullable": true
       },
       "front_tyre": {
        "type": "string",
        "nullable": true
       },
       "rear_tyre": {
        "type": "string",
        "nullable": true
       },
       "wheel_front_in": {
        "type": "number",
        "nullable": true
       },
       "wheel_rear_in": {
        "type": "number",
        "nullable": true
       }
      }
     },
     "dimensions": {
      "type": "object",
      "properties": {
       "seat_height_mm": {
        "type": "integer",
        "nullable": true
       },
       "seat_height_max_mm": {
        "type": "integer",
        "nullable": true
       },
       "wheelbase_mm": {
        "type": "integer",
        "nullable": true
       },
       "ground_clearance_mm": {
        "type": "integer",
        "nullable": true
       },
       "length_mm": {
        "type": "integer",
        "nullable": true
       },
       "width_mm": {
        "type": "integer",
        "nullable": true
       },
       "height_mm": {
        "type": "integer",
        "nullable": true
       },
       "dry_weight_kg": {
        "type": "number",
        "nullable": true
       },
       "wet_weight_kg": {
        "type": "number",
        "nullable": true
       }
      }
     },
     "fuel": {
      "type": "object",
      "properties": {
       "fuel_capacity_l": {
        "type": "number",
        "nullable": true
       },
       "fuel_reserve_l": {
        "type": "number",
        "nullable": true
       },
       "oil_capacity_l": {
        "type": "number",
        "nullable": true
       },
       "fuel_consumption_l100": {
        "type": "number",
        "nullable": true
       },
       "fuel_tank_material": {
        "type": "string",
        "nullable": true
       },
       "emission_standard": {
        "type": "string",
        "nullable": true
       },
       "co2_gkm": {
        "type": "number",
        "nullable": true
       },
       "epa_certificate_no": {
        "type": "string",
        "nullable": true
       },
       "epa_est_fuel_consumption_l100": {
        "type": "number",
        "nullable": true
       },
       "epa_co_gkm": {
        "type": "number",
        "nullable": true
       }
      }
     },
     "other": {
      "type": "object",
      "properties": {
       "warranty_months": {
        "type": "integer",
        "nullable": true
       },
       "colour_options": {
        "type": "string",
        "nullable": true
       }
      }
     }
    }
   }
  }
 }
}
