{
  "openapi": "3.1.0",
  "info": {
    "title": "CheckMyVIN API",
    "version": "1.0.0",
    "summary": "Free AI vehicle report by VIN — NHTSA-official data.",
    "description": "Decode any 17-character VIN against the official NHTSA VPIC database and pull every open recall NHTSA has on file. Adds an AI-generated plain-English summary (strengths, issues, buying advice, 1–10 score) and engine-keyed maintenance specs.\n\n### Rate limit\n- **100 requests per IP per UTC day** on the free tier.\n- Limit headers are returned on every response: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`.\n- HTTP `429` is returned with a `Retry-After` header when the limit is exceeded.\n\n### Data sources (all free, no API key)\n- VIN decode: NHTSA VPIC (`vpic.nhtsa.dot.gov`)\n- Recalls: NHTSA recalls API (`api.nhtsa.gov`)\n- AI summary: OpenAI / Anthropic (configurable on the server)",
    "contact": { "name": "CheckMyVIN", "url": "https://checkmyvin.net" },
    "license": { "name": "Data is public NHTSA. AI summary © CheckMyVIN." }
  },
  "servers": [
    { "url": "https://checkmyvin.net", "description": "Production" }
  ],
  "paths": {
    "/api/decode": {
      "post": {
        "summary": "Decode a VIN into a full vehicle report",
        "description": "Decodes a 17-character VIN against NHTSA VPIC, queries open recalls, returns matched maintenance specs, and generates an AI summary. Cached for 7 days per VIN in Cloudflare KV; cached responses return `X-Cache: HIT`.",
        "operationId": "decodeVin",
        "tags": ["VIN"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/DecodeRequest" },
              "examples": {
                "ford-f150": { "value": { "vin": "1FTFW1ET5DFC10312" } },
                "tesla-model-3": { "value": { "vin": "5YJ3E1EA0KF317650" } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "VIN decoded successfully.",
            "headers": {
              "X-Cache": {
                "schema": { "type": "string", "enum": ["HIT", "MISS"] },
                "description": "Whether the response came from KV cache."
              },
              "X-RateLimit-Limit": { "schema": { "type": "integer" } },
              "X-RateLimit-Remaining": { "schema": { "type": "integer" } },
              "X-RateLimit-Reset": {
                "schema": { "type": "integer" },
                "description": "Seconds until the rate-limit window resets (UTC midnight)."
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VinReport" }
              }
            }
          },
          "400": {
            "description": "Bad request — invalid VIN format OR NHTSA decode failed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DecodeError" }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (100/day per IP).",
            "headers": {
              "Retry-After": {
                "schema": { "type": "integer" },
                "description": "Seconds until the next request will be accepted."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": { "type": "string" },
                    "limit": { "type": "integer" },
                    "remaining": { "type": "integer" },
                    "resetSeconds": { "type": "integer" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "DecodeRequest": {
        "type": "object",
        "required": ["vin"],
        "properties": {
          "vin": {
            "type": "string",
            "pattern": "^[A-HJ-NPR-Z0-9]{17}$",
            "description": "17-character Vehicle Identification Number. VINs never contain I, O, or Q.",
            "example": "1FTFW1ET5DFC10312"
          }
        }
      },
      "DecodedVehicle": {
        "type": "object",
        "properties": {
          "vin": { "type": "string" },
          "make": { "type": "string" },
          "model": { "type": "string" },
          "modelYear": { "type": "string" },
          "trim": { "type": "string" },
          "bodyClass": { "type": "string" },
          "vehicleType": { "type": "string" },
          "driveType": { "type": "string" },
          "engineCylinders": { "type": "string" },
          "engineDisplacement": { "type": "string" },
          "engineModel": { "type": "string" },
          "fuelType": { "type": "string" },
          "transmissionStyle": { "type": "string" },
          "transmissionSpeeds": { "type": "string" },
          "plantCountry": { "type": "string" },
          "plantCity": { "type": "string" },
          "electrificationLevel": { "type": "string" },
          "batteryKwh": { "type": "string" },
          "errorCode": { "type": "string" },
          "errorText": { "type": "string" }
        }
      },
      "Recall": {
        "type": "object",
        "properties": {
          "campNo": { "type": "string", "description": "NHTSA campaign number (e.g. 23V-456)." },
          "component": { "type": "string" },
          "summary": { "type": "string" },
          "consequence": { "type": "string" },
          "remedy": { "type": "string" },
          "reportReceivedDate": { "type": "string" }
        }
      },
      "AiSummary": {
        "type": "object",
        "properties": {
          "overview": { "type": "string" },
          "strengths": { "type": "array", "items": { "type": "string" } },
          "issues": { "type": "array", "items": { "type": "string" } },
          "buyingAdvice": { "type": "string" },
          "maintenanceTips": { "type": "string" },
          "score": { "type": "integer", "minimum": 1, "maximum": 10 }
        }
      },
      "MaintenanceSpec": {
        "type": "object",
        "properties": {
          "oil": { "type": "string" },
          "oilCapacity": { "type": "string" },
          "oilInterval": { "type": "string" },
          "sparkPlugs": { "type": "string" },
          "battery": { "type": "string" },
          "brakeFluid": { "type": "string" },
          "coolant": { "type": "string" },
          "tireSize": { "type": "string", "description": "Often \"Varies by trim — check door-jamb label\" because tire size varies by wheel package." },
          "cabinFilter": { "type": "string" },
          "isElectric": { "type": "boolean" },
          "notes": { "type": "string" }
        }
      },
      "VinReport": {
        "type": "object",
        "required": ["vin", "vehicle", "recalls", "ai", "generatedAt"],
        "properties": {
          "vin": { "type": "string" },
          "vehicle": { "$ref": "#/components/schemas/DecodedVehicle" },
          "recalls": { "type": "array", "items": { "$ref": "#/components/schemas/Recall" } },
          "maintenance": {
            "oneOf": [
              { "$ref": "#/components/schemas/MaintenanceSpec" },
              { "type": "null" }
            ]
          },
          "ai": { "$ref": "#/components/schemas/AiSummary" },
          "generatedAt": { "type": "string", "format": "date-time" },
          "cached": { "type": "boolean" }
        }
      },
      "DecodeError": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string" },
          "errorText": { "type": "string", "description": "Verbatim NHTSA error text when applicable." },
          "vehicle": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "vin": { "type": "string" },
                  "make": { "type": "string" },
                  "modelYear": { "type": "string" },
                  "model": { "type": "string" },
                  "errorCode": { "type": "string" },
                  "errorText": { "type": "string" }
                }
              },
              { "type": "null" }
            ]
          }
        }
      }
    }
  }
}
