{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "AutoFire Public API",
    "version": "1.0.0",
    "description": "Public, read-only integration endpoints for AutoFire. VIN decoding proxies the NHTSA vPIC service. The MCP endpoint exposes dealership-scoped, read-only tools to an authenticated MCP client. Keep credentials server-side, use HTTPS, and follow the rate-limit guidance on each operation. API versioning policy: this document is the v1 public contract and intentionally keeps the existing unversioned paths for compatibility. Additive fields and operations are backward compatible; breaking changes are introduced under a new versioned path only after a migration notice. Deprecated fields and operations remain documented with `deprecated: true` until their announced sunset.",
    "x-api-version": "1",
    "x-api-versioning": {
      "strategy": "unversioned-canonical-path",
      "current": "1",
      "compatibility": "The existing unversioned paths are the stable v1 contract; clients must not assume undocumented routes.",
      "breakingChangePolicy": "Breaking changes use a new versioned path and are announced before the prior version is retired.",
      "deprecationPolicy": "Before removing a stable version, AutoFire publishes a migration guide and emits RFC 9745 Deprecation and Link headers. A dated Sunset header is announced at least 90 days before removal. Version 1 is active with no scheduled sunset; the deprecated unversioned /api/status compatibility alias sunsets on 2026-11-20 in favor of /api/v1/status.",
      "deprecationPolicyUrl": "https://www.goautofire.com/developers#api-versioning",
      "migration": "Clients should pin to this document's version and treat unknown response fields as forward-compatible."
    },
    "contact": {
      "name": "AutoFire Support",
      "url": "https://www.goautofire.com/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://www.goautofire.com/terms"
    }
  },
  "externalDocs": {
    "description": "AutoFire MCP client setup and security guidance",
    "url": "https://www.goautofire.com/mcp"
  },
  "servers": [
    {
      "url": "https://www.goautofire.com",
      "description": "AutoFire public web API"
    }
  ],
  "tags": [
    {
      "name": "Public API",
      "description": "Unauthenticated, side-effect-free API discovery and health resources."
    },
    {
      "name": "VIN decoder",
      "description": "Public VIN decoding through the NHTSA vPIC service."
    },
    {
      "name": "MCP",
      "description": "Authenticated, dealership-scoped Model Context Protocol transport."
    }
  ],
  "paths": {
    "/api/v1/status": {
      "get": {
        "tags": ["Public API"],
        "summary": "Check the public AutoFire API contract",
        "description": "Unauthenticated, side-effect-free probe for agents and generated clients. Returns the active API version and developer documentation URL. AutoFire enforces 120 requests per minute per source and publishes the current quota on every response.",
        "operationId": "getPublicApiStatusV1",
        "security": [],
        "parameters": [
          {
            "name": "X-AutoFire-API-Version",
            "in": "header",
            "required": false,
            "description": "Pins the stable public contract. Omit for the current version or send 1.",
            "schema": {
              "type": "string",
              "const": "1",
              "default": "1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The public API is available.",
            "headers": {
              "X-AutoFire-API-Version": { "$ref": "#/components/headers/ApiVersion" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" },
              "RateLimit": { "$ref": "#/components/headers/RateLimit" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiStatusResponse" }
              }
            }
          },
          "400": {
            "description": "The requested API version is not supported.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "429": {
            "description": "The per-source status quota was exceeded.",
            "headers": {
              "Retry-After": { "$ref": "#/components/headers/RetryAfter" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" },
              "RateLimit": { "$ref": "#/components/headers/RateLimit" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "503": {
            "description": "The durable status quota could not be checked, so the endpoint failed closed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        },
        "x-rate-limit": {
          "sourcePerMinute": 120,
          "windowSeconds": 60
        }
      }
    },
    "/api/status": {
      "get": {
        "tags": ["Public API"],
        "summary": "Check the public API through the deprecated compatibility alias",
        "description": "Deprecated unversioned alias for /api/v1/status. It remains read-only and unauthenticated during the 90-day migration window, and every response includes RFC 9745 Deprecation, Link, and dated Sunset headers.",
        "operationId": "getPublicApiStatusCompatibility",
        "deprecated": true,
        "security": [],
        "responses": {
          "200": {
            "description": "The public API is available; migrate to /api/v1/status before the sunset date.",
            "headers": {
              "Deprecation": { "$ref": "#/components/headers/Deprecation" },
              "Sunset": { "$ref": "#/components/headers/Sunset" },
              "Link": { "$ref": "#/components/headers/DeprecationLink" },
              "X-AutoFire-API-Version": { "$ref": "#/components/headers/ApiVersion" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" },
              "RateLimit": { "$ref": "#/components/headers/RateLimit" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiStatusResponse" }
              }
            }
          },
          "400": {
            "description": "The requested API version is not supported.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "429": {
            "description": "The per-source status quota was exceeded.",
            "headers": {
              "Retry-After": { "$ref": "#/components/headers/RetryAfter" },
              "Deprecation": { "$ref": "#/components/headers/Deprecation" },
              "Sunset": { "$ref": "#/components/headers/Sunset" },
              "Link": { "$ref": "#/components/headers/DeprecationLink" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "503": {
            "description": "The durable status quota could not be checked, so the endpoint failed closed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        },
        "x-sunset": "2026-11-20T00:00:00Z"
      }
    },
    "/api/vin-decoder": {
      "get": {
        "tags": ["VIN decoder"],
        "summary": "Decode a vehicle identification number",
        "description": "Decode a 17-character VIN through the NHTSA vPIC service. This endpoint is public and does not require an API key. The VIN is validated before it is sent upstream, and provider details are sanitized on errors. AutoFire enforces 60 requests per minute per source; every response publishes the current quota, and a 429 includes Retry-After.",
        "operationId": "decodeVin",
        "x-api-version": "1",
        "security": [],
        "parameters": [
          {
            "name": "X-AutoFire-API-Version",
            "in": "header",
            "required": false,
            "description": "Pins the stable public contract. Omit this header for the current version or send 1. Unsupported versions receive a typed 400 response.",
            "schema": {
              "type": "string",
              "const": "1",
              "default": "1"
            },
            "example": "1"
          },
          {
            "name": "vin",
            "in": "query",
            "required": true,
            "description": "Exactly 17 letters or digits. The letters I, O, and Q are not valid VIN characters.",
            "schema": {
              "type": "string",
              "minLength": 17,
              "maxLength": 17,
              "pattern": "^[A-HJ-NPR-Z0-9]{17}$",
              "example": "1HGCM82633A004352"
            },
            "example": "1HGCM82633A004352"
          }
        ],
        "responses": {
          "200": {
            "description": "The raw NHTSA vPIC decode response.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              },
              "X-AutoFire-API-Version": {
                "$ref": "#/components/headers/ApiVersion"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NhtsaDecodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidVin"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "504": {
            "$ref": "#/components/responses/UpstreamTimeout"
          },
          "429": {
            "$ref": "#/components/responses/VinRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/VinRateLimiterUnavailable"
          },
          "default": {
            "description": "Unexpected typed VIN API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "x-rate-limit": {
          "sourcePerMinute": 60,
          "windowSeconds": 60,
          "headers": ["RateLimit-Policy", "RateLimit", "RateLimit-Limit", "RateLimit-Remaining", "RateLimit-Reset"],
          "recommendedRetry": "Honor Retry-After on 429 responses, then use exponential backoff."
        }
      }
    },
    "/api/mcp": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ApiVersion"
        }
      ],
      "servers": [
        {
          "url": "https://www.goautofire.com",
          "description": "Application-hosted MCP compatibility route"
        }
      ],
      "post": {
        "tags": ["MCP"],
        "summary": "Send an MCP JSON-RPC message",
        "description": "Send one MCP JSON-RPC request or notification to the stateless AutoFire dealership MCP server. Authenticate every request with an AutoFire MCP bearer token in the Authorization header. Tokens are dealership-scoped and must never be sent to a browser, logged, or forwarded to another service. The server accepts requests up to 128 KiB and applies source, key, dealership, and per-tool limits. Current HTTP ceilings are 90 requests/minute per source, 120 requests/minute per key, and 600 requests/minute per dealership; individual tools can be stricter. A 429 response includes Retry-After when the retry window is known.",
        "operationId": "sendMcpMessageApi",
        "x-api-version": "1",
        "security": [
          {
            "McpBearerAuth": []
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/McpJsonRpcMessage"
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response. Depending on client negotiation, a request can receive JSON or a server-sent event stream.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "UTF-8 server-sent events containing JSON-RPC messages."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/McpBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/McpUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/McpForbidden"
          },
          "413": {
            "$ref": "#/components/responses/McpRequestTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/McpRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/McpServerError"
          },
          "default": {
            "description": "Unexpected typed MCP transport error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpTransportErrorResponse"
                }
              }
            }
          }
        },
        "x-rate-limit": {
          "sourcePerMinute": 90,
          "keyPerMinute": 120,
          "dealershipPerMinute": 600,
          "maxRequestBytes": 131072,
          "note": "Individual MCP tools may have lower per-key and per-dealership limits."
        }
      },
      "options": {
        "tags": ["MCP"],
        "summary": "Discover MCP transport methods",
        "description": "CORS preflight for the MCP transport. This request does not carry a JSON-RPC body; the server validates the host and origin and returns the supported methods.",
        "operationId": "optionsMcpTransportApi",
        "x-api-version": "1",
        "security": [],
        "responses": {
          "204": {
            "description": "Preflight accepted.",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                },
                "description": "Supported MCP transport methods."
              }
            }
          },
          "403": {
            "description": "The host or origin is not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ApiVersion"
        }
      ],
      "servers": [
        {
          "url": "https://mcp.goautofire.com",
          "description": "Canonical AutoFire MCP host"
        }
      ],
      "post": {
        "tags": ["MCP"],
        "summary": "Send an MCP JSON-RPC message",
        "description": "Canonical MCP transport for AutoFire. Send one JSON-RPC request or notification with a dealership-scoped AutoFire MCP bearer token. The server accepts requests up to 128 KiB and applies source, key, dealership, and per-tool limits: 90 requests/minute per source, 120 requests/minute per key, and 600 requests/minute per dealership. Individual tools may be stricter. Honor Retry-After on 429 responses and never retry a non-idempotent client action without checking its request semantics; AutoFire tools are read-only.",
        "operationId": "sendMcpMessage",
        "x-api-version": "1",
        "security": [
          {
            "McpBearerAuth": []
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/McpJsonRpcMessage"
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response. Depending on client negotiation, a request can receive JSON or a server-sent event stream.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "UTF-8 server-sent events containing JSON-RPC messages."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/McpBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/McpUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/McpForbidden"
          },
          "413": {
            "$ref": "#/components/responses/McpRequestTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/McpRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/McpServerError"
          },
          "default": {
            "description": "Unexpected typed MCP transport error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpTransportErrorResponse"
                }
              }
            }
          }
        },
        "x-rate-limit": {
          "sourcePerMinute": 90,
          "keyPerMinute": 120,
          "dealershipPerMinute": 600,
          "maxRequestBytes": 131072,
          "note": "Individual MCP tools may have lower per-key and per-dealership limits."
        }
      },
      "options": {
        "tags": ["MCP"],
        "summary": "Discover MCP transport methods",
        "description": "CORS preflight for the canonical MCP transport. No JSON-RPC body is expected.",
        "operationId": "optionsMcpTransport",
        "x-api-version": "1",
        "security": [],
        "responses": {
          "204": {
            "description": "Preflight accepted.",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                },
                "description": "Supported MCP transport methods."
              }
            }
          },
          "403": {
            "description": "The host or origin is not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "McpBearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "AutoFire MCP token",
        "description": "Required for MCP requests. Use the complete token generated in the AutoFire dashboard (format af_mcp_live_<43 characters>) as `Authorization: Bearer <token>`. Tokens are hashed at rest, scoped to one dealership, expire according to the dashboard setting, and can be revoked by a dealership owner/admin. Do not put a token in a URL or browser bundle. When MCP OAuth is enabled for a client, use the protected-resource metadata advertised by the MCP host instead of inventing a token exchange. The bearer token carries the same named scope claims used by the MCP authorization layer; the transport itself requires a valid token, while each tool enforces its listed scope.",
        "x-scopes": {
          "dealership:read": "Read the authorized dealership's public business profile.",
          "inventory:read": "Search and read vehicles belonging to the authorized dealership.",
          "leads:read": "List dealership lead workflow records with contact fields masked.",
          "leads:pii": "Read contact details for an individual lead; requires leads:read as well.",
          "test_drives:read": "Read dealership test-drive workflow records without customer contact fields.",
          "insights:read": "Read aggregate dealership insight reports."
        },
        "x-scope-format": "space-delimited bearer-token scope claims",
        "x-scope-policy": "Keys may contain one or more of the named scopes. leads:pii is valid only together with leads:read. The server advertises only tools allowed by the credential."
      }
    },
    "parameters": {
      "ApiVersion": {
        "name": "X-AutoFire-API-Version",
        "in": "header",
        "required": false,
        "description": "Pins the stable public contract. Omit for the current version or send 1. Unsupported versions receive a typed 400 response.",
        "schema": {
          "type": "string",
          "const": "1",
          "default": "1"
        },
        "example": "1"
      },
      "McpSessionId": {
        "name": "Mcp-Session-Id",
        "in": "header",
        "required": false,
        "description": "Optional MCP session identifier returned by a stateful client negotiation. AutoFire currently runs the compatibility transport statelessly.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[A-Za-z0-9._~-]+$"
        }
      }
    },
    "headers": {
      "Deprecation": {
        "description": "RFC 9745 deprecation date. This header is emitted only after a version is formally deprecated; version 1 is active and does not currently emit it.",
        "schema": {
          "type": "string",
          "example": "@1803945600"
        }
      },
      "Sunset": {
        "description": "RFC 8594 removal date announced at least 90 days in advance. This header is absent while no sunset is scheduled.",
        "schema": {
          "type": "string",
          "format": "http-date",
          "example": "Wed, 30 Dec 2027 00:00:00 GMT"
        }
      },
      "DeprecationLink": {
        "description": "Link to the migration guide with rel=deprecation when a version enters deprecation.",
        "schema": {
          "type": "string",
          "example": "<https://www.goautofire.com/developers#api-versioning>; rel=\"deprecation\""
        }
      },
      "ApiVersion": {
        "description": "The public API contract version used for this response.",
        "schema": {
          "type": "string",
          "const": "1"
        }
      },
      "RateLimitPolicy": {
        "description": "Enforced quota and window in seconds.",
        "schema": {
          "type": "string",
          "example": "60;w=60"
        }
      },
      "RateLimit": {
        "description": "Requests remaining in the active quota window.",
        "schema": {
          "type": "string",
          "example": "59;w=60"
        }
      },
      "RateLimitLimit": {
        "description": "Compatibility field containing the enforced request ceiling.",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "RateLimitRemaining": {
        "description": "Compatibility field containing requests remaining.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RateLimitReset": {
        "description": "Compatibility field containing seconds until reset.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying the request.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "NoStore": {
        "description": "Responses are not stored in shared or browser caches.",
        "schema": {
          "type": "string",
          "const": "no-store, max-age=0"
        }
      }
    },
    "requestBodies": {
      "McpJsonRpcMessage": {
        "required": true,
        "description": "One JSON-RPC 2.0 MCP request/notification or a non-empty batch. The request must be no larger than 128 KiB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpJsonRpcMessage"
            },
            "examples": {
              "initialize": {
                "summary": "Initialize an MCP client",
                "value": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "method": "initialize",
                  "params": {
                    "protocolVersion": "2026-06-18",
                    "capabilities": {},
                    "clientInfo": {
                      "name": "example-client",
                      "version": "1.0.0"
                    }
                  }
                }
              },
              "listTools": {
                "summary": "List tools allowed by the credential",
                "value": {
                  "jsonrpc": "2.0",
                  "id": 2,
                  "method": "tools/list",
                  "params": {}
                }
              },
              "callTool": {
                "summary": "Call a dealership-scoped read-only tool",
                "value": {
                  "jsonrpc": "2.0",
                  "id": 3,
                  "method": "tools/call",
                  "params": {
                    "name": "search_inventory",
                    "arguments": {
                      "query": "Toyota",
                      "status": "available",
                      "limit": 20,
                      "offset": 0
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "responses": {
      "InvalidVin": {
        "description": "The VIN is missing or does not match the required 17-character format.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Invalid VIN format. VIN must be 17 characters and exclude I, O, and Q.",
              "code": "invalid_vin",
              "message": "Invalid VIN format. VIN must be 17 characters and exclude I, O, and Q.",
              "resolution": "Provide exactly 17 letters or numbers, excluding I, O, and Q."
            }
          }
        }
      },
      "UpstreamUnavailable": {
        "description": "The NHTSA provider returned an unsuccessful response or could not be reached. Provider details are intentionally not exposed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "The VIN decoder service is temporarily unavailable.",
              "code": "upstream_unavailable",
              "message": "The VIN decoder service is temporarily unavailable.",
              "resolution": "Retry the request shortly. If the problem persists, try again later."
            }
          }
        }
      },
      "UpstreamTimeout": {
        "description": "The NHTSA provider did not respond within the proxy timeout.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "The VIN decoder service did not respond in time.",
              "code": "upstream_timeout",
              "message": "The VIN decoder service did not respond in time.",
              "resolution": "Retry the request shortly."
            }
          }
        }
      },
      "VinRateLimited": {
        "description": "The per-source VIN decoder quota was exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Too many VIN decoder requests.",
              "code": "rate_limit_exceeded",
              "message": "Too many VIN decoder requests.",
              "resolution": "Retry the request after the Retry-After interval."
            }
          }
        }
      },
      "VinRateLimiterUnavailable": {
        "description": "The durable VIN quota could not be checked, so the endpoint failed closed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "The VIN decoder is temporarily unavailable.",
              "code": "rate_limit_unavailable",
              "message": "The VIN decoder is temporarily unavailable.",
              "resolution": "Retry the request shortly."
            }
          }
        }
      },
      "McpMessage": {
        "description": "MCP JSON-RPC response. Depending on client negotiation, a request can receive JSON or a server-sent event stream.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpJsonRpcResponse"
            }
          },
          "text/event-stream": {
            "schema": {
              "type": "string",
              "description": "UTF-8 server-sent events containing JSON-RPC messages."
            }
          }
        }
      },
      "McpEventStream": {
        "description": "Authenticated MCP server-sent event stream.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "text/event-stream": {
            "schema": {
              "type": "string",
              "description": "UTF-8 server-sent events containing JSON-RPC messages."
            }
          }
        }
      },
      "McpBadRequest": {
        "description": "The request is not valid JSON-RPC, uses an unsupported MCP method, or violates the 128 KiB request limit before protocol handling.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpTransportErrorResponse"
            },
            "example": {
              "error": "invalid_request",
              "error_description": "The MCP request is invalid."
            }
          }
        }
      },
      "McpUnauthorized": {
        "description": "Authentication is missing, malformed, expired, or revoked. The server does not disclose which credential check failed.",
        "headers": {
          "WWW-Authenticate": {
            "description": "Bearer authentication challenge. OAuth-enabled deployments may include protected-resource metadata.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpHttpErrorResponse"
            },
            "example": {
              "error": "invalid_token",
              "error_description": "Authentication is required."
            }
          }
        }
      },
      "McpForbidden": {
        "description": "The host/origin is not allowed or the authenticated credential lacks a required tool scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpTransportErrorResponse"
            },
            "example": {
              "error": "insufficient_scope",
              "error_description": "The MCP request is not permitted."
            }
          }
        }
      },
      "McpRequestTooLarge": {
        "description": "The request body exceeds the 128 KiB MCP transport limit.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpHttpErrorResponse"
            },
            "example": {
              "error": "request_too_large",
              "error_description": "MCP requests are limited to 128 KiB."
            }
          }
        }
      },
      "McpRateLimited": {
        "description": "A source, key, dealership, or individual tool rate limit was exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpHttpErrorResponse"
            },
            "example": {
              "error": "rate_limit_exceeded",
              "error_description": "Too many MCP requests."
            }
          }
        }
      },
      "McpServerError": {
        "description": "The MCP request could not be completed securely.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/McpTransportErrorResponse"
            },
            "example": {
              "error": "server_error",
              "error_description": "The MCP request could not be completed securely."
            }
          }
        }
      }
    },
    "schemas": {
      "ApiStatusResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["status", "apiVersion", "documentation"],
        "properties": {
          "status": {
            "type": "string",
            "const": "ok"
          },
          "apiVersion": {
            "type": "string",
            "const": "1"
          },
          "documentation": {
            "type": "string",
            "format": "uri",
            "const": "https://www.goautofire.com/developers"
          }
        }
      },
      "McpTransportErrorResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/McpHttpErrorResponse"
          },
          {
            "$ref": "#/components/schemas/McpJsonRpcErrorResponse"
          }
        ],
        "description": "Typed MCP transport error. Authentication, quota, and request-size failures use the OAuth bearer error envelope; protocol and host/origin failures use the JSON-RPC 2.0 error envelope."
      },
      "McpHttpErrorResponse": {
        "type": "object",
        "description": "OAuth 2.0 bearer-resource error envelope returned by the MCP HTTP transport. The error value is a stable machine-readable code; no credential or provider detail is disclosed.",
        "additionalProperties": false,
        "required": ["error", "error_description"],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_token",
              "insufficient_scope",
              "request_too_large",
              "rate_limit_exceeded",
              "server_error"
            ],
            "description": "Stable OAuth/MCP HTTP error code."
          },
          "error_description": {
            "type": "string",
            "minLength": 1,
            "description": "Safe, human-readable recovery guidance. It never contains tokens, request bodies, or upstream internals."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Stable, machine-readable AutoFire error envelope used by the VIN route. `error` is a human-readable compatibility alias; `code` is the stable discriminator and `resolution` is safe recovery guidance. Optional RFC 9457-style fields are included when a generic API route supplies them.",
        "additionalProperties": false,
        "required": ["error", "code", "message", "resolution"],
        "properties": {
          "error": {
            "type": "string",
            "minLength": 1,
            "description": "Human-readable compatibility alias for message."
          },
          "code": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*$",
            "description": "Stable error code suitable for programmatic handling.",
            "examples": [
              "invalid_vin",
              "unauthorized",
              "rate_limit_exceeded",
              "server_error"
            ]
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "description": "Safe explanation of what happened. It does not contain provider internals, tokens, or request secrets."
          },
          "resolution": {
            "type": "string",
            "minLength": 1,
            "description": "Action the client can take to recover."
          },
          "type": {
            "type": "string",
            "format": "uri-reference",
            "description": "Optional RFC 9457 problem type URI."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "Optional short problem title."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599,
            "description": "Optional HTTP status copied into a problem response."
          },
          "detail": {
            "type": "string",
            "minLength": 1,
            "description": "Optional detailed problem explanation."
          },
          "instance": {
            "type": "string",
            "format": "uri-reference",
            "description": "Optional URI identifying this problem occurrence."
          }
        }
      },
      "NhtsaDecodeResponse": {
        "type": "object",
        "description": "NHTSA vPIC decode response. The provider can add fields over time, so unknown top-level fields and result fields are preserved.",
        "required": ["Count", "Message", "Results"],
        "properties": {
          "Count": {
            "type": "integer",
            "minimum": 0
          },
          "Message": {
            "type": "string"
          },
          "SearchCriteria": {
            "type": ["string", "null"]
          },
          "Results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NhtsaVehicleResult"
            }
          }
        },
        "additionalProperties": true
      },
      "NhtsaVehicleResult": {
        "type": "object",
        "description": "A decoded vehicle result. NHTSA represents most values as strings and can return null for unavailable fields.",
        "properties": {
          "VIN": {
            "type": ["string", "null"]
          },
          "Make": {
            "type": ["string", "null"]
          },
          "Model": {
            "type": ["string", "null"]
          },
          "ModelYear": {
            "type": ["string", "null"]
          },
          "Trim": {
            "type": ["string", "null"]
          },
          "BodyClass": {
            "type": ["string", "null"]
          },
          "EngineCylinders": {
            "type": ["string", "null"]
          },
          "EngineHP": {
            "type": ["string", "null"]
          },
          "FuelTypePrimary": {
            "type": ["string", "null"]
          },
          "DriveType": {
            "type": ["string", "null"]
          },
          "TransmissionStyle": {
            "type": ["string", "null"]
          },
          "Doors": {
            "type": ["string", "null"]
          },
          "ErrorCode": {
            "type": ["string", "null"]
          },
          "ErrorText": {
            "type": ["string", "null"]
          }
        },
        "additionalProperties": {
          "type": ["string", "number", "boolean", "null"]
        }
      },
      "McpJsonRpcMessage": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/McpJsonRpcRequest"
          },
          {
            "$ref": "#/components/schemas/McpJsonRpcBatch"
          }
        ],
        "description": "A single MCP JSON-RPC 2.0 request/notification or a non-empty batch."
      },
      "McpJsonRpcRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["jsonrpc", "method"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 128
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Request correlation identifier. Omit for a notification."
          },
          "method": {
            "type": "string",
            "enum": [
              "initialize",
              "notifications/initialized",
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "$ref": "#/components/schemas/McpRequestParams"
          }
        }
      },
      "McpJsonRpcBatch": {
        "type": "array",
        "minItems": 1,
        "maxItems": 25,
        "items": {
          "$ref": "#/components/schemas/McpJsonRpcRequest"
        }
      },
      "McpRequestParams": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/McpInitializeParams"
          },
          {
            "$ref": "#/components/schemas/McpToolsListParams"
          },
          {
            "$ref": "#/components/schemas/McpToolsCallParams"
          },
          {
            "type": "object",
            "additionalProperties": true
          }
        ]
      },
      "McpInitializeParams": {
        "type": "object",
        "additionalProperties": true,
        "required": ["protocolVersion", "capabilities", "clientInfo"],
        "properties": {
          "protocolVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32
          },
          "capabilities": {
            "type": "object",
            "additionalProperties": true
          },
          "clientInfo": {
            "$ref": "#/components/schemas/McpClientInfo"
          }
        }
      },
      "McpClientInfo": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "version"],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          }
        }
      },
      "McpToolsListParams": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "cursor": {
            "type": "string",
            "maxLength": 256
          }
        }
      },
      "McpToolsCallParams": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name"],
        "properties": {
          "name": {
            "type": "string",
            "enum": [
              "get_dealership_profile",
              "search_inventory",
              "get_vehicle",
              "list_leads",
              "get_lead",
              "list_test_drives",
              "get_dealership_insights"
            ]
          },
          "arguments": {
            "type": "object",
            "additionalProperties": true,
            "description": "Tool-specific arguments. The available fields and limits are returned by tools/list and are constrained by the credential scopes."
          }
        }
      },
      "McpJsonRpcResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/McpJsonRpcSuccessResponse"
          },
          {
            "$ref": "#/components/schemas/McpJsonRpcErrorResponse"
          }
        ]
      },
      "McpJsonRpcSuccessResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["jsonrpc", "id", "result"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "$ref": "#/components/schemas/McpResult"
          }
        }
      },
      "McpJsonRpcErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["jsonrpc", "id", "error"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "$ref": "#/components/schemas/McpRpcError"
          }
        }
      },
      "McpRpcError": {
        "type": "object",
        "additionalProperties": false,
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "integer",
            "description": "JSON-RPC protocol error code."
          },
          "message": {
            "type": "string",
            "minLength": 1
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional safe diagnostic data. Tokens, VINs, database values, and request bodies are never included."
          }
        }
      },
      "McpResult": {
        "type": "object",
        "description": "MCP result. Tool output contains structuredContent and/or content; fields vary by the authorized tool.",
        "additionalProperties": true,
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/McpContentBlock"
            }
          },
          "structuredContent": {
            "type": "object",
            "additionalProperties": true
          },
          "isError": {
            "type": "boolean"
          }
        }
      },
      "McpContentBlock": {
        "type": "object",
        "additionalProperties": true,
        "required": ["type"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["text", "image", "resource", "resource_link"]
          },
          "text": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          }
        }
      }
    }
  }
}
